I want to make jquery plugin to process form submit before ajax.
This is my jquery script
;(function($,window,document,undefined){
"use strict";
$.modalLoad = function(element, options){
var plugin = this;
var $element = $(element),
element = element,
url = $element.attr('href'),
target = $element.data('target');
var defaults = {
form: $(this).serializeArray(),
};
plugin.init = function(context){
plugin.settings = $.extend({},defaults, options);
plugin.add_bindings();
plugin.create_ajax(context);
}
plugin.create_ajax = function(context){
$('form',context).addClass('modal-form');
$('.modal-form',context).on('submit',function(e){
e.preventDefault();
plugin.post_data($(this),context);
});
}
plugin.post_data = function(form,context){
var loaded = false;
var throbbed = false;
var _fd = new FormData();
var password = hex_sha512($('input[type="password"]',context).val());
_fd.append('password',password);
function checkComplete(){
if(loaded && throbbed){
$('.ajax-loader').remove();
}
}
function requestComplete(){
loaded = true;
checkComplete();
}
$.ajax({
url:form.attr('action'),
type: form.attr('method'),
data: _fd,
contentType: false,
cache: false,
processData: false,
success: function(data){
requestComplete();
console.log(data);
},
beforeSend: function(){
var loading = "<img src='images/loader.gif' class='ajax-loader'>";
$('.modal-footer',context).append(loading);
$('.ajax-loader').css({
height: '15px',
'vertical-align': 'middle',
margin: '0px 5px'
});
setTimeout(function(){
throbbed = true;
checkComplete();
},2000);
},
complete: requestComplete()
});
console.log(plugin.settings.form);
}
plugin.init();
}
$.fn.modalLoad = function(options){
return this.each(function(){
if(undefined == $(this).data('modalLoad')){
var plugin = new $.modalLoad(this, options);
$(this).data('modalLoad', plugin);
}
});
}
})(jQuery);
HTML
<div class="modal fade" id="login-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false">
<div class="modal-dialog">
<div class="modal-content">
<form action="<?php echo 'http://'.base_url('authentication.php');?>" method="POST">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Login</h4>
</div>
<div class="modal-body">
<div class="modal-space">
<label class="email">
<input type="text" name="email" value="" placeholder="Email*" data-constraints="#Required #Email" id="regula-generated-387495">
</label>
</div>
<div class="modal-space">
<label class="password">
<input type="password" name="password" value="" placeholder="Password*" data-constraints="#Required #Email" id="regula-generated-387495">
</label>
</div>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary btn-1 btn-1__mod-1" value="LOGIN">
</div>
</form>
</div>
</div>
</div>
Now, i want to encrypt password field with sha512 before it send with ajax which follow this instruction.
Actually, i serialize form data to array and i want to override password array that sets in defaults.form objects.
But even i can't fetch data from defaults.form where form data should be stored in.
Is possible if i print defaults.form in console.log? Could everyone tell me which part that i must fix? Also please tell me how to tidy up my code?
Thanks for advance
make sure in your html code, all input inside tag form. Otherwise you will get missing value from form data serialize in defaults.form. Can you show your html code here?
Related
I have been trying for some time to get this working. I am struggling to take user input from a modal and insert it into a my database in phpmyadmin. Any help would be greatly appreciated.
1) Using the select callback I bring up a modal:
select: function(start, end, allDay)
{
$('#myModal').modal('show');
},
2) The modal itself in the HTML:
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Add Event</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label for="FormControlInput1">Task Title</label>
<input type="text" class="form-control" id="title" placeholder="Enter Task Title">
</div>
<div class="form-group">
<label for="FormControlInput2">Task Number</label>
<input type="text" class="form-control" id="number" placeholder="Enter Task Number>
</div>
<div class="form-group">
<label for="FormControlInput3">Location</label>
<input type="text" class="form-control" id="location" placeholder="Enter Location">
</div>
<div class="form-group">
<label for="FormControlTextarea1">Tooling Required</label>
<textarea class="form-control" id="tooling" placeholder="Enter the tools required for the task here" rows="3"></textarea>
</div>
<div class="form-group">
<label for="FormControlTextarea2">Consumables</label>
<textarea class="form-control" id="consumables" placeholder="Enter the consumables required for the task here" rows="3"></textarea>
</div>
<div class="form-group">
<label for="FormControlSelect1">Safety Condition</label>
<select class="form-control" id="safety">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="buttonAddEvent">Add Event</button>
</div>
</div>
</div>
</div>
3) At this point I would like to use my insert.php file I have made, which works for other functions in the code:
<?php
//insert.php
$connect = new PDO('mysql:host=hostname;dbname=dbname', 'username', 'password');
if(isset($_POST["title"]))
{
$query = "
INSERT INTO events
(title, number, location, tooling, consumables, safety, start_event, end_event)
VALUES (:title, :number, :location, :tooling, :consumables, :safety, :start_event, :end_event)
";
$statement = $connect->prepare($query);
$statement->execute(
array(
':title' => $_POST['title'],
':number' => $_POST['number'],
':location' => $_POST['location'],
':tooling' => $_POST['tooling'],
':consumables' => $_POST['consumables'],
':safety' => $_POST['safety'],
':start_event' => $_POST['start'],
':end_event' => $_POST['end']
)
);
}
?>
I have typically inserted data using the following code however this uses prompts() which I want to replace with the modal inputs:
select: function(start, end, allDay)
{
var title = prompt("Enter Task Title");
if(title)
{
var number = prompt("Enter Task Number");
var location = prompt("Enter Train Location");
var tooling = prompt("Enter Tooling Required");
var consumables = prompt("Enter Consumables Required");
var start = $.fullCalendar.formatDate(start, "Y-MM-DD HH:mm:ss");
var end = $.fullCalendar.formatDate(end, "Y-MM-DD HH:mm:ss");
$.ajax({
url:"insert.php",
type:"POST",
data:{title:title, number:number, location:location, tooling:tooling, consumables:consumables, start:start, end:end},
success:function()
{
calendar.fullCalendar('refetchEvents');
}
})
}
},
Needed to make use of .on() to pass data from modal input to variables
select: function(start, end, allDay)
{
var start = $.fullCalendar.formatDate(start, "Y-MM-DD HH:mm:ss");
var end = $.fullCalendar.formatDate(end, "Y-MM-DD HH:mm:ss");
$('#myModal').modal('show')
$('#buttonAddEvent').on('click', function (){
var title = $("#myModal #title").val().trim();
var number = $("#myModal #number").val().trim();
var location = $("#myModal #location").val().trim();
var tooling = $("#myModal #tooling").val().trim();
var consumables = $("#myModal #consumables").val().trim();
var safety = $("#myModal #safety").val().trim();
var mockEvent = {title:title, number:number, location:location, tooling:tooling, consumables:consumables, safety:safety, start:start, end:end};
$('#calendar').fullCalendar('renderEvent', mockEvent);
$('#buttonAddEvent').unbind('click');
$('#myModal').modal('hide');
$.ajax({
url:"insert.php",
type:"POST",
data:{title:title, number:number, location:location, tooling:tooling, consumables:consumables, safety:safety, start:start, end:end},
success:function()
{
calendar.fullCalendar('refetchEvents');
}
});
});
},
Thanks to #ADyson for pointing in the right direction.
i 'm not seeing any return data from your php code (which is generally get newly updated record and returns as json_encode),
and then the Ajax Success Function should process the response data and fetch it to calendar
I'm currently working on a Project with Phaser.js and I'm running into a problem when working on my Highscore. When the game goes into the last state called "end", it opens a Bootstrap Modal Dialog with the achieved Score and an input where you can put your name. When I hit "send" it should put the value of both inputs into the ajaxcall and send it to "/". But the inputs end up being empty, a console.log(input1 + " and " + input2); brings out nothing but the "and". I have not a clue what the problem could be since I'm not getting ANY errors. Any help is appreciated.
index.ejs:
<div class="col-md-12" id="popup">
<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<label for="score">Your Score:</label>
<input value="" class="form-control" id="score"><br>
<label for="name">Your Name:</label>
<input value="" class="form-control" id="name" placeholder="Choose a name for the leaderboards...">
</div>
<div class="modal-footer">
<button type="button" id="send" class="btn btn-success">Send</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
ajaxcalls.js
var input1 = $('#name').val();
var input2 = $('#score').val();
$('#send').click(function(){
console.log(input1 + 'x' + input2);
$.ajax({
method: "POST",
url: "/",
data: {
Name: input1,
HScore: input2
},
success: function(data){
console.log('success');
$('#myModal').modal('hide');
}
});
});
index.js
router.post('/', function (req, res) {
var Name = req.body.Name;
var HScore = req.body.HScore;
mongoose.model('hs').create(
{
player: Name,
score: HScore
},
function (err,player) {
if(err){
res.send('Errortext!');
}
console.log('POST creating new Player: ' + player);
res.redirect('/');
});
});
mongo.js
var mongoose = require('mongoose');
var highScore = new mongoose.Schema({
player: String,
score: Number
});
mongoose.model('hs', highScore);
You just need to read values inside of click listener
$('#send').click(function(){
var input1 = $('#name').val();
var input2 = $('#score').val();
console.log(input1 + 'x' + input2);
$.ajax({
method: "POST",
url: "/",
data: {
Name: input1,
HScore: input2
},
success: function(data){
console.log('success');
$('#myModal').modal('hide');
}
});
});
I Have a change password form which I have tried to code so that it gets submitted through ajax.
I needed to do validation too.
Below is the code that I've written. Is there anyway so that we can use this js ajax function for multiple modal forms?
Or will we need to create a seperate function for submitting each modal form?
Also I wanted to make the parent page reload after user closes the modal so I have added this code:
$('#edit').on('hidden.bs.modal', function() {
location.reload();
});
but it reloads the page when someone clicks cancel button too. Is there any way to prevent reloading when clicking cancel button and only do reloading only by clicking "x".
Here is the code
index.php file where the modal is
<p data-placement="top" data-toggle="tooltip" title="Edit" data-original-title="Edit">
<button class="btn btn-primary btn-xs" data-title="Edit" data-toggle="modal" data-target="#edit" data-backdrop="static" data-keyboard="false">
<span class="glyphicon glyphicon-pencil"> Edit</span>
</button>
</p>
<div class="modal fade" id="edit" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Edit Your Detail</h4>
</div>
<!--/.modal-header-->
<div class="modal-body">
<form method="post" id="updateForm" action="update-info.php">
<input type="hidden" name="userID" value="<?php echo $_SESSION['user']; ?>" />
<div class="form-group">
<label for="customer_name">Customer Name :</label>
<input class="form-control" type="text" name="customer_name" id="customer_name" value="<?php echo $userRow['fullName']; ?>" />
</div>
<h4><u><strong>Change Password</strong></u></h4>
<div class="form-group" id="currentPass-group">
<label for="current_pass">Current Password :</label>
<input class="form-control" type="password" name="current_pass" id="current_pass">
</div>
<div class="form-group">
<label for="new_pass">New Password :</label>
<input class="form-control" type="password" name="new_pass" id="new_pass">
</div>
<div class="form-group">
<label for="confirm_pass">Confirm Password :</label>
<input class="form-control" type="password" name="confirm_pass" id="confirm_pass">
</div>
<div class="modal-footer">
<!-- <input type="submit" name="submit" class="btn btn-block btn-warning" value="Save changes" /> -->
<button type="submit" name="submit" class="btn btn-success" id="submitForm" value="Save changes">Save Changes</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!--/.modal -->
custom.js file:
$('#edit').on('hidden.bs.modal', function() {
location.reload();
});
/* must apply only after HTML has loaded */
$(document).ready(function() {
$("#updateForm").on("submit", function(e) {
$(".error").hide();
var hasError = false;
var currentpass = $("#current_pass").val();
var newpass = $("#new_pass").val();
var cnfpass = $("#confirm_pass").val();
if (currentpass == '') {
$("#current_pass").after('<span class="error text-danger"><em>Please enter your current password.</em></span>');
//$('#currentPass-group').addClass('has-error'); // add the error class to show red input
//$('#current_pass').append('<div class="help-block">Please enter your current password.</div>'); // add the actual error message under our input
hasError = true;
} else if (newpass == '') {
$("#new_pass").after('<span class="error text-danger"><em>Please enter a password.</em></span>');
hasError = true;
} else if (cnfpass == '') {
$("#confirm_pass").after('<span class="error text-danger"><em>Please re-enter your password.</em></span>');
hasError = true;
} else if (newpass != cnfpass) {
$("#confirm_pass").after('<span class="error text-danger"><em>Passwords do not match.</em></span>');
hasError = true;
}
if (hasError == true) {
return false;
}
if (hasError == false) {
var postData = $(this).serializeArray();
var formURL = $(this).attr("action");
$.ajax({
url: formURL,
type: "POST",
data: postData,
success: function(data, textStatus, jqXHR) {
$('#edit .modal-header .modal-title').html("Result");
$('#edit .modal-body').html(data);
$("#submitForm").remove();
//document.location.reload();
},
error: function(jqXHR, status, error) {
console.log(status + ": " + error);
}
});
e.preventDefault();
}
});
$("#submitForm").on('click', function() {
$("#updateForm").submit();
});
});
update-info.php
To use this code for multiple form add ajax code in one function and call that function whenever you want to.
To prevent page from reloading when someone click on cancel
Instead of using
$('#edit').on('hidden.bs.modal', function () {
location.reload();
});
Add one click event on cross and then reload page by location.reload();
You can use e.preventDefault(); and instead of submit use click event
$("#submitForm").on("click", function(e) {
e.preventDefault();
I am trying to edit user data but when I click on user id, radio button is not selected as per it's value.
result.IsActive returns true or false.
I also try to set result.IsActive(true) by default in ajax response but it does't work.
Where I am going wrong?
Thanks in Advance
var self = this;
self.DealerId = ko.observable();
self.DealerName = ko.observable();
self.Gender = ko.observable();
self.Dealers = ko.observableArray(vm.Dealers());
$.ajax({
url: '#Url.Action("EditDealer", "Dealer")',
cache: false,
type: 'GET',
contentType: 'application/json',
data: { 'id': id },
success: function (result) {
self.DealerId(result.DealerId);
self.DealerName(result.DealerName);
self.IsActive = ko.observable(result.IsActive);
$('#basic').modal('show');
}
});
<div class="modal fade" id="basic" tabindex="-1" role="basic" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header" style="background-color:#4d90fe;padding-top:10px;padding-bottom:10px">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"></button>
<h4 class="modal-title" style="color:white">Update Dealer Information</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="control-label col-md-3">Dealer Name</label>
<div class="col-md-9">
<input class="form-control" data-bind="value:DealerName" required="required"
data-parsley-required-message="Dealer name is required"></input>
</div>
</div>
</div>
</div>
<div class="row" style="margin-top:10px">
<div class="col-md-12">
<div class="form-group">
<label class="control-label col-md-3">Dealer Status</label>
<div class="col-md-9">
<label style="padding-left:0"><input type="radio" name="status" value="true" data-bind="checked: IsActive">Active</label>
<label ><input type="radio" name="status" value="false" data-bind="checked: IsActive">Inactive</label>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer" style="margin-top:0;padding-top:10px;padding-bottom:10px">
<button type="button" id="cancelSave" class="btn default" data-dismiss="modal" >Cancel</button>
<button type="button" id="save" class="btn blue">Save</button>
</div>
</div>
</div>
</div>
It seems, like you are initializing the property self.IsActive of your ko-viewmodel in ajax-success callback. That means, that your observable IsActive property will be created only when ajax is completed. But ajax call is asynchronous. So, if you are binding the viewmodel without the instantiated self.IsActive property you will got an error from ko. (check the browsers console). Its not a good way to make ajax-calls in viewmodel constructor.
Try to declare the property before the ajax like this:
var self = this;
self.DealerId = ko.observable();
self.DealerName = ko.observable();
self.Gender = ko.observable();
self.Dealers = ko.observableArray(vm.Dealers());
self.IsActive = ko.observable(false);
$.ajax({
url: '#Url.Action("EditDealer", "Dealer")',
cache: false,
type: 'GET',
contentType: 'application/json',
data: { 'id': id },
success: function (result) {
self.DealerId(result.DealerId);
self.DealerName(result.DealerName);
self.IsActive(result.IsActive);
$('#basic').modal('show');
}
});
In this case your radio will have default checked-value (be inactive), until the ajax completes. Right after ajax completes it will become the correct value. The best way to avoid this temporally data-inconsistence, is to load all the data before the viewmodel is created and pass all ajax-data as constructor argument. This approach grants, that ko-viewmodel will have actual data in the moment of binding. (something like this:
$.ajax({
url: '#Url.Action("EditDealer", "Dealer")',
cache: false,
type: 'GET',
contentType: 'application/json',
data: { 'id': id },
success: function (result) {
//create your viewmodel inside the ajax-succcess and
//populate it with data
var myViewModel = new MyViewModel(result);
//and apply ko-binding here, after creating the viemodel
$('#basic').modal('show');
}
});
function MyViewModel(ajaxData){
var self = this;
self.DealerId = ko.observable(ajaxData.DealerId);
self.DealerName = ko.observable(ajaxData.DealerId);
self.Gender = ko.observable(ajaxData.DealerName);
self.IsActive = ko.observable(ajaxData.IsActive);
self.Dealers = ko.observableArray(vm.Dealers());
}
You need to assign equal name to both your <input type="radio"> to let the browser understand that they are related.
I'm working on a website where I have implemented Bootstrap's modal component as a login form.
I have my login script working correctly (tested without the modal), however, it obviously is not able to display errors as the modal closes before any errors are displayed. My best bet to get the errors displaying is to use AJAX. I've attempted implementing AJAX into it, but seem to be failing miserably (it's not something I'm familiar with).
Here's the code I've tried so far:
index.php
<script type="text/javascript">
function login(username, password, callback) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "login.php", true);
xhr.responseType = "json";
xhr.onload = function() {
var data = xhr.response;
if (data["status"] === "failure") {
callback({
"errorCode": data["errorCode"],
"errorMessage": data["errorMessage"]
});
} else {
callback(null, data["redirect"]);
$("#error").append(errorMessage);
}
};
xhr.send(JSON.stringify({
"username": username,
"password": password
});
}
</script>
--- // ---
<div id="loginModal" class="modal fade" role="dialog">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<div class="loginForm">
<div id="error"></div>
<form id="login" action="index.php" method="post">
<div class="input-container">
<label for="username">Email or Username</label>
<input type="text" name="username" required class="form-control"/>
</div>
<div class="input-container">
<label for="password">Password</label>
<input type="password" name="password" required class="form-control"/>
</div>
<div class="input-container">
<input type="checkbox" name="remember" value="true" id="remember" />
<label for="remember">Remember me</label>
</div>
<div class="submit-container">
<button type="submit" class="btn btn-primary btn-login">SIGN IN</button>
</div>
</form>
</div>
<h2><span>or</span></h2>
<div class="social-signin">
Sign in with Facebook
Sign in with Google+
</div>
</div>
<div class="modal-footer">
<p>Need an account? Sign up here.</p>
</div>
</div>
</div>
</div>
login.php
--- // ---
login_complete($user_id);
$output = [];
$output["status"] = "success";
echo json_encode($output);
exit;
} else {
echo json_encode(array("status" => "failure", "errorCode": $result[0], "errorMessage": $ERRORMSGS[$result[0]]));
}
My question is, how can I properly implement AJAX into my Bootstrap modal login form, to successfully display error messages (such as "Incorrect username and/or password")? At the moment, no error is displayed and the user isn't authenticated (it just goes back to index.php).
Any help is greatly appreciated.
Here's something to get you started: this is basically what I use and is pretty similar to what you have. It uses ajax to send the form to login.php, which returns a json response. The magic happens in login.html and is really quite easy: just add a messages div to the modal, and then target that with jQuery to add your messages and appropriate Bootstrap alert classes.
login.html
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/r29/html5.min.js"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<button class="btn btn-primary" data-toggle="modal" data-target="#myModal">Login</button>
<div class="modal fade" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
<form id="form" role="form">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title">Login</h4>
</div>
<div class="modal-body">
<div id="messages"></div>
YOUR FORM ELEMENTS HERE
Username: <input type="text" name="username">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Login</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script src="http://code.jquery.com/jquery.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script>
$('#form').submit(function(e) {
var form = $(this);
var formdata = false;
if(window.FormData){
formdata = new FormData(form[0]);
}
var formAction = form.attr('action');
$.ajax({
type : 'POST',
url : 'login.php',
cache : false,
data : formdata ? formdata : form.serialize(),
contentType : false,
processData : false,
dataType: 'json',
success: function(response) {
//TARGET THE MESSAGES DIV IN THE MODAL
if(response.type == 'success') {
$('#messages').addClass('alert alert-success').text(response.message);
} else {
$('#messages').addClass('alert alert-danger').text(response.message);
}
}
});
e.preventDefault();
});
</script>
</body>
</html>
login.php
<?php
$success = true;
if($success == true) {
$output = json_encode(array('type'=>'success', 'message' => 'YAY'));
} else {
$output = json_encode(array('type'=>'error', 'message' => 'WHOOPS'));
}
die($output);
If you want to implement AJAX, the button which does the submission has a type of submit and fires the submit event on the form, which will not let your code even reach the function that does the AJAX call.
Instead, you could change the type of the button from submit to button, and add the following handler to trigger when the form submits:
$('#login').submit(function(){
//prepare your username, password and callback
login(username, password, callback);
});