SitePoint Sponsor

User Tag List

Page 1 of 5 12345 LastLast
Results 1 to 25 of 112

Hybrid View

  1. #1
    ********* Callithumpian silver trophy freakysid's Avatar
    Join Date
    Jun 2000
    Location
    Sydney, Australia
    Posts
    3,798
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Javascript - Useful Tips & Tricks

    Let's have them

  2. #2
    Sultan of Ping jofa's Avatar
    Join Date
    Mar 2002
    Location
    Svj
    Posts
    4,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    1)
    Include js version in the language attribute, e.g.
    <script type="text/javascript" language="JavaScript1.4">

    Useful if you want to "hide" code from older browsers
    E.g. if you use try...catch statements (v 1.4)

    2)
    Use try...catch to catch exceptions

  3. #3
    SitePoint Guru hgilbert's Avatar
    Join Date
    Dec 2004
    Location
    London
    Posts
    839
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by jofa
    1)
    Include js version in the language attribute, e.g.
    <script type="text/javascript" language="JavaScript1.4">

    Useful if you want to "hide" code from older browsers
    E.g. if you use try...catch statements (v 1.4)

    2)
    Use try...catch to catch exceptions
    real shame that it doesn't validate in XHTML 1.0 (Strict)
    it would help me a lot having language="Javascript 1.x"
    to also hide things like regex


  4. #4
    SitePoint Member
    Join Date
    Sep 2007
    Location
    South China
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm a relative newbie to this forum and I would just like to add my thanks to the contributors to this thread. Good stuff!!

  5. #5
    SitePoint Evangelist
    Join Date
    Jul 2007
    Posts
    345
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Prototype referencing, switching and updating

    A discussion of how prototypes work inside and outside of constructor functions.
    http://www.room51.co.uk/js/prototypePlacement.html

  6. #6
    SitePoint Member
    Join Date
    Apr 2008
    Posts
    12
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Very nice thread... i learn some about javascript with this thread... Thanks for all...

  7. #7
    SitePoint Member
    Join Date
    Mar 2008
    Posts
    4
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Very useful thread. I have been looking for some of these.

  8. #8
    SitePoint Member
    Join Date
    Aug 2008
    Posts
    2
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm newbies and try to do website with html and java.

  9. #9
    SitePoint Enthusiast
    Join Date
    Jan 2009
    Location
    Michigan
    Posts
    70
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Code:
    function checkName() {
    	if (document.form.VisitorName.value=="") {
    		alert("you must provide your name");
    		return false;
    	}
    	if (document.form.VisitorName.value.length < 2) {
    		alert("please enter your real name");
    		return false;
    	}
    	return true;
    }
    function checkPhoneEmail() {
    		
    	if ((document.form.VisitorEmail.value=="" || document.form.VisitorEmail.value==null) && 
    		 (document.form.VisitorPhone.value=="" || document.form.VisitorPhone.value==null)) {
    		alert("You must fill in  Phone or Email");
    		return false;
    	}
    	if ((document.form.VisitorEmail.value!="") && (document.form.VisitorEmail.value!=null)){
    			if (!ValidateEmail()){
    					return false;
    			}
    		}
    	if ((document.form.VisitorPhone.value!="") && (document.form.VisitorPhone.value!=null)){
    			if (!ValidatePhone()){
    				return false;
    			}
    		}
    	return true;
    }
    
    
    
    
    
    //		||---------Email Checker --------------||
    //check to make sure email has a @ and a . and that they are in legit places
    function echeck(str) {
    
    		var at="@"
    		var dot="."
    		var lat=str.indexOf(at)
    		var lstr=str.length
    		var ldot=str.indexOf(dot)
    		if (str.indexOf(at)==-1){
    		   alert("Invalid E-mail Address")
    		   return false
    		}
    
    		if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr){
    		   alert("Invalid E-mail Address")
    		   return false
    		}
    
    		if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr){
    		    alert("Invalid E-mail Address")
    		    return false
    		}
    
    		 if (str.indexOf(at,(lat+1))!=-1){
    		    alert("Invalid E-mail Address")
    		    return false
    		 }
    
    		 if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot){
    		    alert("Invalid E-mail Address")
    		    return false
    		 }
    
    		 if (str.indexOf(dot,(lat+2))==-1){
    		    alert("Invalid E-mail Address")
    		    return false
    		 }
    		
    		 if (str.indexOf(" ")!=-1){
    		    alert("Invalid E-mail Address")
    		    return false
    		 }
    
     		 return true					
    	}
    
    function ValidateEmail(){
    	var emailID=document.form.VisitorEmail
    	
    	if ((emailID.value==null)||(emailID.value=="")){
    		alert("Please Enter a Valid Email Address")
    		emailID.focus()
    		return false
    	}
    	if (echeck(emailID.value)==false){
    		emailID.value=""
    		emailID.focus()
    		return false
    	}
    	return true
     }
    
    
    
    
    
    
    //		||-----------Phone Checker -----------||
    // Declaring required variables
    var digits = "0123456789";
    // non-digit characters which are allowed in phone numbers
    var phoneNumberDelimiters = "()- ";
    // characters which are allowed in international phone numbers
    // (a leading + is OK)
    var validWorldPhoneChars = phoneNumberDelimiters + "+";
    // Minimum no of digits in an international phone no.
    var minDigitsInIPhoneNumber = 10;
    
    function isInteger(s)
    {   var i;
        for (i = 0; i < s.length; i++)
        {   
            // Check that current character is number.
            var c = s.charAt(i);
            if (((c < "0") || (c > "9"))) return false;
        }
        // All characters are numbers.
        return true;
    }
    function trim(s)
    {   var i;
        var returnString = "";
        // Search through string's characters one by one.
        // If character is not a whitespace, append to returnString.
        for (i = 0; i < s.length; i++)
        {   
            // Check that current character isn't whitespace.
            var c = s.charAt(i);
            if (c != " ") returnString += c;
        }
        return returnString;
    }
    function stripCharsInBag(s, bag)
    {   var i;
        var returnString = "";
        // Search through string's characters one by one.
        // If character is not in bag, append to returnString.
        for (i = 0; i < s.length; i++)
        {   
            // Check that current character isn't whitespace.
            var c = s.charAt(i);
            if (bag.indexOf(c) == -1) returnString += c;
        }
        return returnString;
    }
    
    function checkInternationalPhone(strPhone){
    var bracket=3
    strPhone=trim(strPhone)
    if(strPhone.indexOf("+")>1) return false
    if(strPhone.indexOf("-")!=-1)bracket=bracket+1
    if(strPhone.indexOf("(")!=-1 && strPhone.indexOf("(")>bracket)return false
    var brchr=strPhone.indexOf("(")
    if(strPhone.indexOf("(")!=-1 && strPhone.charAt(brchr+2)!=")")return false
    if(strPhone.indexOf("(")==-1 && strPhone.indexOf(")")!=-1)return false
    s=stripCharsInBag(strPhone,validWorldPhoneChars);
    return (isInteger(s) && s.length >= minDigitsInIPhoneNumber);
    }
    
    function ValidatePhone(){
    	var Phone=document.form.VisitorPhone
    	
    	if ((Phone.value==null)||(Phone.value=="")){
    		alert("Please Enter your Phone Number ex: 555-555-5555")
    		Phone.focus()
    		return false
    	}
    	if (checkInternationalPhone(Phone.value)==false){
    		alert("Please Enter a Valid Phone Number ex: 555-555-5555")
    		Phone.value=""
    		Phone.focus()
    		return false
    	}
    	return true
     }
    
    
    function CheckAll(){
    	if (checkName() &&	checkPhoneEmail()) {
    		return true;
    		}
    		else
    		{
    			return false;
    		}
    	
    }
    HTML :
    HTML Code:
    <form name="form" action="<?php echo $_SERVER['PHP_SELF'];?>" method="POST" onSubmit="return CheckAll();">
    be sure to name the "name" property of input fields accordingly:
    Name input should be "VisitorName"
    Email input should be "VisitorEmail"
    Phone input should be "VisitorPhone"

    hope it helps!
    J

  10. #10
    SitePoint Member
    Join Date
    Oct 2009
    Posts
    4
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    How do you comment out code? Using /*...*/? Using your IDE to put // before each line? There is a third method:
    view source
    print?
    1.if (0 == 1) {
    2. ... code ...
    3.}

    Pros:

    * Nests
    * You need only change a single character to flip the comment: Replace the 0 with 1.
    * You wont get warnings because of suddenly unused imports or local variables.
    * The Java compiler will remove this block of code in the optimization step, so no runtime penality.

    Cons:

    * Can only be used inside of methods.

    If you need a fast way to repeatedly comment in/out a piece of code elsewhere, use this syntax:
    view source
    print?
    1.//* Fast flip comment starts here
    2. ... code ...
    3./* and ends here */

    Inside of a /*...*/ comment, the sequence /* has no special meaning. To comment out the block of code, remove the first / in //*:
    view source
    print?
    1./* Fast flip comment starts here
    2. ... code ...
    3./* and ends here */

  11. #11
    SitePoint Zealot evilunix's Avatar
    Join Date
    Jun 2008
    Location
    York, UK.
    Posts
    114
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Rather than always doing document.getElementById you can save a lot of space by creating a shortcut function like so:

    Code JavaScript:
    function $(id) {
       if(document.getElementById) return document.getElementById(id);
       return null;
    }

  12. #12
    SitePoint Guru
    Join Date
    Sep 2006
    Posts
    731
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by evilunix View Post
    Rather than always doing document.getElementById you can save a lot of space by creating a shortcut function like so:

    Code JavaScript:
    function $(id) {
       if(document.getElementById) return document.getElementById(id);
       return null;
    }
    When a strict doctype is not used, I.E allows a name parameter as well as ID, and also treats the parameter as case insensitive.
    This version suppresses that behaviour:
    Code:
    function $( id )
    {
      var elem = document.getElementById( id );
       
      return elem && elem.id === id ? elem : null;
    }
    If you just want to repair document.getElementById:
    Code:
    if( !document.GETELEMENTBYID )
    { 
     document.GETELEMENTBYID = document.getElementById;
    
     document.getElementById = function( id )
     {
      var elem = document.GETELEMENTBYID( id );
       
      return elem && elem.id === id ? elem : null;
     }
    }
    Tab-indentation is a crime against humanity.

  13. #13
    SitePoint Member
    Join Date
    Feb 2010
    Posts
    1
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    These code are really very helpful thanks for sharing...

  14. #14
    padawan silver trophybronze trophy markbrown4's Avatar
    Join Date
    Jul 2006
    Location
    Victoria, Australia
    Posts
    4,115
    Mentioned
    28 Post(s)
    Tagged
    2 Thread(s)
    An example of how to use the closest thing to a class with private and public members in Javascript:
    Code HTML4Strict:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Untitled Document</title>
    </head>
    <body>
    <div id="FooManChoo"></div>
    <script type="text/javascript">
    $ = function(id) { return document.getElementById(id);};
     
    var Foo = function(id, options)  {
     
    	// private variables
    	var elm = $(id),
    	favouriteBeer = 'Pale Ale';
     
    	elm.Foo = this; // reference to object so you can access public properties
     
    	// public variables
    	this.beer = false;
     
    	// private function
    	function bar() { alert('Private Bar stocks ' + favouriteBeer); }
     
    	// public function
    	this.bar = function() {
    		bar();
    		this.beer ? alert('Public bar has Beer :) !') : alert('Public bar has no Beer :(');
    	}
    };
     
    new Foo('FooManChoo');
    with ($('FooManChoo').Foo) {
    	bar();
    	beer = true;
    	bar();
    }
    </script>
    </body>
    </html>

  15. #15
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    Sometimes other scripting libraries that you use may conflict with jQuery, so you need a way to use both of them without them conflicting.

    jQuery has a useful noConflict mode that helps with that.

    Load the jQuery library, then tell jQuery to go in to noConflict mode.

    Code javascript:
    <script src="js/jquery.js"></script>
    <script>jQuery.noConflict();</script>

    Now the $ symbol is not automatically used by jQuery anymore.

    It is possible though to still use $ for your jQuery code. You just have to provide it as a function parameter to the jQuery callback.

    Code javascript:
    <script src="js/jquery.js"></script>
    <script src="js/script.js"></script>

    js/script.js
    Code javascript:
    jQuery.noConflict();
    jQuery(function ($) {
        // jQuery code in here
    });
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  16. #16
    SitePoint Member
    Join Date
    Dec 2011
    Location
    London, Britain
    Posts
    4
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here are some Javascript tips I discovered when writing a free game:

    1. You can remove an element from an array with 'splice'. For example:

    array.splice(index, 1); // remove item at index

    usually the built-in array functions on arrays return a new array.

    2. A CSS style attribute that is not set has a value of '', an empty string. To get rid of one of your style settings, set it ''.

    3. You cannot do really slick and fast animations with simple Javascript and dynamic HTML without the browser becoming unresponsive or maybe missing out steps.

    You need to pause, maybe for longer than 50 milliseconds, to let the browser handle your mouse clicks and refresh the screen.

    You could try using the 'canvas' element, but I am not sure if Internet Explorer supports it.

    4. You can of course do transparency yourself - just take a (weighted) average of the red, green and blue values separately.

    Older browsers such as Internet Explorer 6 may not support an 'opacity' setting, particularly if set dynamically.

    5. Dividing a number by zero gives the value 'Number.POSITIVE_INFINITY' and does not cause an error.

    6. My suggestions for optimising Javascript would be to think carefully about what algorithms you use and try hard not to repeatedly execute any code unnecessarily.

    Simple examples of these are that I use a binary search to look up values in a long list, and only make changes related to some settings values once the user has finally left the settings screen so the user can change the values within the settings screen many times and still get a quick response.

    7. You can add a 'toString()' member function to your classes to show the values of their instances nicely. For example:

    myClass.prototype.toString =
    function() { return '(' + this.a + ', ' + this.i + ')'; }

    If the instances are in an array, Javascript will show each instance nicely in a list.

    This is useful when debugging, in alert messages and writing trace output.

    8. You do not need to put brackets around the arguments to the 'typeof' and 'instanceof' operators.

    It is really 'typeof v' not 'typeof(v)'

    9. I extend the built-in 'Array' object with my own functions and so if I use a 'for in' loop to go through array elements then my extensions are included.

    To get round this, I recently tried a suggestion on the Internet and used Javascript's internal 'Object' class directly rather than using arrays at all.

    For example: var o = {}; o['a'] = 4;

    10. I understand that all numbers are stored as floating point numbers in Javascript and that there is no integer type.

    I have read that the bit manipulation operators in Javascript can be slow.

    This may be because the floating point numbers have to be converted to integers and then converted back.

  17. #17
    SitePoint Member
    Join Date
    Dec 2011
    Location
    London, Britain
    Posts
    4
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here are some more Javascript tips I learnt when writing a free game:

    1) If global variables are used many times in a function, it is faster to make local copies of them.

    2) Check just once for features that vary between browsers. For example, finding where you click the mouse by using either 'event.target' or 'event.srcElement'

    3) In a function of an object, inner functions do not have the 'this' variable available to them. 'this' refers to the current instance of the object. A simple way round this is to set a variable 'that' to be 'this' in the outer function and use the variable 'that' in any inner functions.

    4) Javascript acts as though it is single threaded, so you do not need to do much locking. While your current functions are running, Javascript will ignore any mouse clicks and any code starting from a timeout. I do sometimes use a lock to hold onto control during pauses in animations. As Javascript is single threaded, the sequence of testing a value and setting a value is atomic.

    Also when Javascript shows an alert box, the script completely stops. All threads running freeze.

    5) Remember that neatly indenting your HTML adds text elements which can get in the way when your are going through the document tree with, for example, 'nextSibling' or 'previousSibling'. You might like to squash up the HTML.

    6) To set the 'for' property of a HTML 'label' in Javascript, you set the 'htmlFor' property. Otherwise Javascript confuses this with the 'for' loop keyword. My Konqueror browser lets you use 'for' in the 'setAttribute()' function for this but Internet Explorer does not.

    In Javascript you set an HTML element's 'className' not 'class' to add the element to a CSS stylesheet class. Also remember that you set the 'className' on the HTML element and not in the elements 'style' object.

    7) Remember that the user can scroll through the page. When you position a HTML element absolutely, add the amount scrolled. I use the value of 'document.body.scrollTop'.

    8) Coding like this:

    msg = x +
    y;

    rather than:

    msg = x
    + y;

    may help the Javascript interpreter to parse your code faster as newlines can end statements

    9) I found 'JSHint', the static code analyser, to be very useful.

    It seems more flexible than 'JSLint' on which it is based. As an example, 'JSLint' stops when it comes to places where I declare variables inside 'for' loops, for example: 'for (var i = 0; i < 3; i++)'.

    JSHint pointed out that:

    a) I had forgotten to end many statements with a semicolon. In particular I had used the form 'obj.prototype.func = (){}' but missed off the semicolon at the end

    b) I had sometimes forgotten to declare variables as local variables with a 'var', leaving them to be global variables which might be slower to look up

    c) I had defined variables more than once in functions with multiple 'var' statements

    d) I had declared some classes (objects) and variables below where they were used in the source file. Sometimes I had something like:

    function func() {
    function subFunc() { i = 3; }
    var i;
    }

    where it might be slightly better to declare the variable 'i' at the start of the outer function

    e) I still occasionally used '==' and '!=' rather than '===' and '!=='. The former may convert its arguments to a different type leading to subtle errors

    I had a few minor problems with JSHint:

    a) it expects you to restrict the results of 'for in' statements by using the 'hasOwnProperty()' method. I was just worried about my extensions to the built-in Array type being returned with the value of associative arrays and so just checked to see if the values had the 'function' type

    b) it did not like me sometimes letting code 'fall through' 'case' statement in 'switch' blocks

    c) it warned when I put the 'default' statement of a 'switch' block in the middle of other 'case' statements

    e) it would say I was using a variable 'out of scope' when I declared it in an 'if' block and later used it in a similar 'if' block

    You can increase the number of errors that the JSHint website shows if you include a comment like the following at the top of your script:

    /*jshint maxerr: 500 */

    It is best to use 'JSHint' as you are writing your code so you can adjust your coding style. If you wait until you finished, like I did, you will get a huge number of warnings.

  18. #18
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by bert.beckwith View Post
    9) I found 'JSHint', the static code analyser, to be very useful.

    It seems more flexible than 'JSLint' on which it is based. As an example, 'JSLint' stops when it comes to places where I declare variables inside 'for' loops, for example: 'for (var i = 0; i < 3; i++)'.
    That would be due to the variable not being contained within the for loop. That might be your intention, but in reality the variable declaration is hoisted to the start of the function, which is why you're asked to make your code consistent to that.

    Quote Originally Posted by bert.beckwith View Post
    JSHint pointed out that:

    a) I had forgotten to end many statements with a semicolon. In particular I had used the form 'obj.prototype.func = (){}' but missed off the semicolon at the end

    b) I had sometimes forgotten to declare variables as local variables with a 'var', leaving them to be global variables which might be slower to look up

    c) I had defined variables more than once in functions with multiple 'var' statements
    The reason why it's preferred to define them in one var statement is that allowing multiple ones leads to the temptation to place them in different places throughout your code.
    Due to the hoisting effect on variable declaration, it's best to declare them in the one var statement.
    Another useful side-effect of declaring them in one statement is that it makes it easier to see if you're using too many variables, which can lead to the realization that you should split things up in to separate functions.[/quote]

    Quote Originally Posted by bert.beckwith View Post
    d) I had declared some classes (objects) and variables below where they were used in the source file. Sometimes I had something like:

    function func() {
    function subFunc() { i = 3; }
    var i;
    }

    where it might be slightly better to declare the variable 'i' at the start of the outer function
    That's the hoisting effect once again.

    Quote Originally Posted by bert.beckwith View Post
    e) I still occasionally used '==' and '!=' rather than '===' and '!=='. The former may convert its arguments to a different type leading to subtle errors

    I had a few minor problems with JSHint:

    a) it expects you to restrict the results of 'for in' statements by using the 'hasOwnProperty()' method. I was just worried about my extensions to the built-in Array type being returned with the value of associative arrays and so just checked to see if the values had the 'function' type
    You should be aware that extending native objects is a big no-no, because you can't guarantee that someone else's similar extension to the same object will clobber the one you made earlier.

    With for...in, the preferred technique is:

    Code javascript:
    for (key in foo) {
        if (foo.hasOwnProperty(key)) {
            // do stuff
        }
    }

    More advanced code might use the .keys() and .forEach() methods instead. For example:

    Code javascript:
    Object.keys(foo).forEach(function (key, i, arr) {
        // do stuff
    });

    Quote Originally Posted by bert.beckwith View Post
    b) it did not like me sometimes letting code 'fall through' 'case' statement in 'switch' blocks
    Douglas Crockford has a wonderful piece about this, where when someone brought this up to him he considered it to beneficial to have it falling through.
    The next day that same person returned to him with a bug report in Crockford's code, caused by falling through a case statement.
    In that moment Crockford achieved enlightenment. video (from 20:21)

    Quote Originally Posted by bert.beckwith View Post
    c) it warned when I put the 'default' statement of a 'switch' block in the middle of other 'case' statements
    The trouble with that is in long switch/case sections you may look at the end and see there's none there, resulting in you trying to add a second default section to the same switch statement. Always put the default section at the end and you'll never have to face that problem.

    Quote Originally Posted by bert.beckwith View Post
    e) it would say I was using a variable 'out of scope' when I declared it in an 'if' block and later used it in a similar 'if' block
    Declare all variables at the start of the function, and you'll never face that problem.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  19. #19
    SitePoint Guru
    Join Date
    Feb 2005
    Posts
    602
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by jofa
    1)
    Include js version in the language attribute, e.g.
    <script type="text/javascript" language="JavaScript1.4">

    Useful if you want to "hide" code from older browsers
    E.g. if you use try...catch statements (v 1.4)
    That doesn't work in any browser except ones derived from Mozilla, and Firefox 1.5+ versions won't support this feature anymore.

  20. #20
    Web-coding NINJA! silver trophy beetle's Avatar
    Join Date
    Jul 2002
    Location
    Dallas, TX
    Posts
    2,900
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok. What I'm about to relate aren't necessarily rules to be obeyed or anything like that, but just stuff that I've learned from my own experiences with coding javascript that, well, make my life easier.

    Variables
    Always declare variables with var this is just good consistency, and not doing so CAN cause errors in certain situations (it's a scope issue).

    End of lines
    Please, use semicolons. I know javascript doesn't require them, but use them anyways. It makes code easier to read and EVERY other C-based scripting language requires them

    Functions and parameters
    Whenever possible, use a function. Likewise, if something is variable, use a parameter. Functions and parameters are the basic building blocks for any successful javascript...er...uh...script.

    Share the workload
    It may seem ironic at first, but 3 short functions are more efficient than one long procedural function. Especially if tasks get repeated. This becomes more important if you start making methods and objects of your own.

    Global variables
    Did you know that all global variables are also properties of the window object? They are! What does this mean? Well, it means that we can create global variables from inside a function. In fact, let's make a function that exists JUST to create new global variables
    Code:
    function makeNewGlobal( varName, val )
     {
     	window[varName] = val;
     }
     
     makeNewGlobal( "greeting", "Hello World!" );
     alert( greeting ); // Alerts 'Hello World!'
    This concept should go hand-in-hand with the previous topic, Functions and Parameters.

    Create references
    If you have any code that accesses a DOM object that you need to use more than once, create a reference. It's for more efficient than running getElementbyId() a bunch of times, or accessing your object via some collection such as images or links. Example
    Code:
    // Bad way
     function changeObject( oId )
     {
     	document.getElementById( oId ).className = 'blah';
     	document.getElementById( oId ).setAttribute( "alt", "new text" );
     }
     
     // Good way
     function changeObject( oId )
     {
     	var o = document.getElementById( oId );
     	o.className = 'blah';
     	o.setAttribute( "alt", "new text" );
     }
    For those of you that don't know, my variable o is not a copy of the object or anything like this, but just a label of sorts with which I can use it to address the object it's referencing. (don't use the with statement)

    The parseInt() function
    A very handy function indeed, but what happens here?
    Code:
    var myString = "010";
     var myNum = parseInt( myString );
    Does myNum now equal 10? Noooo. myNum is now equal to 8. Why? Becase parsenInt does it's best to guess the proper radix based on the input (8, 10, or 16), and a number like 010 looks octal. It's the leading zero in the string that trips up parseInt() here. It is not very well known that parseInt can take a second parameter. You guessed it, the radix.
    Code:
    var myString = "010";
     var myNum = parseInt( myString, 10 );
    This gives us what we expect, myNum is now equal to 10.

    For loops
    Always initialize each variable you need, rather than calling on a property in the loop's conditional. For example, instead of this
    Code:
    var myString = "Hello";
     for ( var i = 0; i < myString.length; i++ )
     {
     	alert( myString.charAt( i ) );
     }
    Use this
    Code:
    var myString = "Hello";
     for ( var i = 0, len = myString.length; i < len; i++ )
     {
     	alert( myString.charAt( i ) );
     }
    This way, the myString.length property is retrieved only once, and not at each iteration of the loop. Ok, now for my favorite way to do For loops of this nature. Did you know that when you assign a variable a value there is also a return value? That return value is a Boolean indicating if the data was succesfully stored into the variable or not. <EDIT> See notes regarding this statement in the posts below </EDIT> If you need to retrieve a value from the array or string (like above) then your for loop can look like this
    Code:
    var myString = "Hello";
     for ( var i = 0; ( c = myString.charAt( i ) ); i++ )
     {
     	alert( c );
     }
    Remember, the middle portion of the for loop just needs to evaluate as true for the loop to proceed. Neat, eh?

    While loops
    I won't say much here, but if you are performing some type of breaking condition inside a For loop, you probably need a while loop instead.

    Switch statements don't have to break after each case
    Sometimes the pesky behavior of switch statements can be a blessing. Imagine that I wanted you to create a function then when passed an integer between 0 and 10 would return a countdown-style string? How would you do it? If you remembered that switch statments proceed until they see a break, you might use one something like this
    Code:
    function blastoff( timer )
     {
     	var notice = "";
     
     	switch( timer )
     	{
     		case 10 : notice += "Ten, ";
     		case 9 : notice += "Nine, ";
     		case 8 : notice += "Eight, ";
     		case 7 : notice += "Seven, ";
     		case 6 : notice += "Six, ";
     		case 5 : notice += "Five, ";
     		case 4 : notice += "Four, ";
     		case 3 : notice += "Three, ";
     		case 2 : notice += "Two, ";
     		case 1 : notice += "One, ";
     		case 0 : notice += "Zero, ";
     		default : notice += "Blastoff!";
     	}
     	return notice;
     }
     
     alert( blastoff( 10 ) );
     alert( blastoff( 5 ) );
    Our first alert gives us "Ten, Nine, Eight, Seven, Six, Five, Four, Three, Two, One, Zero, Blastoff!" and our second alert gives us "Five, Four, Three, Two, One, Zero, Blastoff!". Simple, huh?

    Popup Window Links
    If you are making a link to a popup window, I highly suggest this format
    Code:
    <a href="whateverPage.htm" target="new" onclick="window.open( this.href, this.target, 'whatever features you want here' ); return false;">Click here!</a>
    This differs somewhat from using the java script: pseudo-protocol or just putting a hash (#) in the href. The method above will still allow the link to be usable if the user has javascript turned off and more importantly, search engine spiders can follow this link

    Use bubbling to your advantage
    Let's say that you have about 100 images onto which you want to apply some events, like onmouseover and onmouseover for a rollover-type className change. Instead of attaching each event to each image, use the events bubbling to make your life easy.
    Code:
    <script type="text/javascript">
     function doRollover( e )
     {
     	// Obtain a reference to the lowest element
     	var o = ( document.all ) ? event.srcElement : e.target;
     
     	// If the element is not what we want, quit the function
     	if ( o.nodeName != 'IMG' ) return;
     
     	// Perform rollover
     	o.className = ( o.className == 'overClass' ) ? 'outClass' : 'overClass';
     }
     </script>
     
     <!-- Now for the interesting part -->
     <div onmouseover="doRollover()" onmouseout="doRollover()">
     	<img src="blah.gif" class="outClass" />
     	<img src="blah2.gif" class="outClass" />
     	<img src="blah3.gif" class="outClass" />
     <!-- Etc, etc -->
     </div>
    Confused? Well, because both the onmouseover and onmouseout events bubble, that means that the DIV that contains all our images is hit with the events too, so we can capture thm there, and filter out the events that we don't want, and keep the ones we do.

    Creating HTML strings
    If you are creating HTML as a string whether performing an innerHTML operation or whatever, use single quotes to delimit the HTML string. Why? Because proper HTML should have double quotes around attribute values, and using single quotes to delimit the HTML keeps you from having to do lots of escaping.

    Regular Expressions
    Learn them. Love them. Use them. Get some links here

    Consult your references
    Always check with documented sources if you are unsure about something. I once spent 2-3 minutes creating a function that would reverse all the items in an array. Lo and behold, the reverse() method for arrays has been around since version 3 browsers.

    A Constructor constructor
    Here's a neat little trick for you advanced JS folks out there. Ever wanted to create your own object without having to define a unique constructor function? Well, you can! Check this out...
    Code:
    function ClassConstructor( props, methods )
     {
     	var prop, meth, fstr='';
     	for ( var p=0; (prop = props[p]); p++ )
     	{
     		fstr += 'this.' + prop + '=' + prop + ';';
     	}
     	for ( var m=0; ( meth = methods[m] ); m++ )
     	{
     		fstr += 'this.' + meth + '=' + meth + ';';
     	}
     	return new Function( props, fstr );
     }
     
     function pricePerUnit()
     {
     	return Math.round( ( this.price / this.quantity ) * 100 ) / 100;
     }
     
     dataprops = ['id','name','price','quantity'];
     datamethods = ['pricePerUnit'];
     
     var ShoppingItem = new ClassConstructor( dataprops, datamethods );
     var myData = new ShoppingItem( 1, 'x-widget', 9.99, 12 );
     alert( "The " + myData.name + " has a per unit cost of $" + myData.pricePerUnit() + " dollars." );
    Well, I'm sure if I sat here long enough I could come up with a dozen more things, but hey, you guys got what came to my head today

    Edit:

    2003.08.15 - Two new tips posted!


    Conditionals
    If you are doing some sort of comparison conditional, where one operand of that conditional is a literal, like if ( someVar == "someString" ) or if ( myNum == 3 ), it's actually better to list the literal operand first:

    if ( "someString" == someVar )
    if ( 3 == myNum )

    Why? Because if you mistype the equality operator (==) and instead type the assignment operator (=) -- a fairly common typo, then you will discover this error at runtime. Tracking down the cause of these errors can be difficult, but switch the order of your operands and the mistake of assigning a variable to a literal error instantly and give a useful line-number (even in IE!)

    The hidden power of setTimeout
    For some reason, many, many, MANYpeople don't know that the first argument for the setTimeout (and setInterval) function doesn't have to be a string. In fact, it is much more powerful when you send a function pointer, or, a reference to a function (passing it by name), instead.

    So, instead of

    setTimeout( "loop()", 1000 );

    do it this way

    setTimeout( loop, 1000 );

    Now, if we get creative, we can solve the issue of passing arguments to a setTimeout-called function, which I've seen many times. As I'm sure some of you know, the variables you are trying to pass will lose scope (unless they are global). The method to our madness will be the anonymous function.

    Once again, instead of

    setTimeout( "loop(counter)", 1000 );

    We use

    setTimeout( function() { loop(counter); }, 1000 );

    I know what you're thinking -- "Why can't I use setTimeout( loop(counter), 1000 ) ???". I'll tell you why: because that, my friend, is a function call, and if you remember, I said we need to pass a function pointer. Since we declare an anonymous function that itself calls loop(), then we are legitimately passing the proper reference, AND maintaining the power to call the function. It's like having your cake and eating it too!

    Here endeth the tips.

    Enjoy, and happy coding

    Edit:

    Re: jofa's post. Although I agree with the concept of hiding javascript from browsers that don't support it, I think it's important to note that XHTML 1.0 Strict does not allow for the language attribute on SCRIPT elements
    Last edited by beetle; Sep 29, 2004 at 13:15.
    beetle a.k.a. Peter Bailey
    blogs: php | prophp | security | design | zen | software
    refs: dhtml | gecko | prototype | phpdocs | unicode | charsets
    tools: ide | ftp | regex | ffdev




  21. #21
    SitePoint Guru
    Join Date
    Sep 2006
    Posts
    731
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by beetle View Post
    For loops
    Always initialize each variable you need, rather than calling on a property in the loop's conditional. For example, instead of this
    Code:
    var myString = "Hello";
     for ( var i = 0; i < myString.length; i++ )
     {
     	alert( myString.charAt( i ) );
     }
    Use this
    Code:
    var myString = "Hello";
     for ( var i = 0, len = myString.length; i < len; i++ )
     {
     	alert( myString.charAt( i ) );
     }
    This way, the myString.length property is retrieved only once, and not at each iteration of the loop.
    It should be noted that this technique must not be used when the length of the array/collection is likely to be changed by the statements executed within the loop, as the change will not be reflected in the value of len.
    Tab-indentation is a crime against humanity.

  22. #22
    Sultan of Ping jofa's Avatar
    Join Date
    Mar 2002
    Location
    Svj
    Posts
    4,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally posted by beetle
    Code:
    // Good way
    function changeObject( oId )
    {
        var o = document.getElementById( oId );
        o.className = 'blah';
        o.setAttribute( "alt", "new text");
    }
    Impressive list of tips

    The "Create references" tip is especially good, because it's very common that people use the Bad way of coding

    Just wanted to add: you can use a with statement when you work with properties/methods of an object
    Code:
    with(o)
    {
      className = 'blah';
      setAttribute("alt", "new text");
    }
    Can make the code easier to read too:
    Code:
    with(Math)
    {
      myVar = abs(sin(x) * PI + cos(y) / E);
      // compare to
      // myVar = Math.abs(Math.sin(x) * Math.PI + Math.cos(y) / Math.E);
    }

  23. #23
    SitePoint Guru
    Join Date
    Sep 2006
    Posts
    731
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ashwariyabisht View Post
    Nice trick this is very helpful for me.
    Not allowed in strict mode:

    Code:
    <script type="text/javascript">
    
    "use strict";
    
    with(Math)  
    {
      myVar = abs(sin(x) * PI + cos(y) / E);
      // compare to
      // myVar = Math.abs(Math.sin(x) * Math.PI + Math.cos(y) / Math.E);
    }
    
    </script>
    Tab-indentation is a crime against humanity.

  24. #24
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by Logic Ali View Post
    Not allowed in strict mode:

    Code:
    <script type="text/javascript">
    
    "use strict";
    
    with(Math)  
    {
      myVar = abs(sin(x) * PI + cos(y) / E);
      // compare to
      // myVar = Math.abs(Math.sin(x) * Math.PI + Math.cos(y) / Math.E);
    }
    
    </script>
    Is sin(x) * PI really a useful example? What would that be used for?

    The pedant in me wants to find either PI * 2 and replace that with TAU for a full circle, or to find PI / 2 and replace that with TAU / 4 to represent a quarter of a circle. This helps to aid an understanding of what is going on.

    PI*r^2 doesn't help you to understand what is going on, whereas (TAU*r*r)/2 is the definate integral of a circle's circumference. There's a direct correlation between the circumference and the area, between TAU*r and (TAU*r^2)/2, that helps you to understand what is happening from one to the other. Draw a simple graph of the circumference, from (0,0) to (r, C) and take the area under the line. TAU*r^2 is the area of a rectangle, and half of that is the triangle from (0,0) to (r,C). That's the area of a circle.

    With PI*r^2 you don't gain any of that understanding, for it's a simplification of (2*PI*r^2)/2 where the 2's are cancelled out. But I digress.


    If the formula is being used for a contour plot of some kind, I would instead use sin(x) * TAU * xScalingFactor

    When using the with statement, you also end up with troubles when using:

    Code javascript:
    var min = Math.min(Math.sin(x) + Math.cos(y));

    Because how is the computer to determine which min is being referred to? The math one or the local variable one?

    Anyway - if you do want to simplify things when using heavy math, the preferred way would be to declare the ones you want to shortcut more explicitly, so that it's clear where they are coming from.

    Code javascript:
    (function () {
        'use strict';
        var abs = Math.abs,
            sin = Math.sin,
            cos = Math.cos,
            PI = Math.TAU,
            E = Math.E;
     
        function calculateGraphingPoint(x, y, xScale, yScale) {
            xScale = xScale || 1;
            yScale = yScale || 1;
            return abs(sin(x) * TAU * xScale + cos(y) / E * yScale);
        }
        ...
        point[x][y] = calculateGraphingPoint(x, y, 0.5);
    }());
    Last edited by paul_wilkins; May 25, 2013 at 15:55.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  25. #25
    SitePoint Enthusiast
    Join Date
    Mar 2001
    Location
    northern Maine
    Posts
    52
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally posted by beetle
    Did you know that when you assign a variable a value there is also a return value? That return value is a Boolean indicating if the data was succesfully stored into the variable or not.
    Somebody's got to do it. That statement is incorrect. The return value is whatever was assigned.

    Type this in your location bar:
    javascript:alert(window.myprop = 'hi')

    You'll get an alert with the message "hi".

    You can do compound assignments:

    myVar1 = myVar2 = myVar3 = "some value";

    because of this fact (assignment goes from right to left, so it works out).

    The reason your charAt() loop ends is because:

    "hello".charAt(10) == ''

    An empty string. And an empty string typecasts into a boolean true value, which is what is happening at the end of each iteration in your loop.
    Jason - Contact Me
    Supermoderator @ CodingForums


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •