I am trying to pop up a confirmation modal when the user presses the delete button on the edit form. The modal pops up fine, but when jQuery should be submitting the form, it's not doing anything. I have delete as a type="button", because when it is of type submit the modal function does not hold up the process and it just deletes the user right away.
The HTML ...
-- EDIT --
(I added the <form> tags)
<form action="/admin/edit-user" enctype="application/x-www-form-urlencoded" method="post" name="edit_user_form" id="edit_user_form">
...
<p><input type="submit" value="Save" name="submit" id="submit"/></p>
<p><input type="submit" value="Cancel" name="cancel" id="cancel"/></p>
<p><input type="button" value="Delete User" name="delete_btn" id="delete_btn" onclick="confirmDeleteUser();"/></p>
...
</form>
...
<div id="dialog-modal" title="Confirm Delete User">
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 0 0;"></span> Are you sure you wish to delete this user?</p>
<p>To continue editing, click cancel.</p>
</div>
The Javascript:
function confirmDeleteUser()
{
$('#dialog-modal').dialog({
autoOpen: false,
width: 400,
modal: true,
resizable: false,
buttons: {
"Cancel": function() {
$(this).dialog("close");
return false;
},
"Delete User": function() {
var self = $(this);
var form = $('#edit_user_form');
tmpElm = $('<input type="hidden" />');
tmpElm.attr('name', 'delete');
tmpElm.attr('id', 'delete');
tmpElm.val(true);
tmpElm.appendTo(form);
form.submit();
return true;
}
}
});
$('#dialog-modal').dialog('open');
}
When I inspect the source, I'm seeing that the code is properly appending the new hidden element, but the submit just doesn't seem to want to fire. What step am I missing?
Try it a different way.
HTML
Your html has the following: onclick="confirmDeleteUser();"
Why? jQuery is supposed to make this easier for you, not harder.
Your HTML should be pure and not calling functions (with the exception of ultra-extreme circumstances you are very unlikely to encounter). Why not use the jQuery library to bind the event to the element, rather than mix javascript function calls into your HTML? You should be doing something like this in the <script> tags, after a document ready statement.
$("#delete_btn").click(function(e){
/*Code that runs on click of the "delete_btn" ID tag*/
});
If you're unfamiliar with jQuery selectors and events then start reading here.
You can find all the events here.
You can find all the selectors here
The other reason you should do this is in the event the document isn't correctly/fully loaded in order to prevent it from breaking on your users.
CSS
You've also done this: style="float:left; margin:0 7px 0 0;" in an HTML tag? That's evil, dude. Just evil. How am I going to maintain this code in five months?
Instead, use CSS.
In your tags, or CSS file, you need an entry such as:
.dialogAdjust {
float: left;
margin: 0 7px 0 0;
}
Then in your HTML you would say:
<span class="ui-icon ui-icon-alert dialogAdjust"></span>
And now you can tweak the thing to your heart's content. It's better if you can make the class on the dialog div, rather than individual HTML elements, and in this case you absolutely can.
JavaScript
Hokay, so, here's your function:
function confirmDeleteUser()
{
$('#dialog-modal').dialog({
autoOpen: false,
width: 400,
modal: true,
resizable: false,
buttons: {
"Cancel": function() {
$(this).dialog("close");
return false;
},
"Delete User": function() {
var self = $(this);
var form = $('#edit_user_form');
tmpElm = $('<input type="hidden" />');
tmpElm.prop('name', 'delete');
tmpElm.prop('id', 'delete');
tmpElm.val(true);
tmpElm.appendTo(form);
form.submit();
return true;
}
}
});
$('#dialog-modal').dialog('open');
}
What's going on here? First step, you should try and use a tool to measure code quality. Two popular ones are JSHint and JSLint. You don't need to follow things they say like it's the only way to write your code, but it's immensely helpful in finding bugs due to small mistakes. I like JSHint, so we're going to run it through that.
And here's the output:
Errors:
Line 17 tmpElm = $('<input type="hidden" />');
'tmpElm' is not defined.
Line 18 tmpElm.attr('name', 'delete');
'tmpElm' is not defined.
Line 19 tmpElm.attr('id', 'delete');
'tmpElm' is not defined.
Line 20 tmpElm.val(true);
'tmpElm' is not defined.
Line 21 tmpElm.appendTo(form);
'tmpElm' is not defined.
Oops. Looks like you've got an undefined variable in there, meaning it's now global. Global variables are bad, they break scope and can make your code function in strange ways.
We need to fix that. You should always declare local variables in local scope. That means putting a var tempElm; at the top of the "Delete User" function.
Do away with that function wrapper, you won't need it. Your code should create the dialog object and code when the document is done loading, and open the dialog when it's clicked. What is happening in your original code both creating the dialog and opening it every time you click that button. What's the problem with that? You keep creating the object, even though it's created. You're creating the same object again and again and again. In this implementation, you won't notice it, but your design will carry over to places it will unless you take notice of this now.
So, what does that look like? In your <head> tag you should see something like this:
<script>
/*
This makes all the code inside
run when the window is done loading,
not before, which may cause issues.
*/
$(window).load(function(){
/*
This sets up the dialog
as you've described before
*/
$('#dialog-modal').dialog({
autoOpen: false,
width: 400,
modal: true,
resizable: false,
buttons: {
"Cancel": function() {
$(this).dialog("close");
return false;
},
"Delete User": function() {
var self = $(this);
var form = $('#edit_user_form');
//We've added the var infront of tepElem
var tmpElm = $('<input type="hidden" />');
tmpElm.prop('name', 'delete');
tmpElm.prop('id', 'delete');
tmpElm.val(true);
tmpElm.appendTo(form);
form.submit();
return true;
}
}
});
/*
This is the part where I talked
about selectors and events in the HTML
*/
$("#delete_btn").click(function(e){
$('#dialog-modal').dialog('open');
});
});
</script>
When asking for help, use a tool like jsFiddle to post JavaScript in to make it easier for other people to help you.
Here's a jsFiddle of the revisions we've made so far. Spend a bit of time learning how to use it if you're doing a lot of work in JavaScript and want to test something really quickly.
Here's why I wanted you to learn jsFiddle:
You didn't give us enough code to work with successfully, thus leading to me writing this huge post about code quality and how to ask questions, doubly so when you post a bounty.
If you want help, don't make people work really hard for it. You won't get good help unless someone is totally insane.
jsFiddle requires you post actual working code (or non-working code) that lets us see if there's a problem with form.submit(), such as any strange attributes or properties on the form element, or any number of other issues that could be kicking around that you excluded.
So let's look at what's breaking your "Delete User" function.
function() {
var self = $(this);
var form = $('#edit_user_form');
tmpElm = $('<input type="hidden" />');
tmpElm.prop('name', 'delete');
tmpElm.prop('id', 'delete');
tmpElm.val(true);
tmpElm.appendTo(form);
form.submit();
return true;
}
Why have you declared self? You never use it once. Lets get rid of that.
You could use something called chaining, it's really up to you. Some people hate it.
You append a whole new input to the form for something that looks like a choice, I'm not sure this is wise. I'd suggest changing the value of a normal input, or using another pattern, this could lead to a lot of issues, but for the sake of the question I'll imagine it's done for all the right reasons. Be careful however, if someone double clicks submit, that input's in there two times.
form is a word reserved by used in the DOM, you should avoid using that one to avoid confusion between your variable and the DOM API.
Which form submission button are we clicking here? You have a lot, and jQuery isn't going to guess and hope for the best.
How forms should look:
The w3 explains what forms are and the purpose of things.
Key points:
Names are paired with values
The submit button clicked is sent, the submit buttons not clicked are not.
The DOM is can be navigated based on NAME and ID attributes
Something weird is going on in your form.
Here's a form that javascript understands how to submit:
http://jsfiddle.net/YS8uW/2/
Here's javascript attempting to submit your form (stripped down to bare-bones):
http://jsfiddle.net/LfDXh/
What's different here?
You have IDs all over the place.
You use keywords for names
Lets look at something you've done, given an ID of submit to something:
http://jsfiddle.net/fdLfC/
And what happens when we don't use that as an ID?
http://jsfiddle.net/fdLfC/1/
Ahh. So that's weird.
It's like giving it an id of submit won't let you call submit. A proper explanation is, you've re-written it because the dom did it when you assigned that ID and Name, it's trying to call the element.
You can see this if you open up a debugger or something, it gives you an alert to the effect of:
TypeError: Property 'submit' of object # is not a function
Keep away from using keywords to mean something else and you won't fall into these weird traps.
A big thank you to #MattMcDonald for linking me to this resource, which explains how to deal with, and why, NAME and ID attributes over-write the built-in HTML DOM methods.
Do the other stuff I said too. Disclaimer: Everyone's going to wage war on me saying it's not absolute that you should be doing all those things, I agree, but I think this post is long enough, and we'll all agree that doing these things is a step forward in code quality, not backwards. It's up to you at the end, but try avoiding mixing things together into a huge messy pot. Think about the execution of your code and how it's happening also.
If you are sure it appends the hidden input, then the problem must be in using duplicate ID.
The button and the hidden input have the same ID. Make them different and try again.
Dont ask me the reason why it worked, all i can tell you is after doing this and that and tearing each part of your code, finally i made it work. click below link to see the demo
http://jsfiddle.net/praveen_prasad/KaK5A/4/
The changes i made are: removed id and name attributes from submit buttons from form
Example:
<input type="submit" value="Save" name="submit" id="submit"/>
changed above to below
<input type="submit" value="Save" />
Note For JsFiddle Demo: when you will click delete user on modal, form will submit. jsfiddle will say "Error 404", as it wont find the link you are posting your form. Open firebug and see that its actually posting to correct url.
"Delete User": function() {
var self = $(this);
var form = $('#edit_user_form');
tmpElm = $('<input type="hidden" />');
tmpElm.attr('name', 'delete');
tmpElm.attr('id', 'delete');
tmpElm.val(true); // HERE ----------------
tmpElm.appendTo(form);
form.submit();
return true;
}
At the designated location, shouldn't it be :
tmpElm.value(true);
or
tmpElm.attr('value', 'true');
I find it less confusing to handle my form submits upon confirms via jQuery ajax with serialized form values. It has the added benefit of avoiding unwanted form submits from buttons inside the <form> tags. So, it would look something like this:
<form id="edit_user_form">
...
<button id="submit_btn">Submit</button><br />
<button id="cancel_btn">Cancel</button><br />
<button id="delete_btn">Delete</button>
...
</form>
And then the javascript:
$('#delete_btn').click(function() {
$('#dialog-modal').dialog({
autoOpen: false,
width: 400,
modal: true,
resizable: false,
buttons: {
"Cancel": function() {
$(this).dialog("close");
return false;
},
"Delete User": function() {
$.ajax({
url: "/admin/edit-user",
type: "POST",
data: $('#edit_user_form).serialize(),
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("An error has occurred: " + errorThrown);
},
success: function(){
//Notify of success, redirect, etc.
}
});
}
}
});
});
So, it still submits via a POST. It now can happen asynchronously (or not) You can "do things" on success without changing the page, or alternatively redirect as you might need. I use a "dispatcher" page to submit to my object oriented framework, which then returns the output back to the PHP dispatcher to be json_encoded and echoed as a string for the AJAX call to use on success. Using this pattern, I only have to have one page that spits out plain text and the rest can reside in my OO Classes, which can't be called directly by ajax without doing some serious clooging (by using xajax)
Related
I am writing a little Meteor app. There is a textarea in a form, which looks like this:
<form name="comments-form">
<label for="textarea">Comment:</label><br>
<textarea cols="40" rows="10" name="comment_textarea" class="comment_textarea">Write your comment here.</textarea><br>
<button class="btn btn-success js-add-comment">add comment</button>
</form>
In my client.js I have the following code for accessing the value of the textarea:
EVENT_HANDLED = false;
Template.website_item_details.events({
"click .js-add-comment": function(event) {
var comment_text = event.target.comment_textarea.value;
if(Meteor.user()) {
Comments.insert({
created_by: Meteor.user()._id,
text: comment_text,
website_id: this._id
});
}
return EVENT_HANDLED;
}
});
However, when I click the button to add the comment, I get the following console output:
TypeError: event.target.comment_textarea is undefined
["click .js-add-comment"]()
client.js:103
Template.prototype.events/eventMap2[k]</</<()
blaze.js:3697
Template._withTemplateInstanceFunc()
blaze.js:3671
Template.prototype.events/eventMap2[k]</<()
blaze.js:3696
attached_eventMaps/</</</<()
blaze.js:2557
Blaze._withCurrentView()
blaze.js:2211
attached_eventMaps/</</<()
blaze.js:2556
HandlerRec/this.delegatedHandler</<()
blaze.js:833
jQuery.event.dispatch()
jquery.js:4690
jQuery.event.add/elemData.handle()
This seems to be basic form handling, but somehow I can't get that text in the textarea into a variable in my javascript code. I've already tried a multitude of variants of accessing it:
document.getElementsByClass()[0].value
$('.comment_textarea').get(0).val() // there should only be one such text area anyway
event.target.comment_textarea.value;
But none of those work for me, I always get that error. It's almost like the textarea was not part of my html or there is a bug in Meteor, which prevents me from accessing textareas.
I also checked whether there are other things named comment_textarea with a fulltext search on all of my projects clientside files, but there isn't any other.
Am I simply blind and overlooking something? How do I get that text?
What's more is, that although I return false, the browser still reloads the page. Could it be related to the error happening before?
You are using the click event of the button and on that event, the textarea is not available. You need to change the event into submit form. First, put the id into your form, change the button into type submit and change the code into
"submit #your-form-id": function(event) {
event.preventDefault();
var comment_text = event.target.comment_textarea.value;
.....
}
After trying even more desperate ways to access that textarea, I think I know now what's wrong:
// var comment_text = event.target.comment_textarea.value;
// var comment_text = document.getElementByName('comment_textarea').value;
// var comment_text = document.getElementByTagName('textarea')[0].value;
// var comment_text = $('textarea').get(0).val();
// var comment_text = $('textarea').get(0).text();
var comment_text = $('textarea').get(0).value; // finally working!
So it seems that when I use jQuery, I can't use the .val() function as stated in my other answers to many other questions, but for some reason I have to treat it like a normal DOM object and use the attribute value instead of the function .val().
Maybe it's specific to the jQuery version in my Meteor app?
So I will test the following:
var comment_text = $('textarea.comment_textarea').get(0).value;
...
Yes, that also works.
Also it fixes the reload issue. I guess since there was an error, it didn't even get to return false and this is why the website reloaded.
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.
I have a form with a password entered twice. I check password complexity and consistency and display appropriate error messages into a popover attached to the INPUT field:
<a href="#" id="aIdPwd2" data-toggle="manual" data-content="The password entered does not match the one previously entered" data-placement="right" href="#" rel="popover">
<input type="password" id="iIdPwd2" class="fmt1" size="60" value=""/>
</a>
With this code:
$("#aIdPwd2").popover({content: msg});
You can chose dynamicaly the message that will be displayed. But once it has been displayed once, it will then always remain the same.
I read many articles about this popular issue and did try many things (attach 2 different popover to the same input, change the inner html in the getElementsByClassName("popover-content"), destroy and recreate the popover, ..), but without any success so far.
A solution on how to change content of a bootstrap popover that has already been displayed or any kind of work-around would be highly appreciated.
In Twitter Bootstrap 3, I just update the content and then call show. Calling of the show ensure that its resized correctly and then positioned correctly.
$(".notes").data("bs.popover").options.content="Content1";
$(".notes").popover("show");
$(".notes").data("bs.popover").options.content="Content2";
$(".notes").popover("show");
If you are using data tags to show the content then you will need to update the data tag as that takes precedence. eg.
$(".notes").attr("data-content","Content1");
$(".notes").popover("show");
$(".notes").attr("data-content","Content2");
$(".notes").popover("show");
I like the second option better coz it doesn;t access the internals by doing data(bs.popover) but the first options is much faster as it doesn't update the dom. So pick what floats your boat.
document.getElementsByClassName("popover-content")[0].innerHTML = 'something else';
sure that this doesn't work?
tried it on this page and it works as expected.
UPDATE: it will work only if the popover is visible because the element is recreated/destroyed every mouseover/mouseout event
i guess it's not the best solution, but you can do this:
var msg = 'ben123 is not a goddamn password!';
document.getElementById('password').addEventListener('mouseover', function() {
document.getElementsByClassName("popover-content")[0].innerHTML = msg;
});
and change msg when you need
The problem with solutions that rely on popover('show') is that if you do this in an event handler for the show event, you will end up with an infinite loop.
If you just want to display some content in your popover when it has already been shown, you will need to directly modify the DOM:
$("#aIdPwd2").next(".popover").find(".popover-content").html(msg);
For example, if you want a popover that will load some data from an API and display that in the popover's content on hover:
DOM:
Hover here for details
jQuery:
$("#myPopover").popover({
trigger: 'hover'
}).on('shown.bs.popover', function () {
var popover = $(this);
var contentEl = popover.next(".popover").find(".popover-content");
// Show spinner while waiting for data to be fetched
contentEl.html("<i class='fa fa-spinner fa-pulse fa-2x fa-fw'></i>");
var myParameter = popover.data('api-parameter');
$.getJSON("http://api.example.com", {
'apiParameter': myParameter
}).done(function (data) {
var result = data['apiReturnValue'];
contentEl.html(result);
}).fail(function (data) {
result = "No info found.";
contentEl.html(result);
});
});
This, of course, assumes that you trust the data supplied by api.example.com. If not, you will probably want to escape the data returned to mitigate XSS attacks.
To replace the contents of a popover on an element, first call destroy.
Tested on Bootstrap 3.1.1
$("#aIdPwd2").popover('destroy').popover({content: msg});
I'm pretty new to javascript and jquery, and have run into a problem that I have not yet found a solution for. I'll attempt to paint it in a fairly simple way.
I have a page that offers the user a few choices (its a game, so..) like attack or defend, what weapon to use. It then loads two html 's, each with a "commit" button. The commit buttons are tied to (separate) functions that pass data to ajax.
The problem I have is that I'm getting buried in nested functions. Does that make sense? My code looks something like this:
code:
$(function() {
$('#choice1').click(function() {
//do some stuff
});
$('#choice2').click(function() {
//do some stuff
});
$('#choice3').click(function() {
//do some stuff, including creating the choices below, and their submit boxes
$('#subChoice1').click(function() {
//send data with ajax to a php document. get result
//create some text on my document to display results
//create an input button, along with an id="subButton1"
});
$('#subChoice2').click(function() {
//send data with ajax to a php document. get result
//create some text on my document to display results
//create an input button, along with id="subButton1"
//(yes, feed both back to same func)
});
}); // end choice3
$('#subButton1').click(function() {
//my buttons in the subChoices do not call this function(!!??)
});
});
edit: link no longer works, sorry. And I've created a living example here.
Thanks for any tips or pointers. I'm almost certain that there is just something simple that I'm missing or unaware of that will get me on the right track.
You could always use normal named functions instead of inline anonymous ones. That might help if the mountain of functions is getting too tall.
Update:
Here's your working Case 1:
$('#button1').click(function(){
$('#div1').append('<span id="span1"><br>Alright. Button 1 worked. Here\'s another button.</br></span>');
$('#div1').append('<input type="button" value = "Button 2" id="button2"/>')
$('#button2').click(function() {
$('#div1').append('<span id="span1"><br>Hey! Button 2 worked!. Let\'s keep going.</br></span>');
$('#div1').append('<input type="button" value = "Button 3" id="button3"/>')
$('#button3').click(function() {
$('#div1').append('<span id="span1"><br>Hey! Button 3 worked!. That\'s probably enough.</br></span>');
});
});
});
What I'm proposing is to update it like this:
function button3_click() {
$('#div1').append('<span id="span1"><br>Hey! Button 3 worked!. That\'s probably enough.</br></span>');
}
function button2_click() {
$('#div1').append('<span id="span1"><br>Hey! Button 2 worked!. Let\'s keep going.</br></span>');
$('#div1').append('<input type="button" value = "Button 3" id="button3"/>');
$('#button3').click(button3_click);
}
function button1_click() {
$('#div1').append('<span id="span1"><br>Alright. Button 1 worked. Here\'s another button.</br></span>');
$('#div1').append('<input type="button" value = "Button 2" id="button2"/>')
$('#button2').click(button2_click);
}
$('#button1').click(button1_click);
That way the structure of the logic stays the same, but you can pull out the nested function definitions.
If you're consistently reusing classes or ids for the submit buttons you can leverage jQuery's live() method. It would allow you to create the bindings for $('#subChoice1') and $('#subChoice2') outside of the click handler for the parent choice, but still have them bind up properly when they're created.
Hey, I'm using a html form that is used to log people into my website, I am building it so it uses AJAX (jQuery) but I'm having some problems.
Here is the JavaScript:
function validateLoginDetails() {
$('[name=loginUser]').click(function() {
$("#mainWrap").css({ width:"600px", height:"200px" });
$("#interfaceScreen").load("modules/web/loginForm.php?username=" + encodeURIComponent(username) + "&password=" + encodeURIComponent(password));
});
}
Here is the html form:
<form id="formLogin" name="loginUser" method="post">
Username<br /><input id="username" name="username" type="text" maxlength="30" style="width:160px; border:solid 1px #444444;" /><br /><br />
Password<br /><input id="password" name="password" type="password" maxlength="50" style="width:160px; border:solid 1px #444444;" /><br /><br />
<input id="submit" type="submit" value="Play" style="width:100px; background:#FFFFFF; border:solid 1px #444444;" />
</form>
The problem is, when I submit the form it runs the code but then goes back to how it was before, this may sound weird but I can tell because I can see it changing the div size and then right after reverting back to its original size.
Any ideas?
EDIT: If I run the code with the below link for example then it works fine.
Clicky
You need to return false from your handler so that it doesn't perform the actual form post after doing the AJAX call.
Here's what I would do.
$(function() {
$('#formLogin').submit( function() {
$('#mainWrap').css( { width: '600px', height: '200px' });
$.post( 'modules/web/loginForm.php',
$(this).serialize(),
function(data) {
$('#interfaceScreen').html(data);
}
);
return false;
});
});
Note that I'm using a post to make sure that the URL (including the username and password) doesn't end up exposed in the web logs. I'm also assuming that the page containing the form was loaded via https and, thus, the post will be secured as well.
I'm pretty sure tvanfosson is on the right path. Try moving up the return false into the click function or try canceling the event.
$('[name=loginUser]').click(function() {
//do stuff
return false;
});
or
$('[name=loginUser]').click(function(e) {
e.cancel();
});
If you're dealing with a form submission, you should really opt for the .form() event handler, rather than a .click() event handler. With the former, if the form is submitted via any other methods, your checks will still run, whereas click depends on that one single element firing an action. You'll also need to return false or preventDefault() on this event, so your function actually fires correctly.
The other thing (and this may be minuscule/unimportant based on the code sampling you've provided) is that you're binding that event handler in a function that has to be called - why not load it on document ready, like so (see below)?
I'd rework your code like this, personally:
$(document).ready(function() {
$('#formLogin').submit(function() {
$("#mainWrap").css({ width:"600px", height:"200px" });
$("#interfaceScreen").load("modules/web/loginForm.php?username=" + encodeURIComponent(username) + "&password=" + encodeURIComponent(password));
return false;
});
});
First, did you confirm that your .php file is returning content and not an error? If you are inserting content (with $load), you should not trigger the CSS commands on the div until your expected content (from load) has returned successfully e.g. use callback. Also, I would suggest using .submit(), a form specific function, with a direct reference to the form tag and/or id to speed things up (not making jquery search as many things in the DOM).
< style >
.loadReg{ width:[yourBeginWidth]; height:[yourBeginHeight];}
.loadSuccess{ width:600px; height:200px;}
< / style >
function validateLoginDetails() {
$('#formLogin').submit(function() {
// using load(url,{data:toPOST},callback(if successful));
$("#interfaceScreen").load("modules/web/loginForm.php?",
{"username": encodeURIComponent(username), "password": encodeURIComponent(password)},
function(){$("#mainWrap").toggleClass('loadSuccess');}
);// end load
});// end submit
return false;
}
This could be even more efficient and less obtrusive, but wanted to leave it recognizable. The other guys are right...if your Div is returning to its original size...it is because the page is being allowed to reload...in which case your initial DIV width/height are applied by the browser...as your alternate width/height are only applied by jquery onsubmit.
To recap:
assign submit event to form directly
use $load built-in ability to pass the value pairs is object {name:val}
move CSS to unobtrusive state vs buried in code
trigger CSS if successful
stop page from reloading and resetting display