Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Object-Oriented JavaScript - Third Edition

You're reading from   Object-Oriented JavaScript - Third Edition Learn everything you need to know about object-oriented JavaScript (OOJS)

Arrow left icon
Product type Book
Published in Jan 2017
Publisher Packt
ISBN-13 9781785880568
Pages 550 pages
Edition 3rd Edition
Languages
Arrow right icon
Authors (2):
Arrow left icon
Stoyan STEFANOV Stoyan STEFANOV
Author Profile Icon Stoyan STEFANOV
Stoyan STEFANOV
Ved Antani Ved Antani
Author Profile Icon Ved Antani
Ved Antani
Arrow right icon
View More author details
Toc

Table of Contents (25) Chapters Close

Object-Oriented JavaScript - Third Edition
Credits
About the Authors
About the Reviewer
www.PacktPub.com
Customer Feedback
Preface
1. Object-Oriented JavaScript FREE CHAPTER 2. Primitive Data Types, Arrays, Loops, and Conditions 3. Functions 4. Objects 5. ES6 Iterators and Generators 6. Prototype 7. Inheritance 8. Classes and Modules 9. Promises and Proxies 10. The Browser Environment 11. Coding and Design Patterns 12. Testing and Debugging 13. Reactive Programming and React Reserved Words Built-in Functions
Built-in Objects Regular Expressions
Answers to Exercise Questions

Chapter 7, The Browser Environment


Lets practice the following exercise:

Exercises

  1. The title clock program is as follows:

            setInterval(function () { 
              document.title = new Date().toTimeString(); 
            }, 1000); 
    
  2. To animate resizing of a 200 x 200 pop up to 400 x 400, use the following code:

            var w = window.open( 
                'http://phpied.com', 'my', 
                 'width = 200, height = 200'); 
     
            var i = setInterval((function () { 
              var size = 200; 
              return function () { 
                size += 5; 
                w.resizeTo(size, size); 
                if (size === 400) { 
                  clearInterval(i); 
                } 
              }; 
            }()), 100); 
    

    Every 100 ms (1/10th of a second) the pop-up size increases by five pixels. You keep a reference to the interval i so you can clear it once done. The variable size tracks the pop-up size (and why not keep it private inside a closure).

  3. The earthquake program is as follows:

           var i = setInterval((function () { 
              var start = +new Date(); // Date.now() in ES5 
              return function () { 
                w.moveTo( 
                  Math.round(Math.random() * 100), 
                  Math.round(Math.random() * 100)); 
                if (new Date() - start > 5000) { 
                  clearInterval(i); 
                } 
              }; 
             }()), 20); 
    

    Try all of them, but using requestAnimationFrame() instead of setInterval().

  4. A different walkDOM() with a callback is as follows:

            function walkDOM(n, cb) { 
              cb(n); 
              var i, 
                  children = n.childNodes, 
                  len = children.length, 
                  child; 
              for (i = 0; i < len; i++) { 
              child = n.childNodes[i]; 
                if (child.hasChildNodes()) { 
                  walkDOM(child, cb); 
                } 
              } 
            } 
    

    Testing:

            > walkDOM(document.documentElement,
            console.dir.bind(console)); 
           html 
           head 
           title 
           body 
           h1 
           ... 
    
  5. To remove content and clean up functions, use the following code:

            // helper 
            function isFunction(f) { 
              return Object.prototype.toString.call(f) === 
                "[object Function]"; 
            } 
     
            function removeDom(node) { 
              var i, len, attr; 
     
              // first drill down inspecting the children 
              // and only after that remove the current node 
              while (node.firstChild) { 
                removeDom(node.firstChild); 
              } 
     
              // not all nodes have attributes, e.g. text nodes don't 
              len = node.attributes ? node.attributes.length : 0; 
     
              // cleanup loop 
              // e.g. node === <body>,  
              // node.attributes[0].name === "onload" 
              // node.onload === function()... 
              // node.onload is not enumerable so we can't use  
              // a for-in loop and have to go the attributes route 
              for (i = 0; i < len; i++) { 
                attr = node[node.attributes[i].name]; 
                if (isFunction(attr)) { 
                  // console.log(node, attr); 
                  attr = null; 
                } 
              } 
     
              node.parentNode.removeChild(node); 
            } 
    

    Testing:

            > removeDom(document.body); 
    
  6. To include scripts dynamically, use the following code:

            function include(url) { 
              var s = document.createElement('script'); 
              s.src = url; 
              document.getElementsByTagName('head')[0].
              appendChild(s); 
            } 
    

    Testing:

            > include("http://www.phpied.com/files/jinc/1.js"); 
            > include("http://www.phpied.com/files/jinc/2.js"); 
    
  7. Events: The event utility program is as follows:

            var myevent = (function () { 
     
              // wrap some private stuff in a closure 
              var add, remove, toStr = Object.prototype.toString; 
     
              // helper 
              function toArray(a) { 
                // already an array 
                if (toStr.call(a) === '[object Array]') { 
                  return a; 
               } 
         
                // duck-typing HTML collections, arguments etc 
                var result, i, len; 
                if ('length' in a) { 
                  for (result = [], i = 0, len = a.length; i < len; i++)
                  { 
                    result[i] = a[i]; 
                  } 
                  return result; 
               } 
     
                // primitives and non-array-like objects 
                // become the first and single array element 
                return [a]; 
              } 
     
              // define add() and remove() depending 
              // on the browser's capabilities 
              if (document.addEventListener) { 
                add = function (node, ev, cb) { 
                  node.addEventListener(ev, cb, false); 
                }; 
                remove = function (node, ev, cb) { 
                  node.removeEventListener(ev, cb, false); 
                }; 
              } else if (document.attachEvent) { 
                add = function (node, ev, cb) { 
                  node.attachEvent('on' + ev, cb); 
                }; 
                remove = function (node, ev, cb) { 
                  node.detachEvent('on' + ev, cb); 
                }; 
              } else { 
                add = function (node, ev, cb) { 
                  node['on' + ev] = cb; 
                }; 
                remove = function (node, ev) { 
                  node['on' + ev] = null; 
                }; 
              } 
     
              // public API 
              return { 
     
                addListener: function (element, event_name, callback) { 
                  // element could also be an array of elements 
                  element = toArray(element); 
                  for (var i = 0; i < element.length; i++) { 
                    add(element[i], event_name, callback); 
                  } 
                }, 
     
               removeListener: function (element, event_name, callback) { 
                  // same as add(), only practicing a different loop 
                  var i = 0, els = toArray(element), len = els.length; 
                 for (; i < len; i++) { 
                    remove(els[i], event_name, callback); 
                  } 
               }, 
     
                getEvent: function (event) { 
                  return event || window.event; 
                }, 
      
                getTarget: function (event) { 
                  var e = this.getEvent(event); 
                  return e.target || e.srcElement; 
                }, 
     
                stopPropagation: function (event) { 
                  var e = this.getEvent(event); 
                  if (e.stopPropagation) { 
                    e.stopPropagation(); 
                  } else { 
                    e.cancelBubble = true; 
                  } 
                }, 
     
                preventDefault: function (event) { 
                  var e = this.getEvent(event); 
                  if (e.preventDefault) { 
                    e.preventDefault(); 
                  } else { 
                    e.returnValue = false; 
                  } 
                } 
     
              }; 
            }()); 
    

    Testing: Go to any page with links, execute the following, and then click any link:

            function myCallback(e) { 
              e = myevent.getEvent(e); 
              alert(myevent.getTarget(e).href); 
              myevent.stopPropagation(e); 
              myevent.preventDefault(e); 
            } 
            myevent.addListener(document.links, 'click', myCallback); 
    
  8. Move a div around with the keyboard using the following code:

            // add a div to the bottom of the page 
            var div = document.createElement('div'); 
            div.style.cssText = 'width: 100px; height:
             100px; background: red; position: absolute;'; 
            document.body.appendChild(div); 
     
            // remember coordinates 
            var x = div.offsetLeft; 
            var y = div.offsetTop; 
     
            myevent.addListener(document.body, 
             'keydown', function (e) { 
             // prevent scrolling 
              myevent.preventDefault(e); 
     
              switch (e.keyCode) { 
                case 37: // left 
                  x--; 
                  break; 
                case 38: // up 
                  y--; 
                  break; 
                case 39: // right 
                  x++; 
                  break; 
                case 40: // down 
                  y++; 
                  break; 
                default: 
                  // not interested 
              } 
     
              // move 
              div.style.left = x + 'px'; 
              div.style.top  = y + 'px'; 
     
            }); 
    
  9. Your own Ajax utility:

            var ajax = { 
              getXHR: function () { 
                var ids = ['MSXML2.XMLHTTP.3.0', 
                 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP']; 
                var xhr; 
                if (typeof XMLHttpRequest === 'function') { 
                  xhr = new XMLHttpRequest(); 
                } else { 
                  // IE: try to find an ActiveX object to use 
                  for (var i = 0; i < ids.length; i++) { 
                    try { 
                      xhr = new ActiveXObject(ids[i]); 
                      break; 
                    } catch (e) {} 
                  } 
                } 
                return xhr; 
     
              }, 
              request: function (url, method, cb, post_body) { 
                var xhr = this.getXHR(); 
                xhr.onreadystatechange = (function (myxhr) { 
                  return function () { 
                    if (myxhr.readyState === 4 && myxhr.status === 200) { 
                      cb(myxhr); 
                    } 
                  }; 
                }(xhr)); 
                xhr.open(method.toUpperCase(), url, true); 
                xhr.send(post_body || ''); 
              } 
            }; 
    

    When testing, remember that same origin restrictions apply, so you have to be on the same domain. You can go to http://www.phpied.com/files/jinc/, which is a directory listing and then test in the console:

            function myCallback(xhr) { 
              alert(xhr.responseText); 
            } 
            ajax.request('1.css', 'get', myCallback); 
            ajax.request('1.css', 'post', myCallback,
             'first=John&last=Smith'); 
    

    The result of the two is the same, but if you look into the Network tab of the Web Inspector, you can see that the second is indeed a POST request with a body.

lock icon The rest of the chapter is locked
arrow left Previous Section
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime