I've written the real-time form validation necessary for my Site. It's included in my javascript/jquery.js file and does things like:
//Let user know if they've left an invalid email in the field
$signupEmail.on("blur", function() {
var form = new SignupForm($signupEmail.val());
if ( !form.isEmailEmpty() && !form.isEmailValid() ) {
form.showEmailError("Invalid email");
} else {
form.isEmailRegistered();
if (!form.emailError && form.isEmailValid()) {
form.hideEmailError();
form.showValidEmail();
}
}
});
and:
//Let user know when they've entered a valid email
$signupEmail.on("keyup", function() {
var form = new SignupForm($signupEmail.val());
var userEmail = form.userEmail();
$.post("/sitename/scripts/checkEmailAvailability.php", {"userEmail": userEmail}, function (data) {
if (form.isEmailValid() && !data) {
form.showValidEmail();
} else {
form.hideEmailError();
}
});
});
This and the rest of the code works flawlessly with my signup and contact forms.
I also have a directory called users/ with a sub-directory called account-settings/. Each page in the sub-directory contains a different form users can submit to update their account. For instance, there is an update-email.php, update-password.php, etc. These pages are loaded onto an account-settings.php page through an xmlhttprequest(). The problem I'm having is figuring out an efficient way of including the jquery real-time validation, which doesn't seem to work unless included in the xmlhttp.onreadystatechange function. As it is now, I have to include the jquery validation twice; One for the signup/contact forms and another for the account-settings forms. Please review the following code:
Site/users/account-settings/account-settings.php
//php includes
//session configurations
<div id="user-settings">
<ul>
<li>Update Email</li>
<li>Update Password</li>
<li>Update Photo</li>
<li>Manage Friends</li>
</ul>
</div>
<div id="user-settings-forms">
</div>
//php include footer
Site/javascript/jquery.js
//Show User Profile's Settings Forms
$("#user-settings li").on('click', function() {
var data = $(this).find('a').attr('href');
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
document.getElementById("user-settings-forms").innerHTML = xmlhttp.responseText;
// I'm currently duplicating all of the real-time validation here
// If I move the code anywhere else, it doesn't work
// This makes for a lot of redundancy
// I also don't know how this affects the xmlhttprequest
}
}
if (data === '#update-email') {
xmlhttp.open('POST', 'update-email.php');
} else if (data === '#update-password') {
xmlhttp.open('POST', 'update-password.php');
} else if (data === '#update-photo') {
xmlhttp.open('POST', 'update-photo.php');
} else if (data === '#manage-friends') {
xmlhttp.open('POST', 'manage-friends.php');
}
xmlhttp.send();
});
Things I've tried so far:
1. Including the necessary jquery code on the update-email.php, update-password.php pages. I thought: well, if I include the code directly on the page that would be using it, it should always work regardless of whether the page is passed through an xmlhttprequest or not. But, I was wrong. It doesn't work.
2. Remove require("templates/header") from the update-email.php, update-password.php pages. This template includes, among other things, all the links to my css and js files. I thought: maybe there is a collision of the templates happening when the page is sent through the xmlhttprequest function. It only seemed half logical since the css was still rendering without a problem but, it was worth a shot.
3. Including the javascript file asynchronously, the same way I would a Google map. I thought: since the xmlhttprequest happens asynchronously, adding the script asynchronously may be necessary. But, that didn't work either.
So, is there a more efficient way of including the jquery events handlers that belong with the page passed through an xmlhttprequest object? If this is the only way, how does it affect the xmlhttprequest? Slow it down? No change at all? Will adding too much code cause a problem with the script in any way? Thank you. I really appreciate any help you can give.
The issue is that by assigning to innerHTML on the form, you're destroying the elements you have the handlers attached to, and replacing them with new elements you don't have handlers attached to.
This is a good use case for event delegation: You hook the event on the form, not the element, but tell jQuery to only notify you of the event when it passes through a given element during the bubbling phase. So suppose your $signupEmail field has name="user-email" or some such (you haven't shown it, so I'm just picking something as an example). To handle blur on it:
$("#user-settings-forms").on("blur", "input[name=user-email]", function() {
/// Your validation logic here, this will refer to the user-email field
});
jQuery makes events like blur and focus bubble even on browsers where they don't natively.
More about event delegation in the .on documentation.
The above hooks up specifically the user-settings-forms element, but you could use a common class on both forms to avoid making it specific like that, so you can include your validation script on both pages without modification.
Here's an example using a .user-form-validate class:
$(".user-form-validate").on("blur keyup", "input[name=user-email]", function(e) {
var $this = $(this),
$validation = $this.closest("label").next(".validation-error");
if (!$.trim($this.val())) {
if (e.type === "blur" || e.type === "focusout") {
$validation.text("Please fill in an email address").fadeIn();
}
} else {
$validation.fadeOut();
}
});
.validation-error {
color: #a00;
}
<form class="user-form-validate">
<label>Email address:
<input type="text" name="user-email">
</label>
<p class="validation-error" style="display: none"></p>
<div>
<input type="button" value="Fake Send Button">
</div>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Related
I have an problem with my site when I want to change the css style from the JavaScript it works but only for few seconds.
function validateForm() {
var fname = document.getElementById('<%=UserFnameTextBox.ClientID%>');
if (fname.value == "") {
document.getElementById("WarnUserFnameTextBox").style.opacity = 1;
document.getElementById('<%=UserFnameTextBox.ClientID%>').style.borderColor = "red";
getElementById('<%=UserFnameTextBox.ClientID%>').focus;
}
}
I'm using also Asp.net, that's why I wrote the ID like this
I want that the JS will save the style for as long that the user enter the textbox.
Multiple things here: I suggest that your validateForm() function triggers in an onClick on your submit-button, right? Does your button look somewhat like this?
<input type="submit" value="submit" onClick="validateForm()">
If this is the case, the reason why your styles work only for few seconds is simply that the website reloads. The styles are in effect, but the form is also triggering and send to the site, which you added in your <form action>. After reloading, the website will fall back to its default style, as if the errors never occured... which is correct on that instance of the site.
If you want to have it permanent, you have to disable the submit-button as long as there are invalid fields. You can make use of the required attribute for form elements as well, since the form won't submit as long as there are invalid fields. These can be styled as well.
Have a look at these CSS rules for that:
/* style all elements with a required attribute */
:required {
background: red;
}
You can make use of jQuery as well and disable the form-submit with preventDefault. You can take care of every style and adjust accordingly, as long as there empty / non-valid characters in your input-fields. I suggest combining this with the onKeyUp-function. This way you check everytime the users releases a key and can react as soon as your input is valid.
As an example with jQuery:
var $fname = $('#<%=UserFnameTextBox.ClientID%>');
var $textBox = $('#WarnUserFnameTextBox');
$fname.on("input", function() {
var $this = $(this);
if($this.val() == "") {
$textBox.show();
$this.focus().css("border", "1px solid red");
}
});
(thanks for pointing out my errors and optimizing the code, #mplungjan!).
To "disable" the actual form-submission, refer to this answer:
https://stackoverflow.com/a/6462306/3372043
$("#yourFormID").submit(function(e){
return false;
});
This is untested, feel free to point out my mistake, since I can't check it right now. You can play around on how you want to approach your "errorhandling", maybe switch to onKeyDown() or change(), that kind of depends on your needs / usecase.
Since your question isn't tagged with jQuery, have a look at this answer given by mplungjan as well, since it uses native JS without any framework.
https://stackoverflow.com/a/53777747/3372043
This is likely what you want. It will stop the form from being submitted and is reusing the field and resetting if no error
It assumes <form id="myForm"
window.addEventListener("load", function() {
document.getElementById("myForm").addEventListener("submit", function(e) {
var field = document.getElementById('<%=UserFnameTextBox.ClientID%>');
var error = field.value.trim() === "";
document.getElementById("WarnUserFnameTextBox").style.opacity = error ? "1" : "0"; // or style.display=error?"block":"none";
field.style.borderColor = error ? "red" : "black"; // reset if no error
if (error) {
field.focus();
e.preventDefault();
}
});
});
I'm developing a custom ordering process and I'm using AJAX requests and dynamic forms a lot to complete parts of the ordering process, but I'd like to cleanup the way I'm doing it into terms of the HTML. I'm using jQuery too.
In looking at applications like Google's word processor, I can see that both the DOM and source exhibit no javascript event attributes. For example:
<div id="docs-file-menu" role="menuitem" class="menu-button goog-control goog-inline-block" aria-disabled="false" aria-expanded="false" aria-haspopup="true" style="-webkit-user-select: none;">File</div>
My guess is that a script is registering Javascript events after the fact based on the HTML attributes.
My website is much less complex, but I was wondering how to approach this as I currently have button styled <a><img></a> tags (or similar) that call Javascript functions, which works fine, but seems like the lesser (and old school) approach. For example:
<a href="javascript:Customisation.beginNewPair()">
<img src="images/begin-new.gif" />
</a>
Here is a simple example on how to use data attributes and an eventListener on click:
var a = document.getElementById('docs-file-menu');
a.addEventListener('click', test);
function test () {
var dis = a.getAttribute('aria-disabled');
var exp = a.getAttribute('aria-expanded');
var has = a.getAttribute('aria-haspopup');
if (dis == 'true') {
alert('disabled = true');
}
if (exp == 'true') {
alert('expanded = true');
}
if (has == 'true') {
alert('haspopup = true');
}
}
You also could access the different data attributes on page load and, according to them, you could be running different functions.
Here's a simple DEMO with onclick event, simply click on File
What you want is addEventListener.
How you access the elements is another question, but say you want an alert every time somebody clicks on a box.
var box = document.getElementById('box');
box.addEventListener('click', function(){ alert(); });
<div id="box" style="width:150px;height:150px;background:blue;"></div>
You can also put what happens in a real function:
function doSomething(){
alert();
}
var box = document.getElementById('box');
box.addEventListener('click', doSomething);
<div id="box" style="width:150px;height:150px;background:blue;"></div>
Can someone explain to me what i am doing wrong in this code?
http://jsfiddle.net/14njfqef/
var isLoggedIn = function(state){
if(state == true) {
$("#content-container").show();
$("#account2").show();
$("#account").hide();
}
else(state == false){
$("#content-container").hide();
$("#account2").hide();
$("#account").show();
}
}
onload=function() {
isLoggedIn(false);
}
On load i want the divs to hide but then when i click the button i want the divs to show?
Is the boolean function set out in the correct way?
Piece below tries to re-arrange piece at OP. onload not appear clearly defined , not addressed , though could be attached to an event , i.e.g., window.onload = onload . Wrapped blocks in jquery .ready() event . Removed js onclick markup from html , included at script element , or loaded from file at jquery .on("click") event . Added strict comparison operator === (an added =) to if / else if statements. Changed input type to button. Added if to else portion of composition (see link posted at comments by Felix Kling).
Try
$(function() {
var isLoggedIn = function(state){
if(state === true) {
$("#content-container").show();
$("#account2").show();
$("#account").hide();
}
else if(state === false){
$("#content-container").hide();
$("#account2").hide();
$("#account").show();
}
};
isLoggedIn(false);
$("input[type=button]").click(function() {
isLoggedIn(true)
})
});
jsfiddle http://jsfiddle.net/guest271314/14njfqef/3/
changed your html to
<input type="submit" value="Boolean" id="toggle"/>
rewrote your js as
// JQuery run at start effectivly
$(document).ready(function() {
function isLoggedIn(state) {
if(state == true) {
$("#content-container").show();
$("#account2").show();
$("#account").hide();
}
else {
$("#content-container").hide();
$("#account2").hide();
$("#account").show();
}
}
// JQuery attaching a click event using an anonymous function
// and hard coding your isLoggedIn to true, passing variables is a bit more complicated.
$('#toggle').click(function() {isLoggedIn(true)});
isLoggedIn(false);
})
Well there's a few things I am not sure if you are aware of so I feel there's some responsibility on my end to make sure they are mentioned. They are a number of syntactical errors in your post that are stopping this from working so instead of addressing them I feel its necessary to update your view on what JQuery you are using as well as your selector choice.
First I would add a class structure to all of the div's to target them all at once so you can save on some lines of code. In production it's always better to have less code for all of your visitors to download because even a little bit of code can get out of control after enough hits on a webpage. Having to serve it kills speed and so does having to process three separate jquery selections as opposed to one.
I would change the HTML to...
<body>
<div id='content-container' class='boxes'>
Content Container
</div>
<div id='account' class='boxes'>
account
</div>
<div id='account2' class='boxes'>
account2
</div>
<input id="validateButton" type="submit" value="Boolean">
</body>
This way you can simply target all divs with $(".boxes"); ... I wouldn't recommend getting into the habbit of using $("div");
Next I would change the JQuery to being more JQuery friendly code. Its not always useful to use an onload event from pure Javascript to handle JQuery driven functions in correct time to the loading of DOM objects. Therefore you should use $( document ).ready( handler ) to handle this load event properly just in case it causes you problems down the road. The more common shorthand of this ready event is a simple $(function() { }); wrapper.
The rest of the code can be re-arranged to this....
var isLoggedIn = false; //<--Instantiate to false, make global to window level scope
//Load event Corrected For JQuery
$(function() {
$(".boxes").hide(); //<--Hide on load
//Add A Proper Updated Click Event To Button
$("#validateButton").click(function() {
isLoggedIn = true; //<--Should include real functionality not hand coded to true
checkLoginAndRespond(); //<--Validate Login Status
});
});
function checkLoginAndRespond() {
//If Logged, Show
if(isLoggedIn) {
$(".boxes").show();
//Else Don't
} else { $(".boxes").hide(); }
} //end function
Lastly, the version. New versions of JQuery have not been released for some time and seem to not be in the making so its a safe bet to use their most recent versions as it has thousands of pages of help for its syntax and it's very stable. I would recommend anything in the 2.0 or higher series JQuery.
I am assuming you have JQuery library loaded. Try
if (state) {
$("#content-container").show();
$("#account2").show();
$("#account").hide();
}
else{
$("#content-container").hide();
$("#account2").hide();
$("#account").show();
}
to solve your problem.
I am making a text adventure game, which would require user input in the form of a element in html, which would send the user input to JavaScript using the click function:
<!-- HTML CODE -->
<div class="game">
<div id="gamebox">
<a name="game"></a>
<!-- Javascript writes to here (if it works :( ) -->
</div>
<div id="inputbox">
<input type="text" id="userinput" placeholder="Input" value="" />
Go!
</div>
</div>
As you can see above, I have a element and a "Go!" button, which sends it to my JavaScript code. In JavaScript, first I define 3 variables where I would output my text.
//JavaScript Code
var txt_input = $("#userinput");
var btn_quest = $("#btn-quest");
I would than define 2 other functions, which allows me to write into the . I would than have other functions, which are for the storyline of the text adventure game. However, the root of the problem is that I can't seem to progress past the second event. Here are my events:
function wakeUp() {
displayGame("You wake up, at stackoverflow. West or east? [Choose 'west' or 'east']");
btn_quest.on({
"click": function() {
// Begin input preproccessing
var input = txt_input.val().toLowerCase();
// If/else block for choice here
if (input === "west") {
//Paste btn_quest here for new event
goWest();
} else if (input === "east") {
//Paste btn_quest here for new event
goEast();
} else {
//Error handler - do not modify
txt_input.val("Error - enter a valid choice");
}
//End of if else block body
}
});
The first event function would work perfectly, and write to my html, and accept the first user choice. However, at the next event, no matter what it is, (goEast() or goWest()), my program aways displays "Error - enter a valid choice"). Right now, my hypothesis is that the "switch" function isn't working correctly. However, I honestly don't know. What is the issue here, and how can I fix it? The other event functions (etc goEast) are exactly the same as the wakeUp function, except with different displayGame() strings and link to other event functions.
I have not included the full code, in order to keep my code short - but here is the full html/css/javascript if needed: http://plnkr.co/edit/55heHh4k5QEIVYdBrWGB?p=preview
Edit: I tried to implement the suggestion, like this: But It seems that JavaScript doesn't even get the userinput anymore. When I try to submit the user's response, nothing happens. What went wrong? I did the same thing here with all of my functions in the game:
function wakeUp() {
displayGame("You wake up at stackoverflow again, but it didn't work. Go West or east again?");
// btn_quest.off("click").on("click",function()){
btn_quest.off("click").on;
"click", function() {
// Begin input preproccessing
var input = txt_input.val().toLowerCase();
// If/else block for choice here
if (input === "walk") {
//Paste btn_quest here for new event
walkToWork();
} else if (input === "bus") {
//Paste btn_quest here for new event
busToWork();
} else {
//Error handler - do not modify
txt_input.val("Error - enter a valid choice");
}
//End of if else block body
};
//End of function. Copy until line under this comment V
}
What did I do wrong? Can you please show a example using this function?
You need to look at all the code to see the problem. The reason is because you keep binding to the element so multiple click events are being triggered. You need to remove the last click
btn_quest.off("click").on("click",function(){});
I have a basic form popup that will display when the button buy now of the main product is clicked with this code: onclick="productAddToCartForm.submit(this)"
and i have related products too in the same page with this main product with exactly the same button, and i want this pop up to be displayed also when it's clicked, and i tried to add onclick="productAddToCartForm.submit(this)" to it too but if i push it the pop up WILL work but will add to the CART both products.
how can i do this?
the code looks like this:
<div style="display: none;" id="ajax-popup">
<span class="button b-close"><span>X</span></span>
<h2 id="ajax-popup-message"></h2>
<div id="ajax-popup-content"></div>
</div>
<script type="text/javascript">
//<![CDATA[
var productAddToCartForm = new VarienForm('product_addtocart_form');
productAddToCartForm.submit = function(button, url) {
if (this.validator.validate()) {
var form = this.form;
var oldUrl = form.action;
if (url) {
form.action = url;
}
var e = null;
// Start of our new ajax code
if (!url) {
url = jQuery('#product_addtocart_form').attr('action');
}
url = url.replace("checkout/cart","ajax/index"); // New Code
var data = jQuery('#product_addtocart_form').serialize();
data += '&isAjax=1';
jQuery('#ajax_loader').show();
try {
jQuery.ajax( {
url : url,
dataType : 'json',
type : 'post',
data : data,
success : function(data) {
jQuery('#ajax_loader').hide();
//alert(data.status + ": " + data.message);
jQuery('#ajax-popup-message').addClass(data.status);
if(jQuery('#ajax-popup')){
jQuery('#ajax-popup-message').html(data.message);
}
if(jQuery('#ajax-popup')){
jQuery('#ajax-popup-content').html(data.sidebar);
}
if(jQuery('.header .links')){
jQuery('.header .links').replaceWith(data.toplink);
}
jQuery('#ajax-popup').bPopup();
}
});
} catch (e) {
}
// End of our new ajax code
this.form.action = oldUrl;
if (e) {
throw e;
}
}
}.bind(productAddToCartForm);
productAddToCartForm.submitLight = function(button, url){
if(this.validator) {
var nv = Validation.methods;
delete Validation.methods['required-entry'];
delete Validation.methods['validate-one-required'];
delete Validation.methods['validate-one-required-by-name'];
// Remove custom datetime validators
for (var methodName in Validation.methods) {
if (methodName.match(/^validate-datetime-.*/i)) {
delete Validation.methods[methodName];
}
}
if (this.validator.validate()) {
if (url) {
this.form.action = url;
}
this.form.submit();
}
Object.extend(Validation.methods, nv);
}
}.bind(productAddToCartForm);
//]]>
</script>
HTML looks like this:
<div class="main">
<div class="first">
<div class="add-to-cart">
<img onclick="productAddToCartForm.submit(this)" title="Add to Cart" src="../images/add-to-cart.png">
</div></div>
//STUFF
<div class="second">
<button onclick="window.location='URL'; productAddToCartForm.submit(this)" class="form-button add-to-cart" type="button"></button></div>
</div>
The root of your issue is, from what I can see from your example, that you are calling the form submission function twice. It appears that the second onclick had debug code with the window.location left in it when you pasted it here, of which is, what I can only determine from your description, the popup window markup that causes an endless loop of submitting items to the cart.
Firstly you're using jQuery to make programming with Javascript easier, get rid of the onclick= DHTML events in your html and use jQuery.
then add
jQuery(document).ready(function(){
jQuery('.add-to-cart').click(function(e){
e.preventDefault();
productAddToCartForm.submit(this);
});
});
Secondly there's no reason to wrap jQuery.ajax in a try catch, it has it's own error processing functionality. Unless you believe something would be wrong with jQuery's ajax function. Otherwise if you are trying to catch errors within the success method, you need to place the code inside the success method.
Think of ajax as a completely separate browser being opened up the instant it is executed.
Here's an example of what I am referring to: http://jsfiddle.net/73gpC/1/
Here's an example of an error method:
jQuery.ajax({
error: function(jqXHR, text, errorThrown){
if(errorThrown){
alert('Error: ' + errorThrown);
}
}
});
Next you have already declared the form with var form = this.form;, why search the DOM for it again?
jQuery('#product_addtocart_form').serialize();
should be form.serialize();
Every time you execute jQuery('selector'), jQuery "searches" for the element within the DOM.
While it sounds okay at first, as you begin dealing with more complex applications it is extremely slow to do things this way while the user interacts with your application.
It is much faster to use the declared variable instead since you already found it. With that said always favor ID's over class names as they are much faster to find but require valid HTML (ID's are unique and can not be reused).
From the look of it <button onclick="window.location='URL'; productAddToCartForm.submit(this)" is just completely broken and you are expecting it do something it simply won't because window.location='URL' is going to redirect the users browser to 'URL' when they click it and productAddToCartForm.submit(this) will never execute.
Example: http://jsfiddle.net/CZqDL/
No alert box will be displayed on click, indicating the function never fired.
I am all for helping someone learn how to figure out an issue if I am able, but this is really beyond your experience level with Javascript or jQuery in general.
I suggest getting a jQuery programming book or hiring a developer to program it correctly.
Especially seeing as how VarienForm is a part of Magento, which should be listed in your tags, which is an eCommerce application.
If you're just learning I suggest reaching out on the jQuery or Magento forums on how to use the applications or possibly for training.
Otherwise you will lose customers, get incorrect orders, or possibly be sued or arrested (depending on if you are processing credit cards) should your form mess up due to poor programming practices.
There are many websites where you can hire a freelancer to do just what you need for very low costs and avoid the hassles.