Universal JavaScript

Author: Thava Alagu thavamuni@gmail.com
Version: 0.1
Date: 2013 August 04
Status: Draft

1   Prologue

This is an introductory book for JavaScript Language for C/C++ or Java Programmers. JavaScript is ubiquitous. It was born from browsers and is now used everywhere. At it's core, it is a decent programming language and it has it's strengths and weaknesses. Much of it's bad reputation came from inconsistent DOM implementations on browsers. However as a language, it is powerful and one of its kind.

As per Atwood's Law proposed by Jeff Atwood:

Any application that can be written in JavaScript, will eventually be
written in JavaScript.

JavaScript is now used to write programs in different areas where no one ever had originally imagined while it was invented for browser.

You may also find it useful to listen to online free video lectures by Yahoo's JavaScript architect Douglas Crockford to get good insights about the history and architectural insights.

I wrote this book based on the notes I had created for myself while learning JavaScript over a period of time.

2   History

It is important to understand the history of JavaScript:

Year Language/Std Author Comments
1995-1996 LiveScript Brendan Eich at Netscape Renamed to JavaScript before release.
1996 JScript Microsoft JScript -- new name to avoid trademark issues. IE 3.0
1997 ECMAScript ECMA-262 Microsoft and Netscape Standardization effort with European Computer Manufacturers Associatin.
1999 ECMA-262 V3   Major Revision. IE 4.0+, Netscape 4.5+
2009 ECMA-262 V5   Major Revision.

3   Installation

You can learn javascript using any browser:

It is also easier to learn javascript using standalone commandline shell:

4   Document Object Model

The primary target audience of JavaScript is Web programmers, both client side and server side. The related standard of interest is DOM, Document object Model.

"Dynamic HTML" is a term to describe the combination of HTML, style sheets and scripts that allows documents to be animated. The W3C standard DOM (Document Object Model) standardizes the object model of XML and HTML documents to be exposed to the scripts.

The W3C DOM specifications provide bindings only to Java and ECMAScript. It would be useful to skim through the ECMAScript bindings provided by DOM standard.

5   Language Overview

JavaScript (or ECMAScript) is Object-based language, not class-based language. The basic language and host facilities are provided by objects. There is a notion of object, properties, attributes, built-in type, primitive value, function object and so on. It is important that we familiarize ourselves with the exact meaning of these terms in the context of Javascript.

Term Definition/Comments
object Unordered collection of properties with zero or more attributes. Example for an attribute is ReadOnly, DontEnum, etc. An object is said to be of type Object.
property Property is used to represent data or function. It could be a primitive value or an object itself. (Note the recursive definition). A property is a property in the context of a 'owning' object. The ownership is not exclusive-- i.e. a single object could be a property of 2 different objects.
builtin-types Following are built-in types: Undefined, Null, Boolean, Number, String and Object. Note that Function is not a separate type-- Function type is a special type of Object type which is callable.
primitive-value Value of the following built-in types: Undefined, Null, Boolean, Number and String.
builtin-objects All built-in types are also built-in objects. In addition, we have Global object, Function, Array, Math, Date, Regexp and error objects Error, EvalError, RangeError, etc. The reason to call these as builtin-objects vs builtin-type is that these are implemented in terms of built-in type Object.
Constructor A constructor is a Function object that creates and initialises objects. Constructor has an associated prototype object that is used to implement inheritance. More on this later.
Prototype Object used to implement inheritance. constructor.prototype refers to the object to be inherited. More on this later.

JavaScript supports prototype based inheritance.

5.1   Understanding typeof Operator

typeof(t) Result
Undefined "Undefined"
Boolean "boolean"
Number "number"
String "string"
Object (native and "object" doesn’t implement [[Call]]) "object"
Object (native and "function" implements [[Call]]) "function"
Object (host) Implementation-dependent

6   Language Tutorial

Following examples are based on using console window using Chrome browser. (Invoke by selecting following options: Tools => Developer Tools => Console).

6.1   Arithmetic operations

> 5 + 10
  15

> Math.pow(2, 5)
  32

> 5/3
1.6666666666666667

> Math.floor(5/3)
1

> 5, 7, 21           # or (5, 7, 21)
  21

> a = b = c = 100
  100

> b = (c=5, d=10, 20)   # Embedded assignment in expression is OK.
  20

> 5 < 10
  true

> 5 && 10
  10               // <== It is not a boolean!

> !! (5 && 10)
  true             // <== Use this to convert expr to boolean.

> 5 || 10
  5

> 5 & 1
  1

> 2 << 5
  64

> typeof 5
  'number'

> aaa
  ReferenceError: aaa is not defined

> 2 * 'some'
  NaN

> a++
  100

> a
  101

> ++a
  102

> a += 10
  112

> 6 + '5'        // Integer promoted to string. Not the other way.
  '65'

> parseInt('123Hello')
123

> parseInt('08')      <== Treats as Octal.
0

> parseInt('08', 10)  <== Use Radix always
8

> a = 10; b = 30 ; eval (' a * b ') ;
300

6.2   String Operations

> 'hello ' + ' world'
  "hello  world"

> typeof 'hello'
  'string'

> a = 'hello world'
> a.<Tab>              # Autocomplete works on node.js shell.

  a.__defineGetter__      a.__defineSetter__      a.__lookupGetter__
  a.__lookupSetter__      a.constructor           a.hasOwnProperty
  a.isPrototypeOf         a.propertyIsEnumerable  a.toLocaleString
  a.toString              a.valueOf

  a.anchor                a.big                   a.blink
  a.bold                  a.charAt                a.charCodeAt
  a.concat                a.constructor           a.fixed
  a.fontcolor             a.fontsize              a.indexOf
  a.italics               a.lastIndexOf           a.length
  a.link                  a.localeCompare         a.match
  a.replace               a.search                a.slice
  a.small                 a.split                 a.strike
  a.sub                   a.substr                a.substring
  a.sup                   a.toLocaleLowerCase     a.toLocaleUpperCase
  a.toLowerCase           a.toString              a.toUpperCase
  a.trim                  a.trimLeft              a.trimRight
  a.valueOf

> a.substring(0,5)
  'hello'
> a.substring(5,11)    # a.slice() also does samething with minor differences.
  ' world'
> a.substr(5,6)
  ' world'
> a.length
  11
> typeof a
  'string'

> b = String(123)          # Convert number to primitive string
'123'

> typeof b
  'string'

> b = String('hello world')  # without new operator, it is primitive type.
> a == b
  true

> c = new String('hello world')   # It is now 'object' not 'string' !
> typeof c
  "object"
> a == c        # Primitive object promoted to String to compare true!
  true

6.3   Array Operations

Array is a built-in object of built-in Object type. It can also be used like a type since it defines a constructor.

> a = [1, 2, 3]
> b = [1, 2, 3]
> a == b
false        #  They are different Objects.


> a.push(4)
[1, 2, 3, 4]

> a.unshift(10)           # Push at front
[10, 1, 2, 3, 4]

> a.shift()               # Pop from font
10

> a.concat(b)             # Creates new list a + b
  [1, 2, 3, 1, 2, 3]

> a                       # a remains unchanged.
  [1, 2, 3]

// Note: There is no built-in a.extend(b) method that will mutate a.

> a + b                   # converts to String and joins.
'1,2,31,2,3'              # To join, use concat

> a = [1, 2, 3, 4, 5, 6]
> a.slice(2,4)            # similar to python a[2:4]
[3, 4]                    # a[2], a[3]

>a.<Tab>
a.__defineGetter__      a.__defineSetter__      a.__lookupGetter__      a.__lookupSetter__
a.constructor           a.hasOwnProperty        a.isPrototypeOf         a.propertyIsEnumerable
a.toLocaleString        a.toString              a.valueOf

a.concat                a.constructor           a.every                 a.filter
a.forEach               a.indexOf               a.join                  a.lastIndexOf
a.length                a.map                   a.pop                   a.push
a.reduce                a.reduceRight           a.reverse               a.shift
a.slice                 a.some                  a.sort                  a.splice
a.toLocaleString        a.toString              a.unshift

> a = [10, 20, 30]
[ 10, 20, 30 ]

> delete a[1]          # delete on array element creates hole using 'undefined'
true

> a
[ 10, undefined x 1 , 30 ]

> a[1]
undefined

> a.length             # length remains unchanged.
3

> a.splice(0, 2)       # Really delete 2 elements starting from index 0.
[ 10, undefined x 1 ]

> a
[ 30 ]

> a = [10, 20, 30]
> for (i in a) console.log(i)     # This prints the keys in array.
  0
  1
  2

> a.some    = 200     # Don't mix non-numeric index into array!
> a['abc']  = 300     # This is same as  a.abc = 300
> for (i in a) console.log(i)
  0
  1
  2
  some
  abc

> for (i in a) console.log(typeof(i))
  string
  string
  string
  string
  string              # All indexes stored as string internally.

> c = new Array(10)   # Array is an object as well as a type!
  [undefined × 10]    # Array.constructor defines the type constructor.

> a = [1, 2, 3]; typeof a
"object"

> a instanceof Array
true

> a.constructor
[Function: Array]

6.4   Object Operations

Object is the only non-primitive built-in type.
> a = { 'one' : 1, 'two': 2 }       # Creating object using literal
> typeof a
  "object"

> for (i in a) console.log(i)
  one
  two

> a = new Object()
  Object               # Chrome displays a clickable, explorable empty Object icon.
  {}                   # node.js shell displays the empty object.

> a.v1    = 200        # Perfect for using as associative array.
> a['v2'] = 300        # It is same as a.v2 = 300
> for (i in a) console.log(i)
  v1
  v2

> F = function() { this.var1 = 100; this.var2 = 200 }
> fobj = new F()              # New object created which becomes 'this' object.
  { var1: 100, var2: 200 }

> a.<tab>             # This autocomplete operation works only on node.js shell.

  a.__defineGetter__      a.__defineSetter__      a.__lookupGetter__
  a.__lookupSetter__      a.constructor           a.hasOwnProperty
  a.isPrototypeOf         a.propertyIsEnumerable  a.toLocaleString
  a.toString              a.valueOf

  a.v1                    a.v2

Note: Object does not contain any enumerable properties, hence suitable
for implementing hash/associative array with string keys.

6.5   Misc operations

> typeof true
"boolean"

> a = [1, 2, 3]
> JSON.stringify(a)            # works for nested object as well.
'[1,2,3]'

> di
{ a: 10, b: 20 }


> JSON.stringify(di)
'{"a":10,"b":20}'

> print(JSON.stringify(di, null, 4))     # Nicely formatted output
{
    "a": 10,
    "b": 20
}

> function f() { console.log('hello world') }
undefined

> f.toString()
'function f() { console.log(\'hello world\') }'

> n = null
> n && n.value       # Use this pattern to avoid Null reference.
null

> null == undefined
  true

> null === undefined
  false

6.6   Input/Output

Examples:

// alert(), confirm(), prompt() work in browsers.
> alert('hello!!!')
> r = confirm('Press Ok or Cancel')
> r
  true   // or false
> console.log('You pressed ' +  (r && 'OK' || 'Cancel'))
> val = prompt('Enter Value ', '0')
> val
> typeof(val)
  'string'

// Following examples work with node.js

> u=require('util');  u.puts('hello!')  // Prints: 'hello!'
> process.stdout.write('hello!')        // Prints: 'hello!'

// readline will be useful in node.js script, not at the command line:
var readline = require('readline');

var rl = readline.createInterface({
   input: process.stdin,
   output: process.stdout,
   terminal: false
});

rl.on('line', function (cmd) { console.log('You just typed: '+cmd); });

7   Common Libraries

7.1   Summary

  • JQuery - Approx 9K lines. Browser independent way of accessing components and manipulating them.
  • JQuery-ui - Approx 15K lines. UI related stuff on top of JQuery.
  • prototype.js - Approx 7K lines. General useful functions. e.g. each(), clone(), etc.
  • Backbone.js - Approx 1500 lines. Small generic util collection to be used on any environment (browser or not). Includes Events, History, etc handling helper functions. Provides basic MVC framework. Requires underscore.js. Can optionally use jquery for view. The model closely resembles Ruby on Rails.
  • underscore.js - Approx 1200 lines. Provides functional programming support without extending any of the built-in JavaScript objects. Used along with Backbone or JQuery. jquery offers only partial support for functional programming.
  • modernizr.js - Approx 1500 lines. Small library to easily manipulate CSS. It is HTML5 and CSS3 aware. Good for progressive enhancement.

Following are complete JavaScript framework libraries, more heavyweight:

  • YUI - Yahoo User Interface Library
  • dojo toolkit
  • mootools - A compact framework with 6000 lines of Javascript code.

Until drupal 7 (PHP based web framework), only jQuery is included in core. Drupal 8 includes backbone.js and underscore.js in it's core.

See Also:

7.2   Node.js Platform

Node.js is a platform to develop standalone JavaScript based applications. Node.js uses an event-driven, non-blocking I/O model.

You can import different modules like below:

var net = require('net');
var server = net.createServer(function(c) { // connection listener ... })

var os = require('os')
console.log(os.hostname())

$  node -e 'var sys = require("sys");   sys.puts("hi world!");
$  node
> util = require('util')     # sys module renamed to util in some versions.
> util.puts('hello')
> print = util.puts
> print('hello')

> mymod = require('/abs/path/to/mymod.js') ;

> u=require('util')
{ format: [Function],
  print: [Function],
  puts: [Function],
  debug: [Function],
  error: [Function],
  inspect: [Function: inspect],
  isArray: [Function: isArray],
  isRegExp: [Function: isRegExp],
  isDate: [Function: isDate],
  isError: [Function: isError],
  p: [Function],
  log: [Function],
  exec: [Function],
  pump: [Function],
  inherits: [Function],
  _deprecationWarning: [Function] }

The other modules include: Cluster, Crypto, File System (fs), HTTP, Net, OS, Readline, etc.

8   Built-in Types

There are only few built-in types. They are:

Note that Function is not a separate type; Function type is a specialization of Object type-- which is callable.

9   Built-in Objects

10   Operators

11   Statements

11.1   Overview

Statements can be of following kinds:

Block              VariableStatement  EmptyStatement    ExpressionStatement
IfStatement        IterationStatement ContinueStatement BreakStatement
ReturnStatement    WithStatement      LabelledStatement SwitchStatement
ThrowStatement     TryStatement

11.2   Block Statement

Examples:

{ x++; y++; }
// Note: There is no block level scope for variables.
var x = 1; { var x = 2; } ;  alert(x); // outputs 2

11.3   Variable Statement

function f() { var i = 10; }  // The i is local, not global variable.
function g() {     i = 10; }  // The i is global.

11.4   Expression Statement

a = 10;      //  (a = 10) evaluates to 10. Expression Statement.

11.5   If Statement

if (x == y)
   f(x)
else if (x > z)
   g(x)
else
   h(x)

11.6   Iteration Statement

Examples:

do   x = f(x);  while ( x < 1000 );
while ( notdone ) { f(x); g(x); }
for (a = b+c; a < 10 ; a++ )  f(a);
for ( var i=0; i < a.length ; i++ ) f(a[i]);
for ( i in a )  f(a[i]);
for ( var i in  (c=a.concat(b)) )  f(c[i]);

11.7   Continue and break Statements

outerloop: while (!finished) {
          f(x);
          innerloop: while (!completed) {
            g(x);
            if (condition_1) continue outerloop;
            if (condition_2) break outerloop;
            if (condition_3) continue;
            if (condition_4) break;
            h(x);
          }
       }

11.8   With Statement (deprecated)

with (obj) {
   a = 10;     // set obj.a = 10  if  obj.a exists ; else set global a=10
   b = 20;     // set obj.b = 20  iff obj.b exists;
}
with (document.getElementById("blah").style) {
  background = "black";
  color = "blue";
  border = "1px solid green";
}
// Because of the confusing semantics it is deprecated.

11.9   Switch Statement

// c-style switch but case expression need not be constant!
x = 'hello'; y = 'hell' ; z = 'o';
switch(x)  // Allows strings
{
   case 1   : console.log('it is 1'); break;
   case y+z : console.log('it is y+z'); break;
   default  : console.log('it is default'); break;
}
// Prints: it is y+z

11.10   Try Catch Finally

You can control the error handling by catching errors that are generated. These are the primary error types:

  • EvalError: Raised when the eval() functions is used in an incorrect manner.
  • RangeError: Raised when a numeric variable exceeds its allowed range.
  • ReferenceError: Raised when an invalid reference is used.
  • SyntaxError: Raised when a syntax error occurs while parsing JavaScript code.
  • TypeError: Raised when the type of a variable is not as expected.
  • URIError: Raised when the encodeURI() or decodeURI() functions are used in an incorrect manner.
  • Error: User defined errors can be thrown using this. e.g: throw new Error('Timeout!');

When user defined errors are thrown, it is typical to throw Error() object, but you can also simply throw anything like just plain string:

throw new Error('Timeout occurred!');
throw 'Timeout!';

Example:

function f() {
  try {
    val = prompt('Enter Option: 1:Throw; 2:return early; 3:Continue;');
    if (val == '1')
         throw  'Option1-Error-thrown'; // finally will execute.
    else if (val == '2')
         return 'early';                // finally will execute before return.
    else if (val > 3)
         throw  new RangeError('Invalid Option');
  }
  catch (err){
     // You can also do... switch (err.name) ... case 'RangeError': ...;
     // if (typeof err == 'string') then err.name == undefined;
     console.log('Caught error name: ' + err.name);
     console.log('Description:' + err);
  }
  finally{
     console.log('Executing finally now...');
  }
  return 'last';
}

12   Functions

A function can be declared like below:

function f(x) { console.log('I am function f. Arg x is ' + x); }

Above declaration is equivalent to following expression:

f = function(x) { console.log('I am function f. Arg x is ' + x); }

Example:

function g(x)
{
   if (x > 10) return;    // return value is undefined
   if (x == 10) return x;
   y = 100;               // y becomes a global variable.
   var z = 200;           // z is local variable.
   { var z = 300; }       // Blocks don't have new scope.
   console.log('z is : ' + z);  // Prints: z is: 200

   // You can call this function as:
   //         g();                // x == undefined
   //         g(10, 20, 30);      // x == 10; Extra args ignored!
   console.log(arguments); // It is array of all arguments passed.
}

// You can use anonymous functions in order to use many temporary variables...
(function(){
    var tmp1 = 1; var tmp2 = 1;
    global_var1 = 100;
    ....
)();
// Above function call creates only one global_var1;
// The other local variables do not corrupt global namespace.

13   Error Handling

See Try Catch Finally

14   Object Oriented Programming

In javascript there is no such thing called class. (Actually the word class is reserved by javascript for future use).

The function definition mechanism is also used to create instances of new objects!

Following example illustrates how to create and use an object in an object oriented style of programming:

> function Car() {  this.wheels = 4 ; this.color = 'red' ; }

> c = Car();          <==  c becomes undefined
> c = new Car();      <==  Get a nice object {wheels:4, color:'red'}

> function Car() {  this.wheels = 4 ; this.color = 'red' ; return this; }

> c = Car();          <==  c gets global object this !!! ; No warnings !!!
c = new Car();
       { wheels: 4, color: 'red' }

Well, so far so good. But, wait! Does the new instance inherit all the properties of the defining function ? It does not. Ok, let us verify:

Car.total_seats = 4
c = new Car();                        <== Does not inherit new properties.
       { wheels: 4, color: 'red' }
c.total_seats
       undefined

If I want the Car to inherit from say Vehicle which defines total_seats, how do I do it ? If you want to follow similar approach in class based languages, you would do

function Vehicle() { this.total_seats = 4; }
v = new Vehicle();

Car.prototype = v;       # By default, every function has "prototype" as empty {}
Car.prototype.constructor = Car;  # This is optional step, but needed to avoid confusions
                                  # during inspection time.

c = new Car();
       { wheels: 4, color: 'red' }    <== By Default does not show parent obj props

c.total_seats                         # However the attribute is there!
       4

How do I see all the attributes of the given object ? You can simply do the following

for (i in c) console.log( i + ' : ' + c[i])
    wheels : 4
    color : red
    total_seats : 4

How can I dynamically add attributes that will be inherited going forward ? The answer is by manipulating the prototype variable of the defining function as we just did earlier. We can either reassign the prototype to new object or just add some additional variables. In the earlier example, we need not have defined Vehicle() function in order to introduce the new variable, we could have simply done:

Car.prototype.total_seats = 4         <== Every Function has "prototype" predefined to {}
c = new Car();                        <== c now inherits the new attribute total_seats
c.total_seats
     4

Given an object, how can I inspect the defining function ? (This question is similar to asking how to find the class of a given object). This is simple. All object instances have a constructor attribute which points to the function used to create the object

c.constructor
       { [Function: Car] }
c.constructor.constructor
       [Function: Function]           <== Leaf constructor/object
c.constructor.constructor.constructor == c.constructor.constructor
       true
c.constructor.constructor.prototype
       [Function: Empty]            <== Equivalent to {}

c.constructor.prototype         // Same as Car.prototype
       { 'total_seats' }

c.constructor.prototype.constructor == c.constructor
       true              <== Usually True unless you have manipulated it otherwise.
                             Remember to set the links right so that the above is always true.

Note: While dumping "prototype" object you may want to skip printing the properties twice,
      by checking  .e.g. if (obj.constructor.prototype == obj) obj = obj.constructor.

Following points worth noting:

Following helper function object() may be defined as follows to quickly create an instance of a derived object of a given object. This is not a perfect or not even recommended way of creating the derived object since inspection of such objects may give confusing details. It is given just to illustrate how prototype mechanism works.

> function  object(o) {   # Example helper function to create derived obj of given obj.
     function F() {}
     F.prototype = o;
     return new F();
  }
> obj = new Object()
> childobj = object(obj)   # childobj is based on parent object obj.

You may find the following question and answer insightful for a good example of setting up the inheritance chain : http://stackoverflow.com/questions/4152931/javascript-inheritance-call-super-constructor-or-use-prototype-chain

15   Closure

16   Design Patterns

17   Window Event Programming

17.1   Example Events

onmouseover, onmouseout

18   AJAX Requests

An example usage:

function handler()
{
    if (oReq.readyState == 4 /* complete */) {
        if (oReq.status == 200) {
            alert(oReq.responseText);
        }
    }
}

var oReq = new XMLHttpRequest();

if (oReq != null) {
    oReq.open("GET", "http://localhost/test.xml", true);
    oReq.onreadystatechange = handler;
    oReq.send();
}
else {
    window.alert("AJAX (XMLHTTP) not supported.");
}

prototype.js defines following function:

var Ajax = {
  getTransport: function() {
    return Try.these(
      function() {return new XMLHttpRequest()},
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
    ) || false;
  },

  activeRequestCount: 0
};

jquery.js sets the global XMLHttpRequest variable if needed using following code:

// If IE is used, create a wrapper for the XMLHttpRequest object
if ( jQuery.browser.msie && typeof XMLHttpRequest == "undefined" )
    XMLHttpRequest = function(){
        return new ActiveXObject(
            navigator.userAgent.indexOf("MSIE 5") >= 0 ?
            "Microsoft.XMLHTTP" : "Msxml2.XMLHTTP"
        );
    };

An example usage from w3schools:

<html>
<head>
<script>
function loadXMLDoc()
{
var xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
  }
xmlhttp.open("GET","ajax_info.txt",true);
xmlhttp.send();
}
</script>
</head>
<body>

<div id="myDiv"><h2>Let AJAX change this text</h2></div>
<button type="button" onclick="loadXMLDoc()">Change Content</button>

</body>
</html>

19   Style Guidelines

Better to use CSS for presentation, HTML for structure and Javascript for interactivity. However, there are cases for which it makes sense to manipulate CSS and html from JavaScript-- this should be kept in minimum.

For accessibility reasons, you may want to define CSS class for hiding like below:

.hide {
   position: absolute;
   top: -9999px;
   left: -9999px;
}

.remove {
   display: none;
}

20   JQuery Basics

  • $(document).ready(fn);

  • Selectors:
    • CSS Style: $('#mycontainer'), $('a'), $('li:first-child'), etc.
    • X-Path: $('a[title]'), $('div[ul]'), etc.
    • Custom: $('li:eq(1)')

20.1   Some Useful Methods

  • DOM Traversal – .parent(), .siblings(), .next() •
  • Manipulation – .html(), .empty(), .append(content) •
  • Events – .ready(fn), .hover(fn1, fn2), .click(fn)
  • Effects – .slideToggle(), .show(), .hide()

20.2   Chaining

       $(‘#someElement’) .parent().parent() .find(‘div.green’)
       .hide().end() .siblings().find(‘div.blue’)
       .show().end() .parent().next()
       .addClass(‘redBorder’);

Show/Hide Example:
      $(document).ready(function() {
             $('a.showhide').click(function() { $(this).parent().parent()
               .find('div.view-data-body') .slideToggle();
               return false;
             });
       });

20.3   jQuery in Drupal

drupal_add_js($data, $type) – Add a JavaScript file,
                 setting or inline code to the page, for example:
drupal_add_js(drupal_get_path(‘module’, ‘mymodule’) .'/myjs.js'); •
drupal_add_js(array(‘myjs’=>$mysettings), ‘setting’);
Drupal_add_js(‘var myVar = “foo”;’, ‘inline’);

20.4   Where do I put my code?

– themers: put your .js file in your theme directory
       and call drupal_add_js(drupal_get_path(‘theme’, ‘mytheme’) . ‘myjs.js’)
       from a tpl file
– module developers: put your .js file in your module directory and call
                      drupal_add_js() before you output content

20.5   Ajaxifying Drupal with jQuery

Basic essentials:
 – jQuery’s .ajax() or .get() method
 - drupal/path – callback function • drupal_to_js($var)
 – Converts a PHP variable into its JavaScript equivalent.

21   Other Advanced Topics

22   FAQ - Frequently Asked Questions

22.1   How to dump object contents in JavaScript ?

  • Use console.log(obj) if it is console.

  • obj.toString() ==> works well if obj is array; but for associative array yields just [Object ]

  • http://phpjs.org/functions/sprintf

  • Use following function. Be warned that it is too noisy:

    function dump(obj)
    {
      var out = '';
      for (var i in obj) { out += i + ": " + obj[i] + "\n"; }
    
      // alert(out);   or ...
      console.log(out);
    
      // or, if you wanted to avoid alerts...
    
      var pre = document.createElement('pre');
      pre.innerHTML = out;
      document.body.appendChild(pre)
    }
    
  • JSON.stringify(obj) (Warning: you may get recursive structure error)

22.2   How to Enumerate all hidden properties/methods ?

for (var i in obj) console.log(i) // This excludes built-in properties.

Possible solutions are:

  • console.dir(), console.log() // Chrome lets you explore Object by clicking.
  • Object.getOwnPropertyNames(obj); // This lists all properties enumerable or not. Object.getOwnPropertyNames(obj.__proto__); Object.getOwnPropertyNames(obj.__proto__.__proto__); // till __proto__ becomes null

Note: getOwnPropertyNames() is part of ECMA v5 specification.

22.4   How to get OuterHTML of DOM element ?

Consider following div DOM element: <div> Hello World! </div>

The element.innerHTML gives you 'Hello World!' without the surrounding <div></div> tags. This attribute is supported by all browsers. However, the outerHTML which includes the full html including the surrounding tags is not supported by all browsers. Getting access to the outerHTML of the given element is bit tricky.

For a good discussion on this topic and some solutions, please See http://stackoverflow.com/questions/2419749/get-selected-elements-outer-html

  • Simplest method:

    console.log(document.getElementsByTagName("head")[0].innerHTML)  // innerHTML
    
    $('.classSelector').html();    // innerHTML using JQuery
    
    // Gives you the outside wrapper as well
    $('.classSelector')[0].outerHTML      // Most browsers support this DOM property.
    
  • Using jQuery + clone:

    (function($) {
      $.fn.outerHTML = function() {
          return $(this).clone().wrap('<div></div>').parent().html();
      }
    })(jQuery);
    
    And use it like this: $("#myTableRow").outerHTML();
    
  • Using jQuery without clone:

    $.fn.outerHTML = function() {
        $t = $(this);
        if ('outerHTML' in $t[0]) {
            return $t[0].outerHTML;
        } else {
            var content = $t.wrap('<div></div>').parent().html();
            $t.unwrap();
            return content;
        }
    }
    
    And use it like this: $("#myID").outerHTML();
    
  • Extend jQuery properly:

    (function($) {
        if (!$.outerHTML) {
            $.extend({
                outerHTML: function(ele) {
                    var $return = undefined;
                    if (ele.length === 1) {
                        $return = ele[0].outerHTML;
                    }
                    else if (ele.length > 1) {
                        $return = {};
                        ele.each(function(i) {
                            $return[i] = $(this)[0].outerHTML;
                        })
                    };
                    return $return;
                }
            });
            $.fn.extend({
                outerHTML: function() {
                    return $.outerHTML($(this));
                }
            });
        }
    })(jQuery);
    
    $.outerHTML($("#eleID")); // will return outerHTML of that element and is
    // same as
    $("#eleID").outerHTML();
    For multiple elements
    $("#firstEle, .someElesByClassname, tag").outerHTML();
    

22.5   How to dynamically Toggle Visibility and Display ?

Using javascript you can choose to hide an element by clicking on it. You can either completely remove it from display or just toggle visibility. Following example code illustrates how to do this

function toggleVisibility() {
  document.getElementById("toggleMe").style.display = "";
  if(document.getElementById("toggleMe").style.visibility == "hidden" ) {
    document.getElementById("toggleMe").style.visibility = "visible";
  }
  else {
  document.getElementById("toggleMe").style.visibility = "hidden";
  }
}
function toggleDisplay() {
  document.getElementById("toggleMe").style.visibility = "visible";
  if(document.getElementById("toggleMe").style.display == "none" ) {
    document.getElementById("toggleMe").style.display = "";
  }
  else {
    document.getElementById("toggleMe").style.display = "none";
  }
}

<p><a href="#" onclick="toggleDisplay();">Click to toggle display.</a> | <a
href="#" onclick="toggleVisibility();">Click to toggle visibility.</a></p>

<div id="toggleMe" style="visibility: hidden;"> Something to Hide and show.
Display collapses it's layout while visibility will keep it's layout.</div>

Note that if you are using JQuery library (instead of plain JavaScript), the code to do the above will be much simpler. For example, toggling will be done by simply writing $('#toggleMe').toggle();

22.6   Treatment of this keyword

The this keyword is a magic keyword which refers to current object. In browser this is global window by default.

> f = function() { console.log(this) }
> f
   // Prints global object window
> obj = { 'one' : 1, 'two' : 2 }
> obj.p = f
> obj.p()
   // Prints obj object

22.7   How to Display definition of the function ?

Short answer is to use toString() function. Given function object f,
the f.toString() gives you the function definition.

> util.puts(util.puts.toString())        # To see definition of function!!!
  function () {
    for (var i = 0, len = arguments.length; i < len; ++i) {
      process.stdout.write(arguments[i] + '\n');
    }
  }

23   Glossary (In progress, Draft, needs cleanup )

V8 Javascript Engine:
 V8 JavaScript Engine is an open source JavaScript engine developed by Google. It ships with the Google Chrome web browser.
SpiderMonkey:First JavaScript Engine developed at Netscape.
PhoneGap:PhoneGap is a mobile development framework to build applications for mobile devices using JavaScript, HTML5 and CSS3,
Ringojs:A JavaScript runtime and shell based on Rhino providing a CommonJS conformant module library and web application framework.

24   References