2
\$\begingroup\$

JavaScript concerns

Is this the best way in jQuery to handle a button being pressed without making an HTTP req?

$("#input-box-form").submit( function(event) {
    event.preventDefault();
    var data = getParityData();
    showParityData(data);
});

This seems like a mess/redundant/I'm not doing it right. How can I make it better with CSS/JavaScript?

$("#input-box").keyup( function(event) {
    var input_num = $("#input-box").val();
    if (input_num.match("^0b")){
        bin_num = input_num.slice(2);
        if (!(/^[0|1]+$/.test(bin_num))){
            $("#input-box-form").addClass("has-error");
            $("#generate-button").prop('disabled',true);
        } else {
            $("#input-box-form").removeClass("has-error");
            $("#generate-button").prop('disabled',false);
        }
    } else {
        bin_num = (+input_num).toString(2);
        if( input_num.length == 0 ){
            $("#input-box-form").addClass("has-error");
            $("#generate-button").prop('disabled',true);
        } else if (isNaN(bin_num)){
            $("#input-box-form").addClass("has-error");
            $("#generate-button").prop('disabled',true);

        } else {
            $("#input-box-form").removeClass("has-error");
            $("#generate-button").prop('disabled',false);
        }
    }
});

Edit - After talking with my friend, I re-worked the above:

$("#input-box").keyup( function(event) {
    var input_num = $("#input-box").val();
    if (input_num.match("^0b")){
        bin_num = input_num.slice(2);
        is_error = !(/^[0|1]+$/.test(bin_num));
    } else {
        bin_num = (+input_num).toString(2);
        is_error = isNaN(bin_num);
    }
    $("#input-box-form").toggleClass("has-error",is_error);
    $("#generate-button").prop('disabled',is_error);
});

Any code suggestions to make it more JavaScript-onic?

HTML concerns

  • Any improvements on bootstrap [mis]usage?
  • Any suggestions on structure/naming conventions?
  • Anything else missing from my html file?

Functionality/usability

http://paritybitgenerator.com

  • Is there anything confusing to the end user?
  • Can I make the experience better?
  • Are there any suggestions for things to add to the site?

HTML code:

<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="mystyle.css">
<title>Parity Bit Generator</title>
<body>

<div class="container">
    <h1><strong>Parity Bit Generator</strong></h1>
    <form class="form-inline" role="form" id="input-box-form" >
        <div class="form-group">
            <label class="sr-only" for="number">Input Number</label>
            <input type="text" class="form-control input-lg" id="input-box" placeholder="1234, 0b10, 0xBA">
        </div>
        <button type="submit" class="btn btn-primary btn-lg" id="generate-button" disabled="true">Generate</button>
    </form>
    <div id="result-section" >
    </div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="handlebars-v1.3.0.js"></script>

<script src="parity-bit-generator.js"></script>
<script src="google-analytics.js"></script>
<script id="parity-data-template" type="text/x-handlebars-template">
     <div class="alert alert-success" id="alert-section" role="alert">
       <div id="input-info-section" class="row">
           <div class="col-sm-12">
               <i class="fa fa-chevron-right"></i>
               <i class="fa fa-chevron-right"></i>
               <p> {{ input_num }}  </p>
           </div>
       </div>
       <div id="parity-data-section" class="row">
           <div class="col-sm-3">
               <p><em>binary</em></p>
               <p> {{ bin_num }}  </p> 
           </div> 
           <div class="col-sm-3"> 
               <p><em>count of 1s</em></p> 
               <p class="large"> {{ count_of_1s }}  </p> 
           </div> 
           <div class="col-sm-3"> 
               <p><em>even parity</em></p> 
               <p> {{ even_parity }} </p> 
           </div> 
           <div class="col-sm-3"> 
               <p><em>odd parity</em></p> 
               <p> {{ odd_parity }}  </p> 
           </div> 
       </div> 
     </div>  
</script>

</body>
</html>

JavaScript:

function getParityData(){
    var data = {};
    data.input_num = $("#input-box").val();
    if (data.input_num.match("^0b")){
        data.bin_num = data.input_num.slice(2);
    } else {
        data.bin_num = parseInt(data.input_num).toString(2);
    }
    data.count_of_1s = data.bin_num.match(/1/g).length;
    data.even_parity = data.count_of_1s % 2;
    data.odd_parity = (data.count_of_1s + 1) % 2;
    return data;
}

function showParityData(data){
    var source = $("#parity-data-template").html();
    var template = Handlebars.compile(source);
    var html = template(data);
    $("#result-section").html(html);
    $("#result-section").fadeIn('fast');
}

$("#input-box").bind('input',function(event) {
        $("#result-section").fadeOut('fast');
});

$("#input-box").keyup( function(event) {
    var input_num = $("#input-box").val();
    if (input_num.match("^0b")){
        bin_num = input_num.slice(2);
        if (!(/^[0|1]+$/.test(bin_num))){
            $("#input-box-form").addClass("has-error");
            $("#generate-button").prop('disabled',true);
        } else {
            $("#input-box-form").removeClass("has-error");
            $("#generate-button").prop('disabled',false);
        }
    } else {
        bin_num = (+input_num).toString(2);
        if( input_num.length == 0 ){
            $("#input-box-form").addClass("has-error");
            $("#generate-button").prop('disabled',true);
        } else if (isNaN(bin_num)){
            $("#input-box-form").addClass("has-error");
            $("#generate-button").prop('disabled',true);

        } else {
            $("#input-box-form").removeClass("has-error");
            $("#generate-button").prop('disabled',false);
        }
    }
});

$("#input-box-form").submit( function(event) {
    event.preventDefault();
    var data = getParityData();
    showParityData(data);
});
\$\endgroup\$
  • \$\begingroup\$ What's the point of .form-group? \$\endgroup\$ – Schism Aug 14 '14 at 21:11
  • \$\begingroup\$ Since the label is class sr-only, I guess I do not need the extra form group. I got it by just using the example straight out of the docs . I removed the wrapping class and it functions the same. \$\endgroup\$ – massover Aug 15 '14 at 1:21
2
\$\begingroup\$

This is nice! A few things I would do differently.

Simplify the parity calculation

Once you have the even parity, it's simpler to calculate the odd parity from it:

data.even_parity = data.count_of_1s % 2;
data.odd_parity = 1 - data.even_parity;

Wait for dom to be ready

You should not make jQuery calls before the page is fully loaded. Wrap all the $(...) calls within this:

$(function() {
    // ...
});

Compile the HandleBars template once, reuse many times

You are recompiling the HandleBars template on every query:

function showParityData(data){
    var source = $("#parity-data-template").html();
    var template = Handlebars.compile(source);
    var html = template(data);
    $("#result-section").html(html);
    $("#result-section").fadeIn('fast');
}

When it would be enough to do only once, on page load:

var template;

$(function() {
  var source = $("#parity-data-template").html();
  template = Handlebars.compile(source);
});

function showParityData(data){
    var html = template(data);
    $("#result-section").html(html).fadeIn('fast');
}

Another small thing here, notice that I chained the .fadeIn on the $("#result-section").html(html), it's less duplication, and more efficient this way because jQuery won't have to repeat the same dom query again.

Usability concerns

I don't like that every keypress in the input field clears the output. I like to see the previous output even while I'm typing. So I would comment out this bit:

$("#input-box").bind('input',function(event) {
    $("#result-section").fadeOut('fast');
});

I would like it more if the input received focus on page load, so I can just start typing. You could chain .focus() after any of the queries on $("#input-box"), for example:

$("#input-box").keyup(function(event) {
    // ...
}).focus();

It might be also nice if you could parameterize the URL to show a specific number, for example:

// permalink to 123 with:
// http://paritybitgenerator.com/?123
$("#input-box").val(location.search.substr(1));
$("#input-box-form").submit();

Simplifying keyup

You could remove the extra parentheses:

is_error = !(/^[0|1]+$/.test(bin_num));

and write simply:

is_error = ! /^[0|1]+$/.test(bin_num);

I don't see the significance of the + sign here:

bin_num = (+input_num).toString(2);

It seems to me this is equivalent, and simpler:

bin_num = input_num.toString(2);

Valid HTML

The site doesn't pass validation on http://validator.w3.org/

  • Change the first line of the HTML to <!DOCTYPE html>
  • Change disabled="true" to disabled in the Generate button
  • Change for="number" to for="input-box" in the label
  • Drop the http-equiv meta header -- Interestingly, the Bootstrap website uses this too, and fails the W3C validator because of it. Strange.
\$\endgroup\$
  • \$\begingroup\$ Thank you for the suggestions! I implemented all of them. I did not know about the w3 validator either. \$\endgroup\$ – massover Aug 14 '14 at 2:12
  • \$\begingroup\$ It looks like http-equiv fails the validator, but it's needed for bootstrap, so I kept it. I used autofocus property inside the input html instead of implementing it jquery. To clarify, I'm using the (+input_num) to handle the hex/int conversion. The + is the unary operator. It will allow the toString(2) function to return NaN if the input_num is not a valid int string or hex string starting with 0x. Is there a better way to implement this? \$\endgroup\$ – massover Aug 14 '14 at 2:23
  • \$\begingroup\$ Hm, interesting, I didn't know that about bootstrap... The page seems to work fine even if I remove it. Maybe the difference is visible only in IE? As for (+input_num).toString(2), you don't need that hackery because the next isNaN line will catch such invalid input, for example isNaN("jack".toString(2)) is true. \$\endgroup\$ – janos Aug 14 '14 at 6:46
  • \$\begingroup\$ @massover RE: http-equiv: in relevant IE versions, declaring <!DOCTYPE html> will automatically set IE to render in edge mode. \$\endgroup\$ – Schism Aug 14 '14 at 21:04
  • \$\begingroup\$ @Schism Interestingly, the bootstrap homepage itself uses it, and it fails the w3c validator as a consequence getbootstrap.com \$\endgroup\$ – janos Aug 14 '14 at 21:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.