BOM

The BOM is a collection of objects that give you access to the browser and the computer screen. These objects are accessible through the global object window.

The window object revisited

As you already know, in JavaScript, there's a global object provided by the host environment. In the browser environment, this global object is accessible using window. All global variables are also accessible as properties of the window object. For example, take a look at the following code:

    > window.somevar = 1; 
           1 
    > somevar; 
           1 

Additionally, all the core JavaScript functions, discussed in Chapter 2, Primitive Data Types, Arrays, Loops, and Conditions, are methods of the global object. Consider the following piece of code:

    > parseInt('123a456'), 
           123 
    > window.parseInt('123a456'), 
           123 

In addition to being a reference to the global object, the window object also serves a second purpose-providing information about the browser environment. There's a window object for every frame, iframe, pop up, or browser tab.

Let's see some of the browser-related properties of the window object. Again, these can vary from one browser to another, so let's only consider the properties that are implemented consistently and reliably across all major browsers.

Using window.navigator property

The navigator is an object that has some information about the browser and its capabilities. One property is navigator.userAgent, which is a long string of browser identification. In Firefox, you'll get the following output:

    > window.navigator.userAgent; 
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) 
          AppleWebKit/536.28.10
          (KHTML, like Gecko) Version/6.0.3 Safari/536.28.10" 

The userAgent string in Microsoft Internet Explorer is something as follows:

       "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)" 

As the browsers have different capabilities, developers are using the userAgent string to identify the browser and provide different versions of the code. For example, the following code snippet searches for the presence of the MSIE string to identify Internet Explorer:

    if (navigator.userAgent.indexOf('MSIE') !== -1) { 
      // this is IE 
    } else { 
      // not IE 
    } 

It's better not to rely on the userAgent string, but to use feature sniffing (also called capability detection) instead. The reason for this is that it's hard to keep track of all browsers and their different versions. It's much easier to simply check if the feature you intend to use is indeed available in the user's browser. For example, take a look at the following code snippet:

    if (typeof window.addEventListener === 'function') { 
      // feature is supported, let's use it 
    } else { 
      // hmm, this feature is not supported, will have to 
      // think of another way 
    } 

Another reason to avoid userAgent sniffing is that some browsers allow users to modify the string and pretend they are using a different browser.

Your console is a cheat sheet

The console lets you inspect what's in an object and this includes all the BOM and DOM properties. Just type the following code:

    > navigator; 

Then click on the result. The result is a list of properties and their values, as shown in the following screenshot:

Your console is a cheat sheet

Using window.location property

The location property points to an object that contains information about the URL of the currently loaded page. For example, location.href is the full URL and location.hostname is only the domain. With a simple loop, you can see the full list of properties of the location object.

Imagine you're on a page with the following URL:

http://search.phpied.com:8080/search?q=java&what=script#results.

Consider the following code:

    for (var i in location) { 
      if (typeof location[i] === "string") { 
        console.log(i + ' = "' + location[i] + '"'), 
      } 
    } 
           href = "http://search.phpied.com:8080/search?
             q=java&what=script#results" 
           hash = "#results" 
           host = "search.phpied.com:8080" 
           hostname = "search.phpied.com" 
           pathname = "/search" 
           port = <<8080>> 
           protocol = <<http:>> 
           search = "?q=java&what=script" 

There are also three methods that location property provides, namely reload(), assign(), and replace().

It's interesting how many different ways exist for you to navigate to another page. The following are a few ways:

    > window.location.href = 'http://www.packtpub.com'; 
    > location.href = 'http://www.packtpub.com'; 
    > location = 'http://www.packtpub.com'; 
    > location.assign('http://www.packtpub.com'), 

The replace() method is almost the same as assign(). The difference is that it doesn't create an entry in the browser's history list as follows:

    > location.replace('http://www.yahoo.com'), 

To reload a page, you can use the following code:

    > location.reload(); 

Alternatively, you can use location.href to point it to itself, as follows:

    > window.location.href = window.location.href; 

Or, simply use the following code:

    > location = location; 

Using window.history property

The window.history property allows limited access to the previously visited pages in the same browser session. For example, you can see how many pages the user has visited before coming to your page, as follows:

    > window.history.length; 
           5 

You cannot see the actual URLs though. For privacy reasons, this doesn't work. See the following code:

    > window.history[0]; 

You can, however, navigate back and forth through the user's session as if the user had clicked on the back/forward browser buttons, as follows:

    > history.forward(); 
    > history.back(); 

You can also skip pages back and forth with history.go(). This is the same as calling history.back(). The code for history.go() is as follows:

    > history.go(-1); 

To go two pages back, use the following code:

    > history.go(-2); 

Reload the current page using the following code:

    > history.go(0); 

More recent browsers also support HTML5 history API, which lets you change the URL without reloading the page. This is perfect for dynamic pages because they can allow users to bookmark a specific URL, which represents the state of the application, and when they come back, or share with their friends, the page can restore the application state based on the URL. To get a sense of the history API, go to any page and write the following lines of code in the console:

    > history.pushState({a: 1}, "", "hello"); 
    > history.pushState({b: 2}, "", "hello-you-too"); 
    > history.state; 

Notice how the URL changes, but the page is the same. Now, experiment with back and forward buttons in the browser and inspect the history.state object again.

using window.frames property

The window.frames property is a collection of all of the frames in the current page. It doesn't distinguish between frames and iframes (inline frames). Regardless of whether there are frames on the page or not, window.frames always exists and points to window, as follows:

    > window.frames === window; 
           true 

Let's consider an example where you have a page with one iframe, as follows:

    <iframe name="myframe" src="hello.html" /> 

In order to tell if there are any frames on the page, you can check the length property. In case of one iframe, you'll see the following output:

    > frames.length 
           1 

Each frame contains another page, which has its own global window object.

To get access to the iframe's window, you can execute any of the following:

    > window.frames[0]; 
    > window.frames[0].window; 
    > window.frames[0].window.frames; 
    > frames[0].window; 
    > frames[0]; 

From the parent page, you can access properties of the child frame as well. For example, you can reload the frame as follows:

    > frames[0].window.location.reload(); 

From inside the child, you can access the parent as follows:

    > frames[0].parent === window; 
           true 

Using a property called top, you can access the top-most page-the one that contains all the other frames-from within any frame, as follows:

    > window.frames[0].window.top === window; 
           true 
    > window.frames[0].window.top === window.top; 
           true 
    > window.frames[0].window.top === top; 
           true 

In addition, self is the same as window, as you can see in the following code snippet:

    > self === window; 
           true 
    > frames[0].self == frames[0].window; 
           true 

If a frame has a name attribute, you cannot only access the frame by name, but also by index, as shown in the following piece of code:

    > window.frames['myframe'] === window.frames[0]; 
           true 

Or, alternatively, you can use the following code:

    > frames.myframe === window.frames[0]; 
           true 

Using window.screen property

The screen property provides information about the environment outside the browser. For example, the screen.colorDepth property contains the color bit depth (the color quality) of the monitor. This is mostly used for statistical purposes. Take a look at the following line of code:

    > window.screen.colorDepth; 
           32 

You can also check the available screen real estate (the resolution), as follows:

    > screen.width; 
           1440 
    > screen.availWidth; 
           1440 
    > screen.height; 
           900 
    > screen.availHeight; 
           847 

The difference between height and availHeight is that height is the whole screen, while availHeight subtracts any operating system menus, such as the Windows task bar. The same is the case for width and availWidth.

Somewhat related is the property mentioned in the following code:

    > window.devicePixelRatio; 
           1 

It tells you the difference (ratio) between physical pixels and device pixels in the retina displays in mobile devices, for example, value 2 in iPhone.

window.open()/close() method

Having explored some of the most common cross-browser properties of the window object, let's move to some of the methods. One such method is open(), which allows you to open new browser windows (pop ups). Various browser policies and user settings may prevent you from opening a pop up (due to abuse of the technique for marketing purposes), but generally, you should be able to open a new window if it was initiated by the user. Otherwise, if you try to open a pop up as the page loads, it will most likely be blocked, because the user didn't initiate it explicitly.

The window.open() method accepts the following parameters:

  • URL to load in the new window
  • Name of the new window that can be used as the value of a form's target attribute
  • Comma-separated list of features, which is as follows:
    • resizable: Should the user be able to resize the new window
    • width, height: Width and height of the pop up
    • status: Should the status bar be visible

The window.open() method returns a reference to the window object of the newly created browser instance. The following is an example:

    var win = window.open('http://www.packtpub.com', 'packt', 
      'width=300,height=300,resizable=yes'), 

The win variable points to the window object of the pop up. You can check if win has a falsy value, which means that the pop up was blocked.

The win.close() method closes the new window.

It's best to stay away from opening new windows for accessibility and usability reasons. If you don't like sites popping up windows to you, why do it to your users? There are legitimate purposes, such as providing help information while filling out a form, but often, the same can be achieved with alternative solutions, such as using a floating <div> inside the page.

window.moveTo() and window.resizeTo() methods

Continuing with the shady practices from the past, the following are more methods to irritate your users, provided their browser and personal settings allow you to do so:

  • window.moveTo(100, 100): This moves the browser window to screen location x = 100 and y = 100, which is counted from the top-left corner
  • window.moveBy(10, -10): This moves the window 10 pixels to the right and 10 pixels up from its current location
  • window.resizeTo(x, y) and window.resizeBy(x, y): These accept the same parameters as the move methods, but they resize the window as opposed to moving it

Again, try to solve the problem you're facing without resorting to these methods.

window.alert(), window.prompt(), and window.confirm() methods

In Chapter 2, Primitive Data Types, Arrays, Loops, and Conditions, we talked about the alert() function. Now you know that global functions are accessible as methods of the global object, so alert('Watch out!') and window.alert('Watch out!') are exactly the same.

The alert() function is not an ECMAScript function but a BOM method. In addition to it, two other BOM methods allow you to interact with the user through system messages. The following are the methods:

  • confirm(): This gives the user two options, OK and Cancel
  • prompt(): This collects textual input

This is how it works:

    > var answer = confirm('Are you cool?'),  
    > answer; 

It presents you with a window similar to the following screenshot (the exact look depends on the browser and the operating system):

window.alert(), window.prompt(), and window.confirm() methods

You'll notice the following things:

  • Nothing gets written to the console until you close this message, which means that any JavaScript code execution freezes, waiting for the user's answer
  • Clicking on OK returns true, clicking on Cancel or closing the message using the X icon, or the ESC key, returns false

This is handy to confirm user actions, as shown in the following piece of code:

    if (confirm('Sure you want to delete this?')) { 
      // delete 
    } else { 
      // abort 
    } 

Make sure you provide an alternative way to confirm user actions for people who have disabled JavaScript, or for search engine spiders.

The window.prompt() method presents the user with a dialog to enter text, as follows:

    > var answer = prompt('And your name was?'),  
    > answer; 

This results in the following dialog box (Chrome, MacOS):

window.alert(), window.prompt(), and window.confirm() methods

The value of answer is one of the following:

  • null: This happens if you click on Cancel, the X icon, or press ESC key
  • "" (empty string): This happens if you click on OK or press Enter without typing anything
  • A text string: This is if you type something and then click on OK or press Enter

The function also takes a string as a second parameter and displays it as a default value prefilled into the input field.

Using window.setTimeout() and window.setInterval() methods

The setTimeout()and setInterval() methods allow scheduling the execution of a piece of code. The setTimeout() method attempts to execute the given code once, after a specified number of milliseconds. The setInterval() method attempts to execute it repeatedly after a specified number of milliseconds has passed.

This shows an alert after approximately 2 seconds (2000 milliseconds). Consider the following code:

    > function boo() { alert('Boo!'), } 
    > setTimeout(boo, 2000); 
           4 

As you can see, the function returned an integer (in this case, 4) representing the ID of the timeout. You can use this ID to cancel the timeout using clearTimeout(). In the following example, if you're quick enough, and clear the timeout before 2 seconds have passed, the alert will never be shown, as you can see in the following code:

    > var id = setTimeout(boo, 2000); 
    > clearTimeout(id); 

Let's change boo()to something less intrusive, as follows:

    > function boo() { console.log('boo'), } 

Now, using setInterval(), you can schedule boo() to execute every 2 seconds, until you cancel the scheduled execution with clearInterval(). Consider the following code:

    > var id = setInterval(boo, 2000); 
           boo 
           boo 
           boo 
           boo 
           boo 
           boo 
    > clearInterval(id); 

Note that both functions accept a pointer to a callback function as a first parameter. They can also accept a string, which is evaluated with eval(); however, as you know, eval() is evil, so it should be avoided. Moreover, what if you want to pass arguments to the function? In such cases, you can just wrap the function call inside another function.

The following code is valid, but not recommended:

    // bad idea 
    var id = setInterval("alert('boo, boo')", 2000); 

This alternative is preferred:

    var id = setInterval( 
      function () { 
        alert('boo, boo'), 
      }, 
      2000 
    ); 

Be aware that scheduling a function in some amount of milliseconds is not a guarantee that it will execute exactly at that time. One reason is that most browsers don't have millisecond resolution time. If you schedule something in 3 milliseconds, it will execute after a minimum of 15 in older IEs and sooner in more modern browsers, but most likely, not in 1 millisecond. The other reason is that the browsers maintain a queue of what you request them to do. 100 milliseconds timeout means add to the queue after 100 milliseconds. However, if the queue is delayed by something slow happening, your function will have to wait and execute after, say, 120 milliseconds.

More recent browsers implement the requestAnimationFrame() function. It's preferable to the timeout functions because you're asking the browser to call your function whenever it has available resources, not after a predefined time in milliseconds. Try executing the following code snippet in your console:

    function animateMe() { 
      webkitRequestAnimationFrame(function(){ 
        console.log(new Date()); 
        animateMe(); 
      }); 
    } 
 
    animateMe(); 

window.document property

The window.document property is a BOM object that refers to the currently loaded document (page). Its methods and properties fall into the DOM category of objects. Take a deep breath (and maybe first look at the BOM exercises at the end of the chapter) and let's dive into the DOM.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.146.152.99