Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Sarah Bradberry
Sarah Bradberry
7,115 Points

Stop form from submitting if all fields not filled in.

I have everything working in my code so far except one thing. I would like to stop the form from submitting if all of the fields are not filled in. At the moment the alert shows, but then the form submits anyway.

I've looked online and found that you can use event.preventDefault(); to do this, however I'm already using that to make my result show on the same page.

How would I stop the form from submitting in this case?

My html

<div id="patternCreate">        

           <p itemprop="description">With only 3 measurements and a gauge swatch, you can knit any size mitts with any yarn you desire! Just </span> fill in a few measurements and clikc the &quot;Make my pattern&quot; button.
          <form id="patterninfo"> <p>Who is this pattern for?
             <input name="name">
           <p><img src="graphics/hand1.jpg" alt="Measurement chart" class="imageleft"/></p>
           <p>Measure the person who will be wearing the mitts. You will need 3 measurements:<br>
             <strong>Note for those who ususally use fractions</strong>: .25 = &frac14;, 
             .5 = &frac12; and .75 = &frac34;</p>
           <p>Would you like your pattern written in inches or cm?  
             <br>
             <input type="radio" id="inches" name="increments">
             <label for="radio">inches </label>
             <br>
             <input type="radio" id="cm" name="increments">
             <label for="radio">cm</label>
           </p>

            <p>The circumference of the hand, excluding the thumb 
            <input name="handCirc"  >
            </p>
         <br class="clear">
            <p >
             <img src="graphics/hand2.jpg" alt="Measurement chart" class="imageleft"/></p>
            <p>The circumference of the thumb,

              <input name="thumbCirc">
            </p>
            <p> The distance from the base of the thumb to the base of the base of the index finger

              <input name="thumbBase">            
            </p>

            <p>Work out your gauge by knitting a stocking stitch swatch and measuring how many sts  you get per 10 cm or 4 inches. Include the numbers after the decimal point, don't round up or down to the nearest stitch. 
              <input name="gauge">
            </p>
            <p>What size needles did you use? 
              <input name="needles">
            </p>

             <p>What yarn did you use? 
              <input name="yarn">
            </p>
            <p class="clear">
              <button id="makepattern">Make my Pattern!</button>
            </p>   
             </form> 
  </div> 

  <div id="patternResult">
  </div> 

My javascript\jQuery

function pattern () {

var yourName = $('input[name="name"]').val(),
    handCircumference = $('input[name="handCirc"]').val(),
    thumbCircumference = $('input[name="thumbCirc"]').val(),
    thumbBaseToIndex = $('input[name="thumbBase"]').val(),
    stitchesPerFourInches = $('input[name="gauge"]').val(),
    needleSize = $('input[name="needles"]').val(),
    yarnUsed = $('input[name="yarn"]').val(),
    inches = $('input[id="inches"]:checked').val("true");

var stsPerCm = parseFloat(stitchesPerFourInches)/10;


if (inches.length > 0) {
var measure = "inches",
    handInches = parseFloat(handCircumference) * 2.5,
    thumbInches = parseFloat(thumbCircumference) * 2.5,
    thumbBase = parseFloat(thumbBaseToIndex),
    palm = (Math.round(thumbBase - .5) * 2 / 2).toFixed(1);} else {
var measure = "cm",
    handInches = parseFloat(handCircumference),
    thumbInches = parseFloat(thumbCircumference),
    thumbBase = parseFloat(thumbBaseToIndex),
    palm = (Math.round(thumbBase - 1.25) * 2 / 2).toFixed(1);
}

var castOn = Math.ceil(stsPerCm * handInches);

if ((castOn % 2 == 0) === true){
var castOn = castOn;
} else {
var castOn = castOn + 1
};

var thumbStitches = Math.ceil(stsPerCm * thumbInches-2);

if ((thumbStitches % 2 != 0) === true){
var thumbStitches = thumbStitches;
} else {
var thumbStitches = thumbStitches + 1
};

if (yourName.length == 0, handCircumference.length == 0, thumbCircumference.length == 0, thumbBaseToIndex.length == 0, stitchesPerFourInches.length == 0,needleSize.length == 0, yarnUsed == 0 ) {
alert("You must fill in all fields or your pattern won't be knittable");}

return '<h2>' + yourName + '\'s Custom Fit Fingerless Mitts Pattern </h2>' +
'<p>You can create more custom fit mitt patterns at http\:\/\/goo.gl\/4uIxfx' +
'</p><p>' +
'<strong>Size\:</strong> ' + 'to fit ' + handCircumference + ' ' + measure + ' hand circumference \(excluding thumb\)' +
'</p>' +
'<h3> Materials </h3>' +
'<p>' +
'<strong>Needles\:</strong> A set of size ' + needleSize + ' double pointed needles and a set of DPNs one or two sizes smaller for the ribbing' +
'</p><p>' +
'<strong>Yarn\:</strong> ' + yarnUsed + '' + 
'</p><p>' +
'<strong>Tension\:</strong> ' + stitchesPerFourInches + ' sts per 10cm\/4\" over stocking stitch on ' + needleSize + ' needles' +
'</p>' +
'<h3> Abbreviations </h3>' + 
'<p>' +
'M1 = Make 1 stitch by putting your needle under the thread that lies between stitches, twist it (to avoid making a hole), and knit it.' +
'</p><p>' +
'P2tog = Purl 2 stitches together.' +
'</p>' +
'<h3> Pattern </h3>' +
'<p>' +
'Using smaller needles, cast on ' + 
castOn + 
' sts, and join for knitting in the round. Place a marker at the beginning of the round. ' +
'</p><p>' +
'Work 5cm or 2\" k1, p1 rib.' +
'</p><p>' +
'Change to larger needles and work 2.5cm or 1\" of stocking stitch \(knit every round\).' +
'</p><p>' + 
'Make thumb gusset as follows\:' +
'</p><p>' +
'K1, m1, k1, m1, k to end of round' +
'</p><p>' +
'Knit 1 round' +
'</p><p>' +
'K1, m1, k3, m1, k to end of round' +
'</p><p>' +
'Knit 1 round' +
'</p><p>' +
'K1, m1, k5, m1, k to end of round' +
'</p><p>' +
'Knit 1 round' +
'</p><p>' +
'Continue increasing in this manner \(working 2 more stitches between the m1\'s on every second round\) until you reach \"K1, m1, k' + 
thumbStitches + 
', m1, k to end of round' +
'</p><p>' +
'Next round\: K1, put next ' + (thumbStitches+2) + ' sts onto a holder, cast on 1 st, k to the end of the round.' + 
'</p><p>' +
'Continue working rounds in stocking stitch for ' + palm + ' ' + measure + '' +
'</p><p>' +
'Change to smaller needles and work 1.25cm or 1\/2\" in k1, p1 rib. Cast off neatly in rib.' +
'</p><p>' +
'<strong>Thumb</strong>' +
'</p><p>' +
'Using smaller needles work k1, p1 rib across the stitches you put on a holder, beginning with a purl stitch, then pick up 3sts at the top of the thumb \(where you cast on 1 st after finishing the thumb gusset\).' +
'</p><p>' +
'Place a marker for the beginning of the round.' +
'</p><p>' +
'Next round\: Work rib to the last 4sts, P2tog, k1, remove the end of round marker and purl the last stitch together with the 1st stitch of the next round. Replace the end of round marker.' +
'</p><p>' +
'Work 1.25cm or 1\/2\" of k1, p1 rib \(beginning with a knit stitch this time!\), cast off loosely.' +
'</p><p>' +
'<strong>Finishing</strong>' +
'</p><p>' +
'Darn in all loose ends, wash and block.' +
'</p><p>' +
'Copyright Sarah Bradberry June 2005. All rights reserved.\n'
}

$("#makepattern").click(function (event) {
    return pattern();
    }
    );

$( "#makepattern" ).click(function( event ) {
    event.preventDefault();
  $( "#patternResult" ).html( event.result );
}
);

$( "#makepattern" ).click(function() {
  $("#patternCreate" ).hide( );
}
);

4 Answers

Christopher Hall
Christopher Hall
9,052 Points

I recommend using this jQuery form validation plugin, it's very easy to use and powerful. One of the things that you will quickly learn as a web designer is not to trust user input to be correctly formed. If you're asking for a number and someone puts text in there instead, it could screw up your script's operation.

Putting all of that concatenated HTML in the return clause of your function is a poor coding practice. If you're just inserting values into pre written text, it would be much easier to put all of that HTML in the #patternResult div, which is initially hidden by giving it a display:none css code. Then for every field you want to insert, put a <span> tag with a unique ID field. In your processing code, you can fill in the spans with the proper values by doing something like the below code, and finally revealing the #patternResult div at the end.

$('#yourName').html(yourName);
Sarah Bradberry
Sarah Bradberry
7,115 Points

Thanks. I'm working on that now.

For instances where I have, for example, (thumbStitches+2) in the return clause rather than just the variable thumbStitches, would I create another variable with the value of thumbStitches+2 or is there a more concise way?

Jonathan Dion
Jonathan Dion
6,131 Points

Maybe this but you should refactoring your code.

http://jsfiddle.net/RdAWe/

Thank

Sarah Bradberry
Sarah Bradberry
7,115 Points

Thanks, I thought I replied before but I mustn't have.

I tried

$("#makepattern").click(function (event) { 
    return pattern();   
    event.preventDefault();
$( "#patternResult" ).html( event.result );
 $("#patternCreate" ).hide( );
}
);

at first but it didn't work. One website I found said they had to separated in order to work (?)

Sarah Bradberry
Sarah Bradberry
7,115 Points
    I just realised I had everything in the wrong order!
$( "#makepattern" ).click(
function( event ) {
    event.preventDefault();
    $( "#patternResult" ).html( event.result );
    $("#patternCreate" ).hide( );
    $("#patternResult" ).show( );
    return pattern();
}
);

is working fine. Of course, the return had to be at the end. I'd forgotten that.

Thank you for mentioning that or I would never have taken the time to work it out.

Christopher Hall
Christopher Hall
9,052 Points

You could create another variable for thumbStitches+2, or you could just put it within the .html() part. I think it would be better in this case to create a new variable because that fits better with your logic code, not the display code.

For better readability and maintenance of the code, try to separate your programming logic from your output/display results as much as possible. If you haven't heard of Model-View-Controller (MVC) pattern yet, this separates your data source (Model) from your processing/logic (Controller), and your output/display (View). This is more useful in web applications (vs single page scripts) because they're a much larger and more complex collection of code.

Sarah Bradberry
Sarah Bradberry
7,115 Points

Excellent advice, thanks.

I only started learning JavaScript 2 weeks ago & it's the first programming I've ever done (unless you count HTML and CSS) so I've got a lot to learn!

Jonathan Dion
Jonathan Dion
6,131 Points

Did you try my code Sarah?

Sarah Bradberry
Sarah Bradberry
7,115 Points
    Hi Jon,

I did but unfortunately it no longer returned a result when all the fields were filled in.