Sunday 8 May 2016

Iterators and Observers in asynchronous javascript - part 3

Observable of Observables, concatAll, mergeAll, and SwitchLatest


Suppose we have an array of array as given below.

[
    [1], 
    [2, 3],
    [],
    [4]
]
If we want to flatten this two-dimenstional array in to a single-dimensional array, we can use the function concatAll on it. 
[[1], [2, 3], [], [4]].concatAll() will give us [1, 2, 3, 4] which is a new array with all the elments of the two-dimensional array excluding the array with no elements. 

In the same way we can apply concatAll() on an Observable of Observalbles. Observable is data + time i.e., the data arrives over time. Suppose we use the notation given below for an Observable of Observables.

-----------------time----------->
{
    ...{1},
    .......{2................................3},
    ...............{},
    ........................{4}
}.concatAll()

When we call concatAll() on the Observable of Observables above we get a flattened one-dimensional Observable given below. 
{...1....2................................3..4}

The Observable that we called concatAll() is a cold Observalbe and the data inside it is not retrieved from it untill we call forEach on it during the operation of flattening. This means that when we flatten the first inner observable with one item we begin to wait and then we flatten the first element (which is 2) of the second inner Observable and wait until the last element (which is 3) of the second inner Observable arrive. We do not jump and start forEach on the third Observabel although it arrives while we are waiting for the last element (which is 3) in the second inner Observable. We just put that third inner Observable in some buffer and continue waiting for the last element of the second inner Observable. Once forEnd succeeds pushing data from the second inner Observable only then it goes to the next Observable i.e., the third inner Observable. 

When we call forEach on the third inner Observable, the onComplete is fired as it has no element and therefore this Observable does not make in to the single-dimensional Observable. We continue with the next Observable. So the order of arrival of an Observable is preserved in the final single-dimensional Observable and that is why the resultatnt single-dimensional Observable is elongated and has more length showing the waiting time in the buffer for the those Observables that had to wait. 

There are Observables that emit data all the time regardless of that data is consumed or not and you use forEach on the Observable or not. For example an Observable that has data about mouse movement emits data irrespevtive of the fact that you have hooked a handler to capture those events or not for it. You will only start getting those event objects when you hook an event listner to that event. So you must call back the "hot" Observable to get data out of it but it emits data all the time even if you don't use forEach on it. Such Observables are not "cold" and they are called "hot" Observables.

We get a subscription object that has a dispose method for each Observable so that the consumer can call that to stop getting any more data. If we call dispose method on the outer Observable all listening to inner Observables will also stop. And we get the resultant flattened Observable with the data already listened to until that time. Similarly if an error occurs in the inner Observable [2........3] when we read data out of it. Suppose the error occurs after we have read 2 but not 3 then the stream would stop at this point. Remember that an Observable pushes data continuously unless the data finishes or some error occurs or the consumer calls the dispose method to inform the producer that it will not have any more data.

The method dispose does not trigger the method onComplete. If a consumer A sends dispose to the producer the producer makes sure not to send any data to consumer A but it will continue to send data to other consumers. When the producer has finished sending all the data then it will inform other consumers that are still listening that the data has finished but not consumer A.

The function mergeAll behaves differently. It works on the policy of first come first serve unlike concatAll. So in mergeAll() data is not emitted on the basis of the order of arrival of the collections inside rather we emit that data first which arrives first irrespective of which collection it belongs to and we do not buffer collections in a queue.
-----------------time----------->
{
    ...{1},
    .......{2................................3},
    ...............{},
    {........................4}
}.mergeAll()

will give
{...1....2..................4..............3}

In switchLatest we always switch to the latest source of data by sending to the last but one source a message that we don't want to consume any more data from you and we do that by calling subscription.dispose() on the last but one source of data. So the final flattened Observer for the Observer of Observers given above will be {...1....2..................4}.

-----------------time----------->
{
    ...{1},
    .......{2................................3},
    ...............{},
    {........................4}
}.switchLatest()

will give
{...1....2..................4}

We switch to the latest Observable as soon as we get an Observable even if the latest Observable is empty stream and has no data. We do not wait for the arival of data in the latest Observable in order to unsubscribe from the last but one stream of data. Its job is to listen to one Observable at a time. As soon a new inner Observable arrives in the outer Observable it switches to the latest calling dispose method on the Observer it already was listening to.

we can demonstrate how switchLater() can replace takeUntil() plus concatAll() in a code where both do the same thing but with the use of switchLater() the code becomes shorter. First we write the code without using these functions.Note that the code below has a bunch of callbacks and state variables which we later on do not use when we write the code in alternative ways.

function play(movieId, cancelButton, callback) {
    var movieTicket,
        playError,
        tryFinish = function () {
            if(playError){
                callback(null, playError);
            }else if (movieTicket && player.initialized) {
                callback(null, ticket);
            }
        };//internal function that takes no arguments ends here
    
    cancelButton.addEventListener("click", function () {
        playError = "cancel";
    });
    
    if(!player.initialized){
        player.init(function (error) {
            playError = error;
            tryFinish();
        })
    }
    
    authorizeMovie(movieId, function (error, ticket) {
        playError = error;
        movieTicket = ticket;
        tryFinish();
    });
    
}//function play ends here.
We can write the above code using takeUntil and concatAll as shown below. We write this code
using the following things in mind.

What are the collections/streams that I have?
What collections/streams do I want to have?

How do we combine the available collections/streams and compose them so that we get the
streams/collections that we want to have?

We have a stream when somebody clicks the cancel button. We have anoher collection when the movie is successfully authoized and that is a stream/Observable of one that comes back from the server. Another collection is that the player is initialized. All these things are done asynchronously.
So composing the collections above we can get the collection that we want i.e., movies to play stream. Then we can just forEach over this stream and get the movie played. So the stream that we finally get is a stream of authorized ids and it is a cold stream. When we run forEach on this cold stream only then the movie began to play.
Here is a better way to write the code given above.

var authorizations = 
    player.
        init().
            map( () =>
                playAttempts. 
                    map(movieId => 
                        player.authorize(movieId). 
                            catch(e => Observale.empty). 
                                takeUntil(cancels)). 
                    concatAll()).
            concatAll();
        
        authorizations.forEach(
            license => player.play(license),
            error => showDialog("Sorry, can't play right now.")
        );

In the code above when we call player.init(), an Observable is created which does nothing 
untill we call forEach on it because Observables are lazy. When we forEach on them onlly then
the player gets intialized. If the player gets successfully initialized then method next()
is called on the Observable which emits a value which may be true and then onCompleted is 
called as this Observable emits only one element and is therefore called an Observable of 
one. 

playAttempts. line shows that we listen to all the attempts made by the user to play. After
the player has been initialized successfully then we start listening to all the clicks and
make Observables from all those clicks using the method
Observable.fromEvent = function(playButton, click){//......see part 2..}

The map function works on a single Observable in those Observables created above. Each click
by the user is a click on a movie with some movieId and that is passed to the map function
one by one. This mapping function checks if this user is authorized to watch thie movie with
this id. So the map function returns a stream of decryption keys, one decryption key for 
each movieId that is authorized to this user. So for each movieId we substitute that movieId 
with a network request to get back a decryption key. Remember Observable is lazy so we do not
send the request to server at this point but we make the Observable replacing the movieId with
a request to the server for decryption key. So we are three levels deep at this point in the 
code. For every initialized player (even if it is one player that is actually initialized) we
make another stream of playAttempts and then for all the playAttmepts we make another Observable
for each movieId replacing it with a network request for decryption key. So we have to make
two concatAll to get a one-dimensional Observable as one call to concatAll can flatten only
two levels of Observables i.e., n numbers of Observables embedded one level deep inside 
another Observable and once we get the flattened Observable then we take the next Observable
and concatAll it with this one.

.catch() passes an error to a function and that function can optionally return an Observable
to resume from.  Observale.empty() is an Observable that has nothing to emit so when onNext()
is called on it, it sends onComplete directly. The line catch(e => Observale.empty) is just
like a try/catch with empty body of the catch block. We are only catching errors on attempts
to authorization for movieIds. We are not catching errors on player initialization in the 
code here. So if the catch in the code above gets an error the whole stream will not be 
stopped rather the catch will pass the error to a function and that funciton might return 
an Observable which can be concatenated with the existing stream and the error will not 
bubble up all the way. 

 


Saturday 7 May 2016

Iterators and Observers in asynchronous javascript - part 2

Iterators and Observers in asynchronous javascript


You can think of Observable as a DOM event where you pass three handlers instead of one handler.


  1.  Step 1: The first handler is for getting the next data. It is equivalent to calling the next() method on an iterator to consume the next data. But in the iterator pattern it is the consumer that is the in-charge of the game. The consumer decides when to consume more data by calling the next() method. But in the Observable here it is the producer of the data that is in-charge and decides when to push new data to the consumers.
  2. Step 2: The second handler is optional and handles a siutation when an error occurs. The Observable pushes information to consumers that an error has occurred so that consumers know what is going on. It is equivalent to the phenomena of throwing error in the iterator pattern where the producer throws error when the consumer calls next() mehtod AND there is an error. But the consumer's action of calling the next() method causes the throwing of the error by the prouducer, so the consumer is incharge in the iterator pattern. Here in the Observable it is the producer who is inchage and decides to inform the consumers that an error has occured without any action on the part of consumers.
  3. Step 3: The thrid step is that the producer informs the consumer that it has no more data for the consumers. The producer is the in-charge and pushes out the information to the consumers that it has no more data for them. It is equivalent to the operation in the iterator pattern when the method next() is called and the producer sends the done: true to indicate that it has no more data. But in the iterator method it is the consumer whose calling of next() on the iterator causes this sending of done: true to indicate that the end of data. In the Observable it is the producer who pushes the information without any action on the part of consumers. This is an optional handler in the Observable.

 
    //Here is an Observable
    //The function fromEvent has been used rom the RxJs library to make the Observable.
    //element could be a button, a link, the document itself or any other element in the DOM.

var mouseMoves = Observable.fromEvent(element, "mouseMove");

 Using the forEach on the Observable the same way we do it on an array but array is blocking and we don't want blocking. In an Observable data arrives over time and with the arrival of the data the forEach works on the freshly arrived data.

//subscribe
    var subscription = mouseMoves.forEach({
        //step 1. next data
        event => console.log(event), /* event is the argument that the function gets whereas the function's body is on the right hands side of =>.*/
        //step 2. error occurs - optional step
        error => console.error(error), /* error is the argument that the function gets whereas the function's body is on the right hand side of =>.*/
        //step 3. data transfer completed - no more data - optional step
        () => console.log("done. No more data.") /* No argument to the function is represented by () and the body of the function handles what to do.*/
    }
    );
     
 If you want to consume the data inside an Observable then you have to make an object Observer with three handlers. Then hand the Observer object to the Observable and the Observable will push data into the Observer object and by extension your call backs in the Observer object.

 In the code below we are passing an object to the Observable mouseMoves. In th object we have name: value pairs for all the three steps discussed earlier. In the code above we just passed three functions to the Observable mouseMoves and not an object.

var subscription = mouseMoves.forEach({
   
      onNext: event => console.log(event),
      onError: error => console.loge(error),
      onCompleted: () => console.log("done")
   
  });
  //unsubscribe
  subscription.dispose();

/*******************************************************************************/
//Here is the method fromEvent

/* Converting Events to Observables. */
//fromEvent is a static method in the Observable.
Observable.fromEvent = function(dom, eventName){
    //returning Observable object
    return{
        forEach: function(observer){
            /* observer is an object with three things 1. onNext to push more data 2. onError to push error message 3. onCompleted to push "done" to consumers.*/
            var handler = (e) => observer.onNext(e);
            dom.addEventListener(eventName, handler);
            //returning Subscription object
            return{
                dispose: function(){
                    dom.removeEventListener(eventName, handler);
                }
            };
        }
    };
}

Iterators and Observers in asynchronous javascript - part 1


Functions map, filter, forEach, takeUntil and concatAll

Suppose we have an array [1, 2, 3] and we want to add 1 to all its elements, we can use the function map to do so.

[1, 2, 3].map( x => x + 1 );

This gives a new array [2, 3, 4]. Remember function map does not change the original array. It transforms the original array and makes a new array with new elements.

Now if we want to filter an array we can use the function filter(criteria for filtering the array).
[1, 2, 3, 4].filter(x => x > 2);

This gives a new array as filter does not change the original array. It makes a new array and copies only those elements in that array that passes the test to make it in to the new array. After applying the filter above we get [3, 4].

Here is another example.

var getOnlyTopRatedMovies = userName =>
userName.playLists.
    map(playList =>
        playList.videos.
            filter(video => video.rating === 5.0)
           ).concatAll();
         
getOnlyTopRatedMovies(userName).
forEach(movie =>
    console.log(movie));


concatAll will flatten the two-dimensional array in to a one-dimensional array. concatAll only works on Observable of Observables and not on a single Observable. We don't want to use concatAll on an Observable that has infinite Observables as we will not be able to flatten them as the data inside the infinite Observable never ends. An analogy of such a situation would be traffic situation where there are three lanes and one lane is under repair so we are left with two lanes. We can't use a strategy that involves allowing traffic from one lane first until all the vehicles are finished and then allowing vehicles from the other lane because arrival of the vehicles on the lanes never finish and will create a blocking situation for one of the lanes. We have a liste of generes and then we have a list of all the films in that genre.



For each userName (user) we have an array representing all the generes allowed to that user. Then wihin each genre we have list of movies belonging
to that genre. So it makes a two-dimensional array. In the script above we loop on those genres and one by one and pass a list of movies in a genre
to the operator map to make a new array and copy those film names in to the new array that pass the criteria described in the function inside the
operator filter. So we get a two-dimensional array of all films that have been rated 5.0 and next will the function concatAll make a one-dimensional
array out of it. Next the forEach function will print them to the console one by one.

None of the functions used above alter the original array. map, filter, concatAll, forEach does not change the array they work on. They just
make new copies.

In the code below we are using the function takeUntil instead of filter but its function is the same as that of the filter.


Mouse Drags Collection

This code creates  a stream of all the mouseDrags events that occur on an elment in the DOM. We pass that DOM element to the function getElmentDrags.

A mouse drag is a series of events that happen between a mouse down and a mouse up. We will show how we can compose simple events to make new and more complex events using methods like filter, concatAll, map, takeUntil etc.

//elmt could be any elment e.g., a button , a picture etc.
var getElmentDrags = elmt => 
elmt.mouseDowns.
/* map functin is all about replacing. We want to replace mouseDown events
with all the mouseMoves event that occur between the mouseDown event and mouseup event.
    */
map(mouseDown =>
/* For each mouseDown we are detecting the mouseMoves on the document level
  untill the event mouseup occurs. For each mouseDown we are going to put
  in the stream a collection of all the mouseMoves events untill the event
  mouseUps occurs. So we are taking each item (mouseDown) in a collection (mouseDowns) and replacing it with another collection (mouseMoves) in the stream.
*/
document.mouseMoves. 
takeUntil(document.mouseUps)). 
/* So now we have a two-dimensional array as we an array of arrays that have
mouseMoves events between mouseDown and mouseUps events. We can flattern       this two--dimensional array in to a single-dimensional array using concatAll.
*/
concatAll();

getElmentDrags(image).forEach(pos => image.position = pos);

/* Here in forEach we are now consuming the data that we created in the collection above and
doing something wit that data. Here we are moving the position of the image so that
the image actually drags around.
       */

Here is the complete code for Mouse Drags Collection.
var getElementDrags = elmt => {
 elmt.mouseDowns = Observable.fromEvent(elmt, 'mousedown');
 elmt.mouseUps = Observable.fromEvent(elmt, 'mouseup');
 elmt.mouseMoves = Observable.fromEvent(elmt, 'mousemove');
 return elmt.mouseDowns.
  map(mouseDown =>
   document.mouseMoves.
    takeUntil(document.mouseUps)).
  concatAll();
};
//using forEach we now consume the data generated above and stored in the flattened Observable created by concatAll.
getElementDrags(image).forEach(pos => image.position = pos);

//Here is the method fromEvent

/* Converting Events to Observables. */
//fromEvent is a static method in the Observable.
Observable.fromEvent = function(dom, eventName){
    //returning Observable object
    return{
        forEach: function(observer){
            /* observer is an object with three things 1. onNext to push more data 2. onError to push error message 3. onCompleted to push "done" to consumers.*/
            var handler = (e) => observer.onNext(e);
            dom.addEventListener(eventName, handler);
            //returning Subscription object
            return{
                dispose: function(){
                    dom.removeEventListener(eventName, handler);
                }
            };
        }
    };
}

The takeUntil works like a filter as we are reducing the number of mouseMoves events by
recording only those events that are between mouseDown and mouseUps events. So takeUntil
recudces the number of items in a collection just like filter does.

We can diagrammatically show the takeUntill as below. We are using the notation {...1..2.....3}
to denote an Observable which is a stream in which the data arrives over time. In the diagram below {......1......2...........................3} is the source collection from which we want to consume data and {........................4} is the stop collection which means that we do not want to consume more data from Observable {......1......2...........................3} as soon as the Observable {........................4} has some data to be consumed by us.

-------------------------time-------------------->
{......1......2...........................3}.takeUntil(
{........................4})

gives the Observable
 {......1......2........}

The Observable {......1......2...........................3} pushed data and we have a filter takeUntil which consumes data from this Observable until the second Observable {........................4} arrives at which point takeUnitl stops consuming more data from the first Observable. takeUntil() consumed 1 and 2 when 4 arrives and at that point it stops consuming more so 3 does not make it in the newly created Observable created by function takeUntil(). Therefore, the resultant Observable has data 1 and 2 only.

This approach makes the unsubscribing from consuming data manually by calling unsubscribe redundant. Normally we consume data until some event is fired (e.g., mouse is moved etc.) and then we unhook our handler once the event is fired. In the takeUntil approach we do not need to call unsubscribe to unsubscribe from events. Create streams of data that complete when you want them to.  Create new events from existing events and make those new events end when you want them to end. Use takeUntil() to do this.

We do not wait for the onComplete to happen in the stop collection rather we stop consuming data from the source collection as soon as onNext() happen in the stop collection i.e., as soon as the stop collection has some data to be consumed for us and we call onNext() on it to consume that data. At this point the first Observable will call onCompletion to indicate that it is not going to push more data. Since we are not interested int he data from the stop collection, therefore, at this point method dispose() will be called on the stop collection.

If the stop collection or the source collection hits an error then the outer Observable (i.e., the Observable that we are creating) will end with that error. We always forward along the errors.

Note: concatAll does not exist on an array in javascript but you can write the function yourself.

Saturday 9 April 2016

The strict mode in javascript

//strict mode in js
var actNow = function(){
 'use strict';
    newVariable = 9;
};
actNow();/* Uncaught ReferenceError: newVariable is not defined. */
/* Due to strict mode we have to define the variable newVariable with keyword var as the strict mode will not allow us to place the variable in the global scope. */
/* If you use 'use strict' mode in the global space while using thir party libraries you may face problems if the those libraries are not meant to be used in the strict mode. */

//*******************************************************
var actNow = function(){
 //'use strict';
    newVariable = 9;
};
actNow();
/* Here we have commented the line with the strict mode so we get no error from this snippet and the variable will be placed in the global space. */

//*******************************************************
//The 'delete' operator removes a variable from the context
var actNow = function(){
 var newVar = 9;
    delete newVar;
};
actNow();//No error and the code works.
//*******************************************************
//The 'delete' operator is not allowed in the strict mode.
var actNow = function(){
 'use strict';
 var newVar = 9;
    delete newVar;
};
actNow();/* Uncaught SyntaxError: Delete of an unqualified identifier in strict mode. */
/* If we declare a variable in strict mode, we can't get rid of it. */
//*******************************************************
/* The following code gives no error as we are not in strict mode inspite of the fact that both the arguments have the same name.
*/
var actNow = function(){
    var fn = function(x, x){
     //Do something here.
    };
};
actNow();//no error

//*******************************************************
var actNow = function(){
 'use strict'
    var fn = function(x, x){
     //Do something here.
    };
};
actNow();
/* Uncaught SyntaxError: Duplicate parameter name not allowed in this context */
//*******************************************************
'use strict';
var obj ={};
with(obj){
 console.log('using with statement');
};
//*******************************************************

Friday 8 April 2016

Some global functions in javascript

Some global functions in javascript


var value = parseInt('1234');
console.log(value);
var value = parseInt('b1234');
console.log(value);
var value = parseInt('12b34');
console.log(value);//When a NaN is hit it stops further parsing but 12 is shown on the console
var value = parseInt('1234.9');
console.log(value);//1234 - It ends parsing when it hits the decimal point. Doesn't do rounding for us.
var value = parseInt('C000', 16);//16 is the base/radix so c000 is a hexadecimal number.
console.log(value);

var value = parseFloat('1234.999');
console.log(value);//1234.99
//Parsing the float with exponential number.
//Move the decimal to one place to the left
var value = parseFloat('1234e-1');
console.log(value);//123.4

var value = isFinite(Number.POSITIVE_INFINITY);
console.log(value);//false

var value = isFinite(Number.NEGATIVE_INFINITY);
console.log(value);//false

var value = isFinite(42);
console.log(value);//true

var value = isFinite('42');
console.log(value);//true

var value = isNaN(NaN);
console.log(value);//true

var value = isNaN(3 / 0);
console.log(value);/* false because isNaN(infinity) is false. Most of the other programming languages will give an exception when dividing a number by zero but js does not give exception. */

var value = isNaN(Number.POSITIVE_INFINITY);
console.log(value);//false

var value = isNaN(Number.NEGATIVE_INFINITY);
console.log(value);//false

var value = isFinite( 3 / 0);
console.log(value);//false because 3 / 0 gives infinity

var path = "\\start\\";
console.log(encodeURI(path));//%5Cstart%5C

var path = "\\start\\+";
console.log(path);//\start\+
var path = "\start\+";
console.log(decodeURI(path));//start+

var path = "\\start\\";
console.log(encodeURIComponent(path));//%5Cstart%5C

var path = "\\start\\+";
console.log(encodeURIComponent(path));//%5Cstart%5C%2B
var path = "%5Cstart%5C%2B";
console.log(decodeURIComponent(path));//\start\+

/* The following global function should be avoided as it opens systems to injection attack and other attacks. */
var globalVar = 'qwerty';
var code = 'console.log(globalVar);';
eval(code);

The Math object in javascript - some important functions

The Math object in javascript - some important functions


//Math object in js
console.log(Math.PI);
console.log(Math.abs(-36));
console.log(Math.ceil(23.12));//24
console.log(Math.floor(23.99));//23
console.log(Math.trunc(34.67));//34
console.log(Math.max(0,67,-3,"99"));//99 the string is converted implicitly to a number
console.log(Math.min(-23, 0,56));
console.log(Math.pow(3,4));//81
console.log(Math.random());//between 0 and 1
console.log(Math.sqrt(64));
console.log(Math.sqrt(-64));//NaN

the string object in javascript - some important functions

The string object in javascript - some important functions


//Some important functions in the string object in js
var value = 'Some string';
console.log(value.charAt(6));//t
console.log(value.concat(' concatenated with this one.'));
console.log(value.includes(' '));
console.log(value.endsWith('ing'));
console.log(value.endsWith('ing '));/* false - There is a space at the end which is not trimmed by function endsWith() */
console.log(value.indexOf('r'));
console.log(value.indexOf('Z'));//-1 as Z is not found in the string value
console.log(value.lastIndexOf('s'));//starts at the end of the string and goes backwards
console.log(value.slice(5));//string - start at index 5 and return a slice of the original string
console.log(value.slice(5, 8));//str - start at index 5 and returna slice up to but not including index 8
//Give me the final 3 characters starting from the end of the string
console.log(value.slice(-3)); // - ing - negative argument shows starting backwards.

//Splitting a string into an array
var str = "This is a string that we will split into an array on the basis of a space character and has 22 words.";
console.log(str.split(' ').length);//22 because we are splitting using a space and that makes it 22 elements
console.log(str.substr(40, 9));//an array - start at index 40 and return 8 characters.

/* If you want a string that starts at index i and ends at index j but j is not included then use str.substring(i, j) function instead of substr(beginningIndex, numberOfCharactersToReturn) function.
*/
console.log(str.substring(40, 65));//character at 65 is not included.

Event bubbling in javascript

Event bubbling and capturing

Event bubbling and capturing are two ways of event propagation in the HTML DOM API, when an event occurs in an element inside another element, and both elements have registered a handle for that event. The event propagation mode determines in which order the elements receive the event.
With bubbling, the event is first captured and handled by the innermost element and then propagated to outer elements.
With capturing, the event is first captured by the outermost element and propagated to the inner elements.
Capturing is also called "trickling", which helps remember the propagation order:
trickle down, bubble up
Back in the old days, Netscape advocated event capturing, while Microsoft promoted event bubbling. Both are part of the W3C Document Object Model Events standard (2000).

Here is the html:

<div id="div1" class="element1">The blue square <div id="div2" class="element2"> The red square </div> </div>

Here is the css:

.element1{
  background-color: blue;
  height: 200px;
  width: 200px;
  position: relative;
  top: 2px;
  left: 20px;
}
.element2{
  background-color: red;
  height: 100px;
  width: 100px;
  position: relative;
  top: 40px;
  left: 50px;
}

Here is the javascript:

/* Event bubbling. */
/* The html used in this js file is given in the html file. */
var div1 = document.getElementById('div1');
var div2 = document.getElementById('div2');
var clickHandler = function divClickHandler(event){
console.log(this.id);
};
div1.addEventListener('click', clickHandler, false);//bubbling
div2.addEventListener('click', clickHandler, false);//bubbling
/* 
The false as the thrid argument in the method call above causes the bubbling. First event is handled
by div2 and then it it is bubbled to its parent div1. If we want it the other way round i.e., we wnat div1
 to handle the event first and then bubble it to div2 then we need to set the boolean value to true as the
 thrid argument in the call to addEventListener().
 */
div1.addEventListener('click', clickHandler, true);//capturing
div2.addEventListener('click', clickHandler, true);//capturing

/* If we wnat the event to be handled by the parent but not by the child then we can stop the propagation of 
the event by using method stopPropgagation() as shown below. In this case the parent will handle the event 
and stop further propagation of the event to the child. 
*/
var div1 = document.getElementById('div1');
var div2 = document.getElementById('div2');
var clickHandler = function divClickHandler(event){
console.log(this.id);
    event.stopPropagation();
    /* 
    If we want to prevent the default action when something is clicked then we include the followin one line of   code also. 
    */
    event.preventDefault();
};
div1.addEventListener('click', clickHandler, true);//capturing
div2.addEventListener('click', clickHandler, true);//capturing

Thursday 7 April 2016

The Event Object in javascript


The event object in javascript is created by the javascript runtime engine which gets passed to an event handler. Here are some key properties of this object:

1. bubbles - true or false - based upon whether this event bubbles up to their parents or not.

2. cancelable - true or false - will let us know whether we can cancel any kind of propagation of this event.

3. currentTarget - is the DOM (Document Object Model) element that we are currently looking at.

4. defaultPrevented - true or false - tells us if preventDefault() was called.

5. detail - This property holds extra information about the event.

6. eventPhase - 1/2/3 - 1 means that it is the capture phase which is the opposite of bubbling - going in the other direction of bubbling. 2 means that we are currently at the target. 3 means that we are in the process of bubbling.

7. preventDefault() - To prevent the browser from executing any default behavior. An example would be preventing the submit button on a form submit the form. Another example would be preventing the browser following a link in an anchor tag.

8. stopPropagation() - will stop all event-capturing and bubbling.

9. stopImmediatePropagation - will stop all event-capturing and bubbling but will also make sure that no more handlers get called.

10. target - the original target of this event. For example if we click on a button and the event bubbles up from parent to parent to parent, target will be set to that original button.

11. trusted - true or false - true if event comes from the browser. false if event is triggered through the javascript code written by the programmer.

12. type - name of the event. For example it would be the string "click" for a click event.

Query selectors in javascript

Here is the html code that will be used in the javascript on this page.

<article id="article1" class="my-custom-class">
    <h3>
        Title of the page goes here.
    </h3>
    <p>
        This is paragraph one.
    </p>
    <p class="special">
        This is paragraph two.
    </p>
    <p class="special">
        This is paragraph three.
    </p>
</article>

Here is the javascript code that uses the html code above.

//Query selectors
/* 
Use MDN, the Mozilla Developers Network to learn more about other functions and properties.
 */
var element = document.querySelector('article');
console.log(element);//prints on the console the complete article tag
var element = document.querySelector('#article1');
console.log(element);
//Getting only the first paragraph
var element = document.querySelector('.special');
console.log(element);
//Getting all the paragraphs in the document
var elements = document.querySelectorAll('.special');
console.log(elements);

Document object in javascript - introduction

Here is the html code that has been used in the javascript code on this page.

<article id="article1" class="my_new_class">
    <h3>
        Demonstrating how to get an element fron an html document in javascript
    </h3>
    <p>
        This is paragraph one.
    </p>
    <p>
        This is paragraph two.
    </p>
    <p class="new_point">
        This is paragraph three.
    </p>
    <p class="new_point">
        This is paragraph four.
    </p>
</article>

Here is the javascript code that uses the html code above.

var element = document.getElementById('article1');
console.log(element);//We get the element in the document that has id=article1
var elements = document.getElementsByTagName('p');
console.log(elements);//We get an array of all the elements that has a tag of p i.e., paragraph
var element = document.getElementsByTagName('h3');
console.log(element);//We get an array of all the elements with heading set to h3
var elements = document.getElementsByClassName('new_point');
console.log(elements);//We get an array of our two paragraph elements with class=new_point

//***************************************************************************
/* 
Once we get an element from a document then we can get access to any of its attributes also. 
*/
var e = document.getElementById('article1');
console.log(e.getAttribute('class'));//my_new_class

//We can dynamically set an attribute also. 
e.setAttribute('class', 'my_old_class');
console.log(e.getAttribute('class'));//my_old_class

//We can get all the child nodes of an element.
console.log(e.childNodes); /* We get on the console
[text, h3, text, p, text, p, text, p.new_point, text, p.new_point, text]
the array has text 6 times because we have spaces before the h3, and all the paragraph elements and white space is represented as text. */

The location object in javascript

/* 
The location object lets us look at the browser's URL location. 
*/

console.log(location.href); // https://fiddle.jshell.net/_display/

console.log(location.host); //fiddle.jshell.net

console.log(location.port); //port number

console.log(location.protocol); // https:


//redirecting to another page/website but it depends on your browsing settings.
location.assign('https://www.google.com');//directs browser tot he page passed as argument.

System Dialogs in javascript - alert, confirm, and prompt

//System dialogs
//1. alert
alert('Hello jsfiddle.net');


//2. confirm - with ok and cancel button ok button for the if is true case and cancel button for the else case 
if(confirm('Do you want to leave this page?')){
 console.log('You chose to leave the page.');
}
else{
 console.log('You chose to stay on the page.');
}

//3. prompt - with an ok and a cancel button
var input = prompt('Enter Your address please!');
if(input != null && input != '')
 console.log(input);
else
{
 console.log('You did not enter any address');
}

timer in javascript

//Timer related code snippets in js
console.log(new Date().getSeconds()); //e.g., 49 seconds
/* function setTimeout() is a global object window and we do not need to prefix it with window.*/
setTimeout(function() {
  console.log(new Date().getSeconds());
 }, 1000
);/* 1000 milliseconds of delay should be observed before calling the function setTimeout after the internal function has been called. */
/* I got 
6
7
because there were 6 seconds in to the minute and then it was 7 seconds into the minute. Note that the 7 appears after an 
interval of 1 second after the 6 appears on the console. If I delete the ', 1000' then I will 
instead get
6
6
as no delay is being observed. 
*/

//*******************************************************
console.log(new Date().getSeconds());
/* Assigning the id of the timer to a variable so that we use that id later on to clear the timer and prevent it from being activated. */
var id = setTimeout(function(){
  console.log(new Date().getSeconds());
 }, 1000
);
clearTimeout(id);
/* After executing the code above we get only one number as our timer is prevented being activated by the clearTimeout() method.
*/
//*******************************************************
/* In the code snippet given below we pass a funciton to method setInterval() and that internal function will be called over and 
over again untill the if condition is true and it is then when the function clearInterval(id) will be called to stop calling the 
internal function.
*/
console.log(new Date().getSeconds());
var id = setInterval(function(){
  var seconds = new Date().getSeconds();
        console.log(seconds);
        if(seconds === 30)//shutting down the timer when there are 30 seconds into the minute
         clearInterval(id);//id exists in the outer function.
 }, 1000
);
//*******************************************************


Window object in javascript

console.log(window.screenLeft + ', ' + window.screenTop);//0,0 but depends on where the window is positioned on your screen
/* innerWidth is where your html document is showing. The brower ususall has some kind of frame and that is included in the outer width. */
console.log(window.innerWidth + ', ' + window.outerWidth);//100, 1280 
window.open('http://www.google.com', '_blank');/*Popup might be blocked so you will not get a new window but might get an indication that a poping up window has been blocked.*/

Recursive functions in javacript - an introduction

//Recursion in javascript 
//functions
/* Making a json object that uses anonymous function instead of a named funciton
which causes problem in a scenario in which we make another variable ftn2 to 
point to the same function ftn by assigning ftn2 to ftn. Then we set ftn to null
and we lose our reference to the recrusive call to ftn inside the funciton ftn. 
If we use a named function then the problem gets solved and recursion works. 
*/
var orgChart = {
    name: 'Dilshad',
    subordinates: [{
        name: 'Rafaqat',
        subordinates: [{
            name: 'Sardar',
            subordinates: []
        }, {
            name: 'Shaukat',
            subordinates: []
        }]
    }]
};
//Writing an anonymous function that uses recursion.
var ftn = function(topEmployee) {
    console.log(topEmployee.name);
    console.log('Number of subordinates of ' + topEmployee.name + ': ' + topEmployee.subordinates.length);
    /* 
      Calling itself recrusively for each employee to check it s(he) has subordinates. 
      */
    for (var i = 0; i < topEmployee.subordinates.length; i++){
     console.log(topEmployee.name + "'s subordinate # " + (i + 1) + ": ");
        //Recursive call to ftn in the line below.
        ftn(topEmployee.subordinates[i]);
    }
};
//calling the funciton ftn and passing it the json object representing the organization chart.
//**********************************
//ftn(orgChart);
//**********************************
/*
Here is the output of the function above:
Dilshad
Number of subordinates of Dilshad: 1
Dilshad's subordinate # 1: 
Rafaqat
Number of subordinates of Rafaqat: 2
Rafaqat's subordinate # 1: 
Sardar
Number of subordinates of Sardar: 0
Rafaqat's subordinate # 2: 
Shaukat
Number of subordinates of Shaukat: 0
*/
//The problem with the anonymous function above starts when we do the following two lines.
//**********************************
//var ftn2 = ftn;
//ftn = null;
//ftn2(orgChart);
//**********************************
/*
We get an error after the first top employee of the organization chart as shown as the recursive call fails because we have set ftn to null and we are still calling it in the recrusive call inside the body of the function. 

Dilshad
Number of subordinates of Dilshad: 1
Dilshad's subordinate # 1: 
Uncaught TypeError: ftn is not a function
*/
/*
 The solution is simple - use a named function instead of an anonymous funciton as shown below:
*/

//Writing a named function that uses recursion.
var ftn = function showAllEmployees(topEmployee) {
    console.log(topEmployee.name);
    console.log('Number of subordinates of ' + topEmployee.name + ': ' + topEmployee.subordinates.length);
    /* 
      Calling itself recrusively for each employee to check it s(he) has subordinates. 
      */
    for (var i = 0; i < topEmployee.subordinates.length; i++){
     console.log(topEmployee.name + "'s subordinate # " + (i + 1) + ": ");
        //Recursive call to ftn in the line below.
        showAllEmployees(topEmployee.subordinates[i]);
    }
};

/* Now the code works even if we do the following. */
var ftn2 = ftn;
ftn = null;
ftn2(orgChart);
/* But don't forget to comment the lines above which were causing errors. The lines between 
//********************************** and //**********************************
 should be commented
*/



Here is the output on the console:

Dilshad
Number of subordinates of Dilshad: 1
Dilshad's subordinate # 1: 
Rafaqat
Number of subordinates of Rafaqat: 2
Rafaqat's subordinate # 1: 
Sardar
Number of subordinates of Sardar: 0
Rafaqat's subordinate # 2: 
Shaukat
Number of subordinates of Shaukat: 0

Immediately invoked function expressions (IIFEs)

//IIFEs - Immediately invoked function expressions
//IIFEs don't pollute the global environment.
(function(){
 console.log('Executed!');
})();
//*************************************************************
/* We can move the last pair of parenthesis () before the semicolon inside the parenthesis containing hte whole function. This works the same way as the
code snippet given above. 
*/
(function(){
 console.log('Executed again!');
}());
//*************************************************************
//IIFEs don't pollute the global environment.
(function(){
 var employeeName = 'Jack';
})();
/* The linew of code below will give error as employeeName has been declared
with keyword var inside the function so it does not pollute the global 
namespace. Its scope is limited to the function only. */

/* console.log(employeeName);//Uncaught ReferenceError: employeeName is not defined
*/
//*************************************************************
/* app in the code below is an object that is empty here but in a real
app it will be populated. Most of the libraries in js has
a global variable e.g., $ in jQuery. An application has often a variable
in the global namespace called app. */
var app = {};
(function (ns) {
 ns.name = 'None';
})(app);//Passing the global variable app as an argument to the IIFE function.
console.log(app.name);//None
//*************************************************************
var app = {};
var jQuery = {};
/* The way we pass jQuery as a second argument to the IIFE guarantees that
the jQuery === $ (the dollar sign). */
(function (ns, $) {
 ns.name = 'None';
  console.log($ === jQuery);//true
})(app, jQuery);
//*************************************************************
/* To make sure that the system's undefined object is set to the undefined 
object we do as given below: */
var app = {};
var jQuery = {};
(function (ns, $, undefined) {
 ns.name = 'None';
  console.log(undefined);//undefined
})(app, jQuery);
//*************************************************************
//We can also use +, -, or ! with the keyword function instead of parentheses
+function(){
 var employeeName = 'Jack';
  console.log('Executed!');//Executed
}();
console.log(employeeName);//Uncaught ReferenceError: employeeName is not defined.
//*************************************************************

Wednesday 6 April 2016

Using anonymous functions might give problems if used recursively in javascript - an example scenario

Recursive functions in javascript

Making a json object that uses anonymous function instead of a named funciton which causes problem in a scenario in which we make another variable ftn2 to point to the same function ftn by assigning ftn2 to ftn. Then we set ftn to null and we lose our reference to the recrusive call to ftn inside the funciton ftn. If we use a named function then the problem gets solved and recursion works.

// Making a json object that uses anonymous function 
var orgChart = {
    name: 'Dilshad',
    subordinates: [{
        name: 'Rafaqat',
        subordinates: [{
            name: 'Sardar',
            subordinates: []
        }, {
            name: 'Shaukat',
            subordinates: []
        }]
    }]
};
//Writing an anonymous function that uses recursion.
var ftn = function(topEmployee) {
    console.log(topEmployee.name);
    console.log('Number of subordinates of ' + topEmployee.name + ': ' + topEmployee.subordinates.length);
    /* 
      Calling itself recrusively for each employee to check it s(he) has subordinates. 
      */
    for (var i = 0; i < topEmployee.subordinates.length; i++){
     console.log(topEmployee.name + "'s subordinate # " + (i + 1) + ": ");
        //Recursive call to ftn in the line below.
        ftn(topEmployee.subordinates[i]);
    }
};
//calling the funciton ftn and passing it the json object representing the organization chart.
//**********************************
//ftn(orgChart);
//**********************************
/*
Here is the output of the function above:
Dilshad
Number of subordinates of Dilshad: 1
Dilshad's subordinate # 1: 
Rafaqat
Number of subordinates of Rafaqat: 2
Rafaqat's subordinate # 1: 
Sardar
Number of subordinates of Sardar: 0
Rafaqat's subordinate # 2: 
Shaukat
Number of subordinates of Shaukat: 0
*/
//The problem with the anonymous function above starts when we do the following two lines.
//**********************************
//var ftn2 = ftn;
//ftn = null;
//ftn2(orgChart);
//**********************************
/*
We get an error after the first top employee of the organization chart as shown as the recursive call fails because we have set ftn to null and we are still calling it in the recrusive call inside the body of the function. 

Dilshad
Number of subordinates of Dilshad: 1
Dilshad's subordinate # 1: 
Uncaught TypeError: ftn is not a function
*/
/*
 The solution is simple - use a named function instead of an anonymous funciton as shown below:
*/

//Writing a named function that uses recursion.
var ftn = function showAllEmployees(topEmployee) {
    console.log(topEmployee.name);
    console.log('Number of subordinates of ' + topEmployee.name + ': ' + topEmployee.subordinates.length);
    /* 
      Calling itself recrusively for each employee to check it s(he) has subordinates. 
      */
    for (var i = 0; i < topEmployee.subordinates.length; i++){
     console.log(topEmployee.name + "'s subordinate # " + (i + 1) + ": ");
        //Recursive call to ftn in the line below.
        showAllEmployees(topEmployee.subordinates[i]);
    }
};

/* Now the code works even if we do the following. */
var ftn2 = ftn;
ftn = null;
ftn2(orgChart);
/* But don't forget to comment the lines above which were causing errors. The lines between 
//********************************** and //**********************************
 should be commented
*/

Monday 4 April 2016

Returning a function from another function - closures in javascript

closures are used to persist functions in javascript. It helps us to persist functions and access their context. We can have access to the variables inside the functions even when we are outside the function as the function is not garbage-collected due to persistence.
//closures
var salaryUpdater = function(salary){
 var currentSalary = salary;
  var generator = function(){
   currentSalary *= 2;
    return currentSalary;
  };
  return generator;
};
var updateFtn = salaryUpdater(50000);
console.log(updateFtn());//100000
//*************************************************************
/* 
To prove that the function salaryUpdater and its context is persistent
we will call it twice and will show that the increment made in the
first call remains and the second call increments the salary further. 
*/
var salaryUpdater = function(salary){
 var currentSalary = salary;
  var generator = function(){
   currentSalary += 5000;
    return currentSalary;
  };
  return generator;
};

var updateFtn = salaryUpdater(30000);
updateFtn();
console.log(updateFtn());//40000
//*************************************************************

Indirectly calling functions using the call() and apply() function in javascript

//Using call() and apply() functions
var updateZipCode = function(){
 console.log(this);//Window(....) //this points to the global object Window
};
updateZipCode();
//************************************************************************
var updateZipCode = function(){
 console.log(this);//Object{}
};
/* In the line given below we are passing an empty object as parameter to the call mehtod so that inside the function updateZipCode 'this' can refer to it. */
updateZipCode.call({});
//************************************************************************
var updateZipCode = function(){
 console.log(this);//Object {zip: "22675"}
};
/* In the line given below we are passing an object that has a property zip along with the valu of that property set to 22675 as parameter to the call mehtod so that inside the function updateZipCode 'this' can refer to it. */
updateZipCode.call({zip: '22675'});
//************************************************************************
//We can pass a variable as argument to call() as shown below
var updateZipCode = function(){
 console.log(this);//Object {zip: "24358"}
};
//Making a variable to be passed to the method call() as argument.
var zipCode = {
 zip : '24358'
};
updateZipCode.call(zipCode);
//************************************************************************
//Using a function that requires arguments. 
var updateZipCode = function (newZip, country) {
 console.log(newZip + ' ' + country);//98679 japan
};
var zipCode = {
 zip: '45345'
};
/*In the line below we are passing the object zipCode as the first argument which will be associated with the keyword 'this' in the function updateZipCode(). We are also passing the arguments for the neqZip and country.
*/
updateZipCode.call(zipCode, '98679', 'japan');
//************************************************************************
/* The apply() function gets an array as argument and break down this array 
in to arguments to pass them to the function updateZipCode(). If we supply 
a list of arguments instead of an array it will not work. */
var updateZipCode = function(newZip, country){
 console.log(newZip + ' ' + country);//29468 japan
};
var zipCode = {
 zip: '34679'
};
updateZipCode.apply(zipCode, ['29468', 'japan']);
/*
If we use apply() but instead of an array, pass it a list then we get the 
following error:
Uncaught TypeError: CreateListFromArrayLike called on non-object
*/
//updateZipCode.apply(zipCode, '29468', 'japan');
//************************************************************************

'this' keyword in functions and the global space - an exercise on what 'this' refers to in a piece of code

//This file explains the this keyword in functions and the global space but does not explain the use of this in eventhandlers.
console.log(typeof this);//object
console.log(this === window);/*true. It refers to the window object. Will not works in node as node doesn't have a window object as it works on a server.*/
var name = 'Dilshad';
console.log(this.name);//result ???
console.log(name);//Dilshad
//"this" gets assigned to window if we specify it in the global space without attaching it to any object.
var updateSalary = function(){
 console.log(this === window);//true
};
updateSalary();
//**************************************************************************************************
var employee = {
 name: 'Jeff',
  updateSalary : function (){
   console.log(this);
    /* 
    Object {name: "Jeff"} shows that 'this' refers to the object employee as function updateSalary() is attached to an object    employee.
    */
  }
};
employee.updateSalary();
//**************************************************************************************************
var employee = {
 name: 'Dilshad',
  updateSalary: function() {
   var fn = function () {
     console.log(this);/* Window {external: Object, chrome: Object, document: document, speechSynthesis: SpeechSynthesis, caches: CacheStorage…}  shows that keyword 'this' is attached to the global window. as function window has no object attached to it and 
      therefore the keyword this gets attached to the window. We can ascertain it by using the following line also.*/
      console.log(this === window);
    };
    fn();
  }
};
employee.updateSalary();
//**************************************************************************************************
//We have a constructor function given below 
var Address = function (line1) {
 this.line1 = line1;
  console.log(this);//Address {line1: "Chak 79 Street 12"}
};
/* Creating a new object using the operator 'new' and calling the constructor and passing it a string. 
This will attach the keyword 'this' to this newly created object. */
var address = new Address('Chak 79 Street 12');
//**************************************************************************************************
var Address = function (line1){
 this.line1 = line1;
};
/* Creating a function and attaching it to the prototype of the constructor so that all
instances created by this constructor can have access to the function to update zip codes
in the instance that call this function.*/
Address.prototype.updateZipCode = function(){
 //update the zipcode here in the address object created by the constructor Address
  console.log(this);//Address {line1: "chak 79 Street 12"}
};
//creating a new instance/object address
var address = new Address('chak 79 Street 12');
address.updateZipCode();
//**************************************************************************************************

//**************************************************************************************************

Sunday 3 April 2016

Constructor functions and their empty prototypes and adding functions to those prototypes in javascript

/* 
Finding the type of Object in js. Object is of type function in js and not of type Object. 
Object is a constructor function in js. 
*/
console.log(typeof Object);//function
//****************************************************************************************
var Employee = function (name, boss) {
 this.name = name;
  this.boss = boss;
};
var newEmployee = new Employee('jj', 'jhon jhones');
console.log(typeof newEmployee);//object
console.log(newEmployee.name);//jj
console.log(newEmployee.boss);//jhon jhones
//****************************************************************************************
var Employee = function(name){
 this.name = name;
};
var e1 = new Employee('jj');
var e2 = new Employee('kk');
var e3 = e1;
console.log(e1 == e2);//false
console.log( e1 === e2);//false
console.log(e1 == e3);//true
console.log( e1 === e3);//true
//****************************************************************************************
//__ double underscore is called dunder proto and is a kind of hack to enable us to reach the prototype 
console.log(e1.__proto__ === e2.__proto__);//true
/* The line above proves that both the employee objects have the same prototype and that
makes it very easy for the programmer to add functionalities to the Employee. We don't have
to write a function for the thousand of employee objects instead we just write it once
in the prototype of our Employee and all ojbects have acess to it.
*/
//****************************************************************************************
/* We should not add function to the body of the constructor Employee otherwise it would 
be duplicated into the body of all those objects that we are creating using this 
constructor. The following block of code is wrong. */
var Employee = function (name){
 this.name = name;
  this.giveRaise = function(){
   //Increase the salary by 10 %.
  };
};
var e1 = new Employee('jj');
var e2 = new Employee('kk');
console.log(e1.giveRaise === e2.giveRaise);//false
/* The line above gives false as both e1 and e2 get their own copies of function giveRaise() when
they are created using the constructor Employee. *
/* The correct way to do it is to add the function giveRaise to the prototype of the Employee constructor. See later in the code. */
//****************************************************************************************
/* When we work with json objects, we do not have direct access to the prototypes but 
now when we are working with the Constructor functions we do have access to the prototype. */
console.log(typeof Employee.prototype);//object
//****************************************************************************************
//Is Employee.prototype is the same as Object.prototype?
console.log(Employee.prototype === Object.prototype);//false
/* The line above gives false and that proves that Employee has got its own empty prototype
object. In json, each object has its prototype set to Object.prototype but that is not
the case when we are dealing with constructor functions. */
//****************************************************************************************
/* The correct way to add a funciton is not to add it to body of the constructor Employee
as done above in the code but to add it to the prototype of the connstructor Employee as 
shown below: */
var Employee = function (name){
 this.name = name;
  this.salary = 25000;//All employees get a start salary of 25 k during creation of an object of type Employee
};
Employee.prototype.giveRaise = function(raise){
 this.salary += raise;
};
var e1 = new Employee('jj');
var e2 = new Employee('kk');
console.log(e1.giveRaise === e2.giveRaise);//true
/* Now even if we 50 k employees we don't duplicate the function as we have added it to the  
prototype of the constructor function and all the employees objects can call it. */
e1.giveRaise(5000);
console.log(e1.salary);
console.log(e2.salary);
//****************************************************************************************

Defining custom properties on an object to have more control.

'use strict';
//We define an empty object.
var task = {};
//We define a property on the object task with key as 'text' and value as 'Get this job done!'
Object.defineProperty(task, 'text', {
 value: 'Get this job done!'
});
console.log(task.text);
//*****************************************************************
var task = {};
Object.defineProperty(task, 'text', {
 value: 'Get this job done!',
  //By default writable : false. Therfore, we have to set it to true if want o make th property text writable
  writable: true
});
/* 
If the writable : true is commented out then by default writable : false and we will get TypeError: can not assign to read only property.
*/
task.text = task.text + ' ... Now!';
console.log(task.text);
//*****************************************************************
var task = {};
Object.defineProperty(task, 'text', 
{
 value: 'Get this job done!',
  //enumerable is used in for in statements
  enumerable: true
});
for(var f in task){
 console.log(f);/* We get text on the console but if we do not set enumerable: false then by default 
  enumberable: false and nothing will be shown on the console.*/
}
//*****************************************************************
var task = {};
Object.defineProperty(task, 'text', {
 value: 'Get this job done!',
  configurable: true
});
Object.defineProperty(task, 'text', {
 value: 'Done!'
});
console.log(task.text);/* The output on the console is 'Done!' as configurable: true but if we set
configurable: false or just delete that line then by default configurable:false and, therefore, we get
Ucaught TypeError: Cannot redefine property: text 
*/
//*****************************************************************
//Getter functions
var task = {
 _dueDate: '1/30/2016'
};
Object.defineProperty(task, 'dueDate', {
 get: function(){
   return this._dueDate;
  }
});
console.log(task.dueDate);
//*****************************************************************
//Setter function
var task = {
 _dueDate: '1/30/2016'
};
Object.defineProperty(task, 'dueDate', {
 get: function (){
   return this._dueDate;
  },
  set: function (newValue) {
   this._dueDate = newValue;
  }
});
//The line below will call the setter funciton 
task.dueDate = '10/28/2016';
console.log(task.dueDate);
//*****************************************************************
//Assigning multiple properties to a single task
var task = {};
Object.defineProperties(task, 
 {
   // Setting the property text of the object task
  'text': {
    value: 'New Task'
   },
    //setting the property dueDate of the object task
   'dueDate': {
    value: '1/30/2014'
   }
 }
);
console.log(task.text + ' Due: ' + task.dueDate);
var descriptor = Object.getOwnPropertyDescriptor(task, 'text');
console.log(descriptor);//Object {value: "New Task", writable: false, enumerable: false, configurable: false}
var descriptor = Object.getOwnPropertyDescriptor(task, 'dueDate');
console.log(descriptor);//Object {value: "1/30/2014", writable: false, enumerable: false, configurable: false}
//*****************************************************************

//*****************************************************************

Wednesday 30 March 2016

Some features of arrays in java script

Some features of Arrays in java script

var entries = new Array('Trains', 'Planes', 'Automobiles', 'Carts');
console.log(entries instanceof Array);
console.log(entries);
//You can leave out the new keyword and it still works
var entries = Array("Ajmal", "Dilshad", "Russell", "Anders");
console.log(entries instanceof Array);
console.log(entries);
//We can make array with [] also.
var places = ['Malmö', 'Lund', 'Stockholm', 'Gothenborg'];
console.log(places instanceof Array);
console.log(places);
console.log(places[1]);
//No exception gets thrown if you access a non-existing index
console.log(places[9]);//Get undefined.
//Initializing array of a particular length
var books = new Array(5);
console.log(books.length);//returns 5
var books = new Array("5");//one string element. Not length.
console.log(books.length);
var entries = [,,,];
console.log(entries.length);

//We can assign a numeric length to the length property of an array
var transport = ['Planes', 'Trains', 'Carts', 'Buses'];
console.log(transport.length);
transport.length = 10;
console.log(transport.length);
transport.length = 2;
//Accessing a non-existent index of the array gives undefined.
console.log(transport[3]);
//Assigning a new means of transport to a non-existing index.
transport[49] = 'Cars';//expands the array.
console.log(transport[49]);
console.log(transport.length);
//Appending to the end of the array
transport[transport.length] = 'Bicycles';
console.log(transport.length);

//To get a comma separated list of the elements of an array
console.log(transport.toString());

var ratings = [5, 2, 4];
console.log(ratings);
console.log(ratings.valueOf());

//For separating the elements of the array with another string
console.log(ratings.join('|'));
console.log(ratings.join('   '));

//Array acting as a stack.
var ratings = [];
ratings.push(5);
ratings.push(2, 4);
console.log(ratings.length);
ratings.shift(1);
console.log(ratings.length);
//To check that the element at index 0 does not exit now.
console.log(ratings.valueOf());
console.log(ratings.pop());//Gets us the last inserted element
console.log(ratings.length);
//Inserting a new element at the beginning
ratings.unshift(9);
console.log(ratings.valueOf());
ratings.unshift(8);
console.log(ratings[0]);
console.log(ratings.valueOf());
var newCount = ratings.unshift(7);
console.log(ratings.valueOf());
console.log(newCount);

//Concatenation on arrays
var ratings = [1, 2, 3];
var newRatings = ratings.concat([4, 5, 6]);
console.log(newRatings.length);
console.log(newRatings.valueOf());
newRatings = newRatings.concat([7, 8], 9, 10);
console.log(newRatings.valueOf());

//Slicing an array to get the remaining element
var ratings = [1, 2, 3, 4, 5, 6, 7];
var newRatings = ratings.slice(2);//2 means index 2 
console.log(newRatings.valueOf());
console.log(newRatings.toString());
var newRatings = ratings.slice(1, 4);//Gives 2,3. Excludes index 3
console.log(newRatings.toString());
console.log(newRatings.valueOf());
//Passing a negative argument to slice function give elements from the end of the array
var newRatings = ratings.slice(-2);
console.log(newRatings.valueOf());

//Starting at ith index and deleting x number of elements
var ratings = [1, 2, 3, 4];
ratings.splice(1, 2);//Start from index 1 and delete 2 items.
console.log(ratings.toString());//The riginal array gets modified.
//Getting the removed elements as an array with splice function
var ratings = [1, 2, 3, 4];
var removedRatings = ratings.splice(0, 2);
console.log(removedRatings.toString());
console.log(ratings.toString());

//Function splice with three arguments.
var ratings = [1, 2, 3, 4];
//start at index 2, delete nothing and insert 99 at index 2
ratings.splice(2, 0, 99);
console.log(ratings.toString());
//We can insert more than one items also
var ratings = [1, 2, 3, 4];
ratings.splice(2, 0, 99, 100, 101);
console.log(ratings.toString());
//We can delete items and insert items at the same time
var ratings = [1, 2, 3, 4];
//Start at index 2, delete one item and insert 3 items.
ratings.splice(2, 1, 99, 200, 300);
console.log(ratings.toString());

//Reversing elements of an array
var ratings = [1, 2, 3, 4,];
ratings.reverse();
console.log(ratings);

//Sorting the elments of an array that is not the correct way
//The sort function is treating elements liks Strings while sorting
var ratings = [1, 4, 10, 14,];
ratings.sort();
console.log(ratings.toString());
//The correct way to use function is sort is to pass it a function
var ratings = [1, 4, 10, 14,];
ratings.sort(
       function(value1, value2){
               return value1 - value2;
              }
            );
console.log(ratings.toString());

//Searching an item in an  array
var ratings = [1, 2, 3, 4, 5, 4, 3, 2, 1];
console.log(ratings.indexOf(3));//returns 2
console.log(ratings.indexOf('3')); //returns -1 as it can not find '3' in the array
console.log(ratings.indexOf(66));//returns -1 as there is no 66 in the array.
var names = new Array("Ajmal", "Dilshad", "Russell", "Anders", "Russell");
console.log(names.indexOf("Dilshad"));
//lastIndexOf() function starts at the end of the array to search
console.log(names.lastIndexOf("Russell"));