Objectives

Use both native JavaScript and JQuery to access and manipulate the DOM.

index1.html / dom-manip-1.js

In Webstorm, create new empty project called jquery-intro. Bring in the .jscsrc file as in the previous labs, and make sure the code inspections are enabled.

Introduce this file

index1.html

<!DOCTYPE html>
<!DOCTYPE html>
<html>
  <head>
    <title> JQuery Experiments </title>
  </head>
  <body>
    <p id="demo">Click the button to change this text.</p>
    <button onclick="domAccess()">Try it</button>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="js/dom-manip-1.js"></script>
  </body>
</html>

Add the following file to the project (in the js subdirectory):

dom-manip-1.js

function domAccess() {
  document.getElementById('demo').innerHTML = 'Hi ICTSkills';
}

Open dom-access.html in Chrome browser.

  • You should be presented with something similar to that depicted in Figure 1.

Figure 1: Invitation to click

  • Click the button Try it.
    • The text Click the button to change this text should be replaced with:
    • Hi ICTSkills (Figure 2).

Figure 2: Hi ICTSkills

Let's use Google Chrome debugger to better understand what's happening:

  • Open dom-access.html in Chrome.
  • Select Tools | Developer Tools in the context menu: see Figugre 3. Figure 3: Launching Developer Tools

  • Select the file dom-access.js into the text window (see Figure 4). Figure 4: Select dom-access.js

  • The file dom-access.js should now be visible as shown in Figure 5. Figure 5: dom-access.js javaScript file

Place a breakpoint on line 3, the statement document.getElementById("demo").innerHTML = "Hi ICTSkills";

  • You may do this by simply placing the mouse pointer on the number 3 and clicking. See Figure 6. Figure 6: Breakpoint set

  • Reload the page and press the button Try it

    • As shown in Figure 7, the program stops at line 3, the breakpoint. Figure 7: Program halts at breakpoint

How does this happen?

  • When, during the loading of the page described in the file dom-access.html, the statement <script src="js/dom-access.js"\></script\> is encountered, the JavaScript file dom-access.js, located in the folder js, is incorporated into the page and the document.getElementById command executed.
    • This accesses the paragraph node in the DOM whose id is demo and replaces the text with Hi ICTSkills.

Let's now replace the native JavaScript with jQuery to achieve the same goal.

  • Replace the the function domAccess in with the following:

dom-manip-1.js

function domAccess() {
  $('#demo').html('Hi ICTSkills');
}
  • Reload the index1.html
  • Press the Try it button:
    • Opps! There's a problem. The text does not change.
      • The reason is that we have not loaded the jQuery library.
      • We can load a local or a cloud copy of jQuery. Let's do the latter.
      • The modified html follows: reload this file, press the Try it button and observe that the result should be exactly the same as before: the text changes to Hi ICTSkills.

index1.html

<!DOCTYPE html>
<html>
  <head>
    <title> JQuery Experiments </title>
  </head>
  <body>
    <p id="demo">Click the button to change this text.</p>
    <button onclick="domAccess()">Try it</button>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="js/dom-manip-1.js"></script>
  </body>
</html>

Study the jQuery syntax.

  • $("#demo").html("Hi ICTSkills");
    • #demo refers to the id in the html paragraph node
      • Observe that a hash (#) is prepended to the id as shown in the html file.
    • $("#demo") is a jQuery object
    • $("#demo").html(...): here a jQuery method html(...) is being invoked on the jQuery object.
      • The text parameter in html(...) replaces the existing text at the location identified by the id #demo.

index2.html / dom-manip-2.js

In this step we shall use both native JavaScript and jQuery to obtain information on a single DOM element using the element's id attribute.

-Recall that an id uniquely identifies an element on a page.

Download the img.zip from the local archive, expand and place the folder img in your WebContent folder.

  • The folder img contains three arbitrarily chosen png images, 01, 02 and 03.
  • Create a file domManip.html in WebContent and add the following content:

index2.html

<!DOCTYPE html>
<html>
  <head>
    <title> JQuery Image Experiments </title>
  </head>
  <body>
    <div>
      <h2>Image 1</h2>
      <img src='img/01.png' id='img1'></div>
    <div>
      <h2>Image 2</h2>
      <img src='img/02.png'>
    </div>
    <div>
      <h2>Image 3</h2>
      <img src='img/03.png'>
    </div>
    <script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script>
    <script src='js/dom-manip-2.js'></script>
  </body>
</html>

Create file dom-manip-2.js in the folder js and add this content:

dom-manip-2.js

const image = document.getElementById('img1'); 
alert('Image height is '' + image.height);

Open domManip.html in Chrome. An alert box should open as shown in Figure 1. Figure 1: Image height

Let's now use a jQuery function call to obtain the image height.

Replace the dom-manip-2.js content with:

const image = $('#img1');
alert('Image height is ' + image.height());

Alternatively use a more compact version:

alert('Image height is ' + $('#img1').height());

index3.html / dom-manip-3.js

Recall that whereas an id uniquely identifies an element on a page, a name may be repeated.

  • In this step we shall obtain information about an array of elements identified by their name attribute.

Modify the file a new file index3.html which differs from the previous version:

  • add a name attribute to images 1 and 2
    • name="imgs"
    • the third image shall remain nameless.

The object is to retrieve an array of elements comprising those whose name attribute is "imgs".

  • We expect, therefore, that the array shall contain two images.

Here is a new html file for the project:

index3.html

<!DOCTYPE html>
<html>
  <head>
    <title> More Query Image Experiments </title>
  </head>
  <body>
    <div>
      <h2>Image 1</h2>
      <img src="img/01.png" id="img1" name="imgs">
    </div>
    <div>
      <h2>Image 2</h2>
      <img src="img/02.png" name="imgs">
    </div>
    <div>
      <h2>Image 3</h2>
      <img src="img/03.png">
    </div>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="js/dom-manip-3.js"></script>
  </body>
</html>

And here is the corresponding JavaScript:

dom-manip-3.js

const images = document.getElementsByName('imgs');
for (let i = 0; i < images.length; i++) {
  alert('Image number ' + i + ' is ' + images[i].height);
}

Open (or reload) index2.html.

  • Two alert boxes should open in succession, each stating the image number and its height.
    • Note that there are three images on the page but that, as expected, we obtain information on only two, those whose name is imgs.

Figure 1: Get elements by name

To use jQuery to the same effect replace the content of domManip.js with:

dom-manip-3.js

const $images = $('[name="imgs"]');
alert('There are ' + $images.length + ' images with name="imgs" in this page');
let index = 0;
$images.each(function () {
  alert('Image ' + index + ' height is ' + $(this).height());
  index += 1;
});

We have included an extra statement here to indicate the number of images with *name=\"imgs\".

  • alert("There are "+ images.length +" images with name="imgs" in this page"); Figure 2: Using jQuery to discover number of elements matching name="imgs"

Note the jQuery syntax to reference the name attribute.

  • $('[name="imgs"]')

Recall the syntax to reference id

  • $("#img1")

index4.html / dom-manip-4.js

In this step we shall retrieve nodes using the native JavaScript method getElementsByTagName and its jQuery equivalent.

The method getElementsByTagName differs from the methods getElementById and getElementsByName in that it can be invoked on any node, not just the document root node as is the case with the latter two methods.

There are two parts to this step.

  • In part 1 we shall retrieve an array of all the images in a web page and print the size of the array in an alert box.
  • In part 2 we shall retrieve an array only of those images in the div node whose id is "ictskills-imgs".

Preparation

  • Download the img2.zip from the local archive, expand and copy the three png images (04, 05,06) to the img folder in WebContent.
    • There will then be six images in the img folder.

Add a new html file:

index4.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

  <div id="ictskills-imgs">
      <div>
        <h2>Image 1</h2>
        <img src="img/01.png" name="imgs">
      </div>
      <div>
        <h2>Image 2</h2>
        <img src="img/02.png" name="imgs">
      </div>
      <div>
        <h2>Image 3</h2>
        <img src="img/03.png" name="imgs">
      </div>
    </div>

    <div id ="computer-science-imgs">
      <div>
        <h2>Image 4</h2>
        <img src="img/04.png" name="imgs">
      </div>
      <div>
        <h2>Image 5</h2>
        <img src="img/05.png" name="imgs">
      </div>
      <div>
        <h2>Image 6</h2>
        <img src="img/06.png" name="imgs">
      </div>
    </div>

    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="js/dom-manip-4.js"></script>
</body>
</html>

Study the changes:

  • We have added 3 extra images.
  • The original 3 images are wrapped in a div with id ictskills-imgs.
  • The new images are in a div with id computer-science-imgs.

Part 1

dom-manip-4.js

const images = document.getElementsByTagName('img');
alert('Number of images in page is ' + images.length);

Open index4.html in Chrome. You should be presented with an alert box as depicted in Figure 1:

Figure 1: Discovered six image tags

To repeat using jQuery, replace the javascript file with the following:

dom-manip-4.js

const images = $("[name='imgs']");
alert("Number of images in page is " + images.length);

Carefully note the jQuery syntax.

Part 2 In this part we shall count the number of images in a specific div.

The html remains unchanged.

Here is the revised javascript:

const imgDiv = document.getElementById('ictskills-imgs');
const images = imgDiv.getElementsByTagName('img');
alert('There are '+images.length+' images in this page');

Replace the content of dom-manip-3.js with the above code and then open index3.html in a browser.

You should see a JavaScript Alert box similar to that in Figure 2. Figure 2: Three images in node whose id is ictskills-imgs

Note what's happening here:

  • We retrieve the node whose id is "ictskills-imgs".
    • This is the div defined within the html as follows:
      • <div id="ictskills-imgs"\></div>
  • We then invoke *getElementsByTagName on this node (an object):
    • imgDiv.getElementsByTagName('img');
    • This allows us to determine the number of images in the node.

Here is the jQuery code.

Filename: dom-manip-4.js

const images = $('#ictskills-imgs [name="imgs"]');
alert('There are '+ images.length +' images with name "imgs" in this page');

The jQuery syntax here requires careful study.

The expression $("[name='imgs']"); would return all images whose attribute name is imgs, 6 in total.

However, the expression $("#ictskills-imgs [name='imgs']"); returns only the images within the node (the div in this case), whose id is ictskills-imgs AND whose attribute name is imgs, a total of 3.

index5.html / dom-manip-5.js

Create a file in WebContent named index5.html with the following content:

Filename: index5.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hide and Reveal</title>
  </head>
  <body>
    <p id="text">Watch me appear and disappear</p>
    <button onclick="hide()">Hide</button>
    <button onclick="reveal()">Reveal</button>

    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="js/dom-manip-5.js"></script>
  </body>
</html>

Create a corresponding JavaScript file in the js folder:

dom-manip-5.js

function hide()  {
  document.getElementById("text").style.visibility = "hidden";
}
function reveal()  {
  document.getElementById("text").style.visibility = "visible";
}

Open show.html in Chrome.

Figure 1: Now you see me

Press Hide.

Figure 2: Now you don't

Press Reveal.

Figure 3: Can't get rid of me that easily

Replace the content of show.js with the jQuery equivalent:

function hide() {
  $('#text').hide();
}

function reveal() {
  $('#text').show();
}

Test as before: the behaviour should be similar.

Exercises

Archive of the project so far: