Skip to main content
Code Review

Return to Answer

replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link

As you can see from this jsPeft, a native for loop is much faster than $.each. You can see the source code for each at this StackOverflow post StackOverflow post.

As you can see from this jsPeft, a native for loop is much faster than $.each. You can see the source code for each at this StackOverflow post.

As you can see from this jsPeft, a native for loop is much faster than $.each. You can see the source code for each at this StackOverflow post.

Source Link
Daniel Imms
  • 985
  • 7
  • 16

Initial notes

  • [-] caching (no jquery selector is cached)

You should be creating variables that store the elements you're selecting with jQuery. The reason for this is that when you call $("#step" + stepNumber + "_tab") for example, jQuery will determine what type of selector it is (id), and them call document.getElementById("step" + stepNumber + "_tab"). This is particularly important when you're selecting multiple elements.

  • [-] performance optimization (nope, usage of jquery each instead of a native loop)

So you used $.each, what is the problem with that? Well it is doing a tonne of other stuff just so you can have some nice convenient syntax. For systems you're trying to optimise you should probably stay away from it, prefer this:

 var required = $(".required");
 for (var i = 0; i < required.length; i++) {
 // object is required[i]
 }

As you can see from this jsPeft, a native for loop is much faster than $.each. You can see the source code for each at this StackOverflow post.

  • [-] reusable code (hardly, as commented above)

The main issue here is that your document ready is a whopping 85 lines long. You should be splitting it up into logical groupings and placing it in functions. This is something that a lot of new programmers have trouble with and I never really understood until I saw a great example. Consider a function of 85 lines of code vs:

 $(document).ready(function () {
 setupItemA();
 setupItemB();
 setupItemC();
 setupItemD();
 });

This is much more readable, modular and reusable.

  • [+] clean code and good structure

This ties in a lot with above point 'reusable code' in my opinion. I'm assume your teacher was marking this point on consistency, indentation, appropriate calls, etc. which it seems to do pretty well.

  • [] Extra points for applied design pattern

This would depend on what design patterns you have been learning in your course.

Code walkthrough

I'll now go through my implementation, line-by-line.

// Ideally this should go in your HTML page, I assume it wasn't an option though.
$("<link rel='stylesheet' href='css/ui-lightness/jquery-ui-1.10.1.custom.css' type='text/css' media='screen' />").insertAfter("[type='text/css']"); // CSS de Jquery UI
// This regex wouldn't be acceptable in a lot of companies as it's huge and difficult
// to read. A link to the source would be good in this situation.
function isValidEmailAddress(emailAddress) {
 var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
 return pattern.test(emailAddress);
};
// If your spacing is more consistent, your code will look cleaner. More than one 
// line in a row can make code look messy.
function setTabOn(stepNumber) {
 // This conversion is redundant, you're converting an int to an int and then using
 // it in a string. JavaScript does conversions like this implicitly anyhow
 //stepNumber = parseInt(stepNumber);
 
 // Caching
 var tab = $("#step" + stepNumber + "_tab");
 tab.addClass("on");
 tab.click(function() {
 $(".step").hide();
 $("#step" + stepNumber).show();
 $("#steps a.active").removeClass("active");
 }); 
}
function nextStep(stepNumber) {
 stepNumber = parseInt(stepNumber) + 1;
 $(".step").hide();
 // You don't need to include the ol in 'ol#steps', it makes your code more specific
 // and thus less reusable.
 $("#steps li a").removeClass("active");
 $("#step" + stepNumber).show();
 $("#step" + stepNumber + "_tab").addClass("active");
}
$(document).ready(function() {
 // Your indentation went a little funny in your document ready
 $(".back").click(backClick);
 $("#step2_confirm_button").click(step2Confirm);
 $("#step2_cancel_button").click(step2Cancel);
 $("#step1_next").click(step1NextClick);
 $("#step2_next").click(step2NextClick);
 
 // Shuffled around in better order
 $(".step").hide();
 $("#step1").show();
 $("#step1_tab").addClass("active");
 $("#step2_confirm").hide();
});
function step2Confirm() {
 $("#step2_confirm").dialog("destroy");
 nextStep(2);
 setTabOn(2);
}
function step2Cancel() {
 $("#step2_confirm").dialog("destroy");
}
function backClick = function() {
 // You defined idBank twice here?
 //var idBack = $(this).attr("id");
 //var idBack = idBack.match(/\d/) - 1;
 // Use this.id instead of the jQuery alternative, it's much faster
 var idBack = this.id
 // I'm not sure what your regex was trying to do
 $(".step").hide();
 $("#step" + idBack).show(); 
};
function step1NextClick() { 
 var flagFirstStepError = 0;
 var flagFirstStepEmpty = 0;
 var flagFirstStepEmail = 0;
 
 $("#step1_errors").html("");
 
 var required = $(".required");
 for (var i = 0; i < required.length; i++) {
 if ($(this).val() == "") {
 flagFirstStepError = 1;
 // Missing semi-colon
 return false;
 // Place } else { all on same line
 } else {
 flagFirstStepEmpty = 1;
 }
 }
 
 if (flagFirstStepError == 1) {
 showError(this, required);
 }
 
 var userEmail = $("#email").val();
 if (!isValidEmailAddress(userEmail)) {
 // Include a closing tag, address spelt wrong ;)
 $("#step1_errors").append("<p>You must provide a valid email address</p>");
 flagFirstStepEmail = 0;
 } else {
 flagFirstStepEmail = 1;
 }
 
 // Never do an operation of the left-hand side of an if
 if (flagFirstStepEmail == 1 && flagFirstStepEmail == 1) {
 nextStep(1);
 setTabOn(1);
 }
}
function showError(sender, required) {
 // Only append the string once, keep in a variable
 var message = "We are sorry, but you need to enter all the required fields in order to proceed. The following information is missing: <br /><ol>";
 for (var i = 0; i < required.length; i++) { 
 if ($(sender).val() == "") {
 var y = $("#step1 label[for=" + sender.id + "]").html();
 message += "<li>You must fill the " + y + " field</li>";
 }
 }
 message += "</ol>";
 $("#step1_errors").append(message);
}
// I moved your events down here to reduce indentation, the size of document ready, and
// improve readability
function step2NextClick() { 
 $("#confirm_list li").remove();
 $("#share_list li label").find("input:checked").each(function() { 
 var x = $(this).val(); 
 $("#confirm_list").append("<li>" + x + "</li>");
 });
 $("#step2_confirm").dialog();
};
default

AltStyle によって変換されたページ (->オリジナル) /