jQuery Loan Calculator – Impromptu Style
04 Mar
Posted by: trent in: Impromptu, Javascript, Programming
I’ve developed a few real estate websites in the past and one common request is a loan calculator. I’ve put together an example of a simple loan calculator using Impromptu with states. It also makes use of form fields, submit functions and demonstrates how to validate and show errors, so its a little more detailed example of using a form. I’ve designed it where you can call a function with optional parameters to default the amount, years, or interest rate. Take a peak:
To use this puppy first copy this javascript function into your code:
function openLoanCalculatorPrompt(o){
o = jQuery.extend({},{ amount:100000, years:15, rate:5 },o);
var formstr = '<p>Calculate monthly payments:</p>'+
'<div class="field"><label for="intamount">Amount</label><input type="text" name="intamount" id="intamount" value="'+ o.amount +'" /></div>'+
'<div class="field"><label for="intyears">Years</label><input type="text" name="intyears" id="intyears" value="'+ o.years +'" /></div>'+
'<div class="field"><label for="intrate">Rate</label><input type="text" name="intrate" id="intrate" value="'+ o.rate +'" /></div>';
jqistates = {
state0: {
html: formstr,
focus: 1,
buttons: { Cancel: false, Calculate: true },
submit: function(v, m, f){
var e = "";
m.find('.errorBlock').hide('fast',function(){ jQuery(this).remove(); });
if (v) {
if(isNaN(f.intamount))
e += "Please enter a numeric amount<br />";
if(isNaN(f.intyears))
e += "Please enter a numeric number of years<br />";
if(isNaN(f.intrate))
e += "Please enter a numeric interest rate<br />";
if (e == "") {
var interest = f.intrate/100;
var years = f.intyears;
var amount = f.intamount;
var n = years * 12;
var i = interest / 12;
var i_to_n = Math.pow((i + 1), n);
var p = amount * ((i * i_to_n) / (i_to_n - 1));
var m = Math.round(p * 100) / 100;
jQuery('#intmonthlypayment').text(m);
jQuery.ImpromptuGoToState('state1');
}
else{
jQuery('<div class="errorBlock" style="display: none;">'+ e +'</div>').prependTo(m).show('slow');
}
return false;
}
else return true;
}
},
state1: {
html: 'Monthly Payment: $<span id="intmonthlypayment"></span>',
focus: 1,
buttons: { Back: false, Done: true },
submit: function(v,m,f){
if(v)
return true;
jQuery.ImpromptuGoToState('state0');
return false;
}
}
};
$.prompt(jqistates);
}
First in this function you’ll see I check for parameters, and default them if they’re not present. Then we build our form, just three fields. Then we build our states. Once valid numbers are submitted we calculate the monthly payment, populate the result in “state1″, then go to “state1″. Since the parameters are all optional you can easily customize values on the fly. You know how this works…
// use all options
openLoanCalculatorPrompt({ amount:150000, years:30, rate:5.25 });
// just one option
openLoanCalculatorPrompt({ amount:150000 });
// use defaults
openLoanCalculatorPrompt();
Thats all there is to it. Use it how you like, although use at your own risk, I am not a finance guru by any means! You can find the full working loan calculator here.
Related posts:




19 Responses
Kfir Gollan
10|Mar|2009I’m not sure if this is the best place to post this but I’ll post it here anyway..
I’ve encountered a minor bug with the positioning on IE. Instead of setting the position to the middle like so
jqi.css({ position: “absolute”, top: o.top, left: “50%”, marginLeft: ((jqi.outerWidth()/2)*-1) });
we can just put all that we need into the left property and avoid this bug
jqi.css({ position: “absolute”, top: o.top, left: Math.ceil((w.width() – jqi.outerWidth())/2) });
It would also be nice to enable “middle” for the top and left properties.
var jqi_top, jqi_left;
if(o.top === “middle”)
jqi_top = Math.ceil((w.height() – jqi.outerHeight()) / 2);
else
jqi_top = o.top;
if(o.left === “middle”)
jqi_left = Math.ceil((w.width() – jqi.outerWidth())/2);
else
jqi_left = o.left;
jqi.css({ position: “absolute”, top: jqi_top, left: jqi_left });
trent
10|Mar|2009You found the right place. The positioning of the prompt has been a big topic lately. I was going to post over the next day or so asking opinions on how developers thought Impromptu should be positioned, as far as scrolling/fixed, etc.. currently Impromptu is set to position: fixed; which with large prompts creates an issue with accessing the entire prompt if it flows off the screen.
The other option is to have the overlay fade cover the entire document but have the prompt stationary, so you can scroll to view the entire prompt, but with that the prompt could be scrolled off the screen.
Taking this into consideration what are your thoughts? Within the next few days I want to make a decision and try to get something in place. Thanks also for reporting your findings!
Kfir Gollan
10|Mar|2009well I really dont see the point in having a prompt bigger than the screen size…
Instead I think it’ll be better to add a scrollable option if the prompt is bigger than page.
Here is a link to a scrollable plugin for jQuery:
http://flowplayer.org/tools/scrollable.html
Another thing that could be nice is if you would wrap all of the Impromptu methods and objects inside one sub object of jQuery like $.impromptu.prompt(“Hello!”);
Hugo
12|Feb|2010I think that your plugin is one of the best but has a major problem. It forces you to mix UI code with function code. I really don’t understand why you didn’t follow the approach of loading content from an existing container like a div. I know we can load from external html, but that forces you to have a lot of files just for one form. Is there any way of loading content the way I explained? For instance, using Facebox, i can show a popup with the contents of a div just by using jQuery.facebox({ div: ‘#NewUserForm’ }).
trent
12|Feb|2010Hey Hugo, I understand your concern. I guess the origins of this plugin weren’t to be able to handle forms, it was mainly to replace the alert and confirm to something more attractive. Over time it evolved into a tool for handling forms. Would something like $.prompt($(‘#myform’).html()); work for you? I think the only issue you will end up seeing there are having forms with submit buttons, then impromptu has it’s own set of submit buttons. Also if you have forms with events tied to it before it is copied over to the prompt.
Probably the more ideal solution would add a function like $(‘#myform’).prompt(options); I will put some thought towards how to approach this, although I haven’t had many requests for it, but I see how it could improve usability in case the user has an incapable browser. Thanks for the feedback!
Markis
11|Apr|2010Hi Trent,
Thanks for the plugin — certainly a great tool for everyone, and wonderfully well supported. I also appreciate your patience and friendly manner towards everyone who asks questions about it!
I’m trying to use Impromptu in kind of a weird way (to show a larger version of a photograph on my photography site), and I’m running into the problem where the prompt runs off the page and it inaccessible. Is there a way to set the prompt to scroll with the page?
I know this isn’t really what you had in mind when you wrote it, but I like Impromptu, and I’ve used it before (q-cogo.com), so I thought I’d ask!
Thanks again for your awesome plugin and all your hard work!
trent
11|Apr|2010Hey Markis,
There are two approaches I guess.
1) The first is like you said to make it scroll with the page. This will need some changes in the source code. Right now the prompt and the fade are inside of what I call a “box” in the source. The box is set to the height of the window and as the window scrolls so does the box. The fix would be to make the box position absolute, and the height of the body of the page. This is all set in “var positionPrompt” function on line 162 of the latest 3.1 version. Whatever height you assign to jqib (the box) you will also want to assign to jqif (the fade). Then set jqi “top” to the window’s scroll position. (this is off the top of my head but should get you really close)
The reason for doing it the window’s height is that some older websites, or people who use a ton of aboslute position elements and some browsers acted funny. It became much easier to just create a box to cover the window viewing area.
2) This is the easy way and won’t require any changes to Impromptu, but might not be the solution you’re looking for. Just check to see if the height of the image or width is larger than the $(window).width(), $(window).height(), if it is scale it back to window height – 100 or something.
Hope that helps! I’m glad you like Impromptu, thanks for using it!
Markis
11|Apr|2010I used number 2 and it works really great! Thanks for that!
Hey, for the above URL, if you click on the title of the page (near the “…”), a prompt comes up quite nicely and smoothly. But if you click on the “+” sign below the photo, the prompt comes up kind of roughly — it loads the picture first, then pops in the margins of the holder div.
(This is in FF — other browsers load the div more smoothly).
Is it just because it’s a big div? If it makes a difference, the prompt contents in the fist div are pulled from an existing (hidden) div, while the contents of the second are generated on the fly to match the properties of the photo. Also, the first CSS has a fixed with (just holds text) and the second CSS doesn’t (hold a picture of unknown dimensions).
Thanks again!
Markis
11|Apr|2010OK, I sorted it out. Tuns out Firefox is a little hit-or-miss on all types of animations. I just set it to appear with sped set to 0 … that works nicely in all browsers.
Thanks again for a great plugin!
trent
12|Apr|2010cool, glad you got it going!
AZ
23|Apr|2010I had the same issue as Markis and used solution #1, it worked great. (I can post the code if anybody wants to see it.) Thanks trent for the solution and for the great plugin.
trent
23|Apr|2010Code is always welcome. If its not too integrated it might be a nice option to add just for this scenerio. It would also help solve a big problem with the UberUploadCropper.
http://trentrichardson.com/2010/04/12/uberuploadcropper-0-2-with-example/
I just released it and most of the common problems is dealing with large images which are bigger than the screen, this might be one possible solution. Thanks AZ!
AZ
28|Apr|2010I was working from version 1.5, so this might not match exactly with the latest version.
I added ‘enableScroll:false’ to the ImpromptuDefaults, then modified the function as below. The ‘else’ clause is the old body of the function; the ‘if’ is my changes, so that default behavior is unchanged. The height setting could maybe use some more tweaking, it leaves a little extra black space at the bottom of the page.
var positionPrompt = function(){
if(o.enableScroll) {
var wsize = getWindowSize();
var height = wsize.documentHeight();
jqib.css({ position: “absolute”, height: height, width: “100%”,
top: (ie6)? getWindowScrollOffset():0,
left: 0, right: 0, bottom: 0 });
jqif.css({ position: “absolute”, height: height, width: “100%”,
top: 0, left: 0, right: 0, bottom: 0 });
jqi.css({ position: “absolute”, top: “100px”, left: “50%”,
marginLeft: ((((jqi.css(“paddingLeft”).split(“px”)[0]*1)
+ jqi.width())/2)*-1) });
} else {
var wsize = getWindowSize();
var height = (o.position == ‘absolute’) ? wsize.documentHeight() :
wsize.height;
jqib.css({ position: (ie6 || o.position == ‘absolute’)? “absolute” : “fixed”,
height: height,
width: “100%”, top: (ie6)? getWindowScrollOffset():0,
left: 0, right: 0, bottom: 0 });
jqif.css({ position: “absolute”, height: height, width: “100%”,
top: 0, left: 0, right: 0, bottom: 0 });
jqi.css({ position: “absolute”, top: “100px”, left: “50%”,
marginLeft: ((((jqi.css(“paddingLeft”).split(“px”)[0]*1)
+ jqi.width())/2)*-1) });
}
};
trent
30|Apr|2010Thanks a ton AZ! I will at integrating this into the next version.
Car Loans
05|Apr|2011Hi, great tutorial but most loan calculators including car loans calculators would have a down payment field so it would be great to have this functionality. Car Loans calculators are probably one of the most highly searched for….
Thanks
Patrick
16|May|2011@Car Loans – Below is a version with down-payment. I made this tweak for a website I am working on and I thought I would share:
function openLoanCalculatorPrompt(o){
o = jQuery.extend({},{ amount:100000, years:15, rate:5, down:15000 },o);
var formstr = ‘Calculate monthly payments:’+
‘Amount:’+
‘Down-Payment:’+
‘Years:’+
‘Rate:’;
jqistates = {
state0: {
html: formstr,
focus: 1,
buttons: { Cancel: false, Calculate: true },
submit: function(v, m, f){
var e = “”;
m.find(‘.errorBlock’).hide(‘fast’,function(){ jQuery(this).remove(); });
if (v) {
if(isNaN(f.intamount))
e += “Please enter a numeric amount (No commas)”;
if(isNaN(f.intdown))
e += “Please enter a numeric down-payment (No commas)”;
if(isNaN(f.intyears))
e += “Please enter a numeric number of years”;
if(isNaN(f.intrate))
e += “Please enter a numeric interest rate”;
if (e == “”) {
var interest = f.intrate/100;
var years = f.intyears;
var amount = f.intamount-f.intdown;
var n = years * 12;
var i = interest / 12;
var i_to_n = Math.pow((i + 1), n);
var p = amount * ((i * i_to_n) / (i_to_n – 1));
var m = Math.round(p * 100) / 100;
jQuery.prompt.getStateContent(‘state1′).find(‘#intmonthlypayment’).text(m);
jQuery.prompt.goToState(‘state1′);
}
else{
jQuery(”+ e +”).prependTo(m).show(‘slow’);
}
return false;
}
else return true;
}
},
state1: {
html: ‘Monthly Payment: $’,
focus: 1,
buttons: { Back: false, Done: true },
submit: function(v,m,f){
if(v)
return true;
jQuery.prompt.goToState(‘state0′);
return false;
}
}
};
$.prompt(jqistates);
}
Patrick
16|May|2011Interesting. It stripped the divs out. I will post to a clipboard app if you have anyone else request this.
BTW:
Great script. Easy to implement and very effective/pleasing.
Thanks.
trent
16|May|2011Thanks Patrick, yeah, the blog sometimes will strip out some html, sorry.. Also don’t forget if interest rate is 0, I noticed I didn’t handle that situation in my original version..
trent
19|May|2011I updated the loan calculator with Patrick’s changes and posted about it here:
http://trentrichardson.com/2011/05/18/updated-jquery-impromptu-loan-calculator/