Today let's talk about going further with JavaScript and jQuery.
 No particular relevance to this image except that perhaps by
	the end of today you'll feel like you've learned some
	JavaScript techniques you can use to make your pages explode
	with joyful psychedelia.
      
	No particular relevance to this image except that perhaps by
	the end of today you'll feel like you've learned some
	JavaScript techniques you can use to make your pages explode
	with joyful psychedelia.
      
    Last time we worked on JavaScript we left off with a folder that looked like this:
 
    Today we're going to add some new files and by the end of the day you should have a working folder that looks like this:
 
    To get started, download the following multimedia files, and save or move them into the right place:
Next, let's make a new page that we can use to experiment with the new techniques for today. I've created a page that contains several paragraphs of lorem ipsum text with some images interspersed, which I hope will seem to you like a plausible page of text that you might be working with for your project.
      Download this file and save it as article.html,
      overwriting the article.html file you already have,
      or, copy/paste the contents of this file into
      your article.html, deleting all the contents first:
      
      If you double-click on article.html right now, it
      looks pretty basic in your browser:
    
 
    
      Let's get started by adding some CSS to clean up that layout a
      bit. First, link this file to our CSS file. Add the following to
      the <link> tag
      inside <head>:
      
  <link rel="stylesheet" href="css/article-style.css">
      Let's look in that CSS file. Not too much there yet. Let's start
      by adding some rules for styling the images. At the end of the
      file after the .header {} rule, add
      this:
      
.header {
  width: 100%;
  height: 100px;
}
img {
    width: 200px;
    border: solid 1px #000;
    margin: 20px;
}
img.left {
    float: left;
}
img.right {
    float: right;
}
      Here I'm setting the width for all the images, adding a black
      border, and some margin spacing around them. I'm also adding two
      rules for images that I've classed
      as left
      and right, floating them appropriately.
    
    Now your page should look like this:
 
      
      Since there was a request for it in class, let's learn how to
      use CSS and JavaScript to add the infamous three bar
      "hamburger
      icon"-style navigation menu
      (≡) to
      this page. It's really quite simple!
    
There are a few different ways you can approach this. One is to use a Unicode text character for the three bars icon. This is what we'll do here. I've adapted this from this really great article from The Intercept related to our class that you might enjoy: "White Supremacists, Conspiracy Theorists Are Targeting Cell Towers, Police Warn". If you're curious, you can right-click on their hamburger menu in the upper-left corner and click "inspect" to poke around and see how this is implemented.
      To get started with this, let's first add the clickable icon in
      a navigation menu area. Add the following HTML code
      into article.html:
      
<body> <div class="main-navigation"> <span class="hamburger-icon"></span> <nav> <a href="">Home</a> <a href="">About</a> <a href="">Contact</a> </nav> </div> <div class="header">The
.main-navigation <div>
      will extend across the width of the page, and be pinned to the
      top of the window and the <span> is where
      we'll put the hamburger icon. <nav> is rather
      like a <div> tag: it does not do much
      formatting on its own, but it has semantic significance, it
      tells the browser that this is navigation text, which might help
      text-to-speech readers or web crawlers or etc. To do anything
      with this we have to style it. Add the following
      into article-style.css:
      
.main-navigation {
    position: fixed;
    top: 0;
    width: 600px;
    height: 35px;
    background-color: #ff88ff;
    z-index: 10;
}
.hamburger-icon {
    display: block;
    font-size: 30px;
    line-height: 30px;
    margin: 0 0 0 10px;
}
.hamburger-icon:before {
    content: "\2261";
}
.main-navigation nav {
    background-color: #ffccff;
    width: 100px;
    margin-top: 5px;
    padding: 5px 0 5px 10px;
}
.main-navigation a {
    display: block;
    color: #ffffff;
    font-family: sans-serif;
    text-decoration: none;
    text-transform: uppercase;
    margin: 8px 0 8px 0;
    padding-left: 10px;
}
.main-navigation a:hover {
    text-decoration: underline;
}
      You can put this anywhere that you like in the file, but I would
      recommend in between lines 9 and 11, before
      the .header rule.
    
    
      There's a lot going on here. Most of it is basic styling stuff
      to make this look nice: setting layout things like widths and
      margins, background colors, etc. Probably the most
      new/interesting is position:
      fixed. This tells the browser to position this item in
      relation to the browser window, meaning that as the user
      scrolls, this item will not move. It is positioned in accordance
      with the top property, which I've set
      here to 0 meaning there are zero pixels
      between the top of this item and the top of the browser window.
    
      Also interesting
      is .hamburger-icon:before. The colon is
      used to indicate what is called
      a pseudo-class. It is not a class specified by
      you in HTML, but rather an implicit class that usually refers to
      the state of the element. For example, you
      could use :hoverto control display
      properties when the user hovers over an element. In this case,
      this style will insert content before the element(s)
      being targeted
      by .hamburger-icon. (You
      can read more here.) The "\2261"
      indicates a special character, in this case the Unicode
      character code for ≡.
    
      One other thing worth noting:
      the .main-navigation a selector is a
      new technique. This targets all <a> tags that
      are inside any elements with
      the .main-navigation class. In this
      case it will target all the hyperlinks inside
      the <nav> element, and it mainly is just
      specifying layout and display properties.
    
Your page should now have this element at the top, and it should stay fixed there no matter if you scroll the page down:
 
      
      If you want to get a little fancier, try
      modifying .main-navigation by deleting
      or commenting out the background-color
      rule, and below it add the following:
      
    background-image: linear-gradient(to bottom right, #ff88ff, #880088);
      Now your page should look like this:
       
      
      Now that we have the clickable menu icon, and the actual menu
      itself, let's hide it and only show it when the user clicks the
      hamburger. First, to hide the menu, add the following property
      to the .main-navigation nav rule:
      
    display: none;
      This will hide the menu by default. Now let's see how to display
      it interactively using JavaScript.      
    
    
      First, to get started with jQuery on this page, we have to
      include the jQuery library, like so: (add this inside
      the <head> tag)
      
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script> <script src="js/article-interaction.js"></script>(Make sure to copy/paste that whole thing. The
integrity attribute assures that the
      file being included is the unaltered file from jquery.com, and
      has not been intercepted and modified by a hacker. This is
      important.)
    
    Next, let's add our custom JavaScript file with our interaction rules. In Atom, create a new file and add the following boilerplate starting code for a jQuery file:
$(document).ready( function(){
});
      And save this file in your js folder
      as article-interaction.js
    
    Now to add the actual interactive code. There are many ways you can do this. Probably the simplest is the following:
    $(".hamburger-icon").click(function(){
    	$(".main-navigation nav").toggle();
    });
      This is saying: target any elements with
      the hamburger-icon class, and for each one, add
      a click event handler. This way,
      whenever the user clicks on the icon it
      will trigger this event handler, which then
      will target any <nav> elements inside
      a .main-navigation element, and for each of those,
      toggle it's visibility. Thus, when the user clicks, if
      the <nav> is hidden, it will be made visible,
      and if the user clicks and it is already visible, it will be
      hidden.
    
    We could do the same thing but with fancier effects like sliding or fading, simply by changing that middle line:
    $(".hamburger-icon").click(function(){
        $(".main-navigation nav").slideToggle();
    });
      or
      
    $(".hamburger-icon").click(function(){
        $(".main-navigation nav").fadeToggle();
    });
      Each of those can also take a numeric argument which would
      specify the amount of time in milliseconds for the effect to
      last. For example:
      
    $(".hamburger-icon").click(function(){
        $(".main-navigation nav").fadeToggle(200);
    });
    
    Now what if instead of the user clicking you wanted them just to hover the mouse over. You could implement that like this:
    $(".hamburger-icon").mouseenter(function(){
     	$(".main-navigation nav").show();
    });
      The selectors and the event handler are the same, but the event
      being handled is now mouseenter, which means when
      the mouse moves over the element without needing to click.
    
    
      This gets a little trickier because we can't use
      the toggle functions, so instead we have to
      implement a second event handler for when the mouse moves away
      from the element:
      
    $(".main-navigation nav").mouseleave(function(){
    	$(".main-navigation nav").hide();
    });
      
      Note that now the selector is indicating that
      the mouseleave event is being handled when the
      mouse moves away from the actual menu itself. This seems to me
      to make the most sense as a user interface behavior, but you
      could experiment with different methods yourself.
    
    Let's move on to some techniques for highlighting or emphasizing multimedia content that you'd like the viewer to focus on, based on where they're at in the article in terms of their scrolling. What we'll do is gray out all the images, and then give them color to indicate focus or attention. Start by graying out all the images with the following rule:
img {
    width: 200px;
    border: solid 1px #000;
    margin: 20px;
    filter: grayscale(1);
}
      
    
    Now let's add some JavaScript to handle scrolling events, and try to use some math to figure out which elements are in the middle of the window, which we'll consider "active." Probably easiest for me to include a chunk of code here and then explain:
    $(window).on("scroll", function() {
	var halfwayPoint = window.innerHeight / 2;
	
	$("img").each(function() {	
	    var imgY = $(this).get(0).getBoundingClientRect().y;
	    if ( Math.abs(imgY - halfwayPoint) < 50 ) {
		$(this).css("filter","none");
	    } else {
		$(this).css("filter","grayscale(1)");
	    }
        });
    });					 
      What this is doing first of all is adding an event handler that
      is triggered whenever the window (specified in jQuery
      as $(window)) is scrolled. Now inside this event
      handler, first the halfway point of the window as measured in
      pixels is calculated: window.innerHeight / 2 and
      that number is saved for later use as halfwayPoint.      
    
    
      Next, for every <img> tag on the page
      ($("img").each(...) the jQuery
      function .each() loops over every element that
      matches that selector and applies the following code to it.
      Inside that code, $(this) refers to the
      "current" <img> element that matched. This is
      almost like a for loop that iterates over a list,
      and each time through, sets some variable to the next item in
      the list.
    
      So then $(this).get(0).getBoundingClientRect().y
      accesses the current y position in pixels of
      the <img> being looked at. imgY -
      halfwayPoint is the difference between
      the <img>'s y position as it is
      scrolling and the middle point of the window. This value could
      be positive or negative (if the image is above or below the
      halfway point) so we take Math.abs() to always get a positive
      value. Now, if that distance is less than 50 (which could be
      above or below) then we turn off the
      filter .css("filter","none"), otherwise we apply
      grayscale with .css("filter","grayscale(1)"
    
Try this out and see what you get!
We can get a bit fancier. Have a look at this:
    $(window).on("scroll", function() {
        var halfwayPoint = window.innerHeight / 2;
    
	$("img").each(function() {	
	    var imgY = $(this).get(0).getBoundingClientRect().y;
	    var distanceFromCenter = Math.abs(imgY - halfwayPoint);
	    if ( distanceFromCenter < 50 ) {
		var fadeFactor = distanceFromCenter/50;
		$(this).css("filter","grayscale("+fadeFactor+")");
	    } else {
		$(this).css("filter","grayscale(1)");
	    }
	});
    });
      Here I'm calculating this variable fadeFactor
      simply by dividing the distance by 50. The maximum value for
      that distance is 50, and the minimum value is 0, so dividing by
      50 is going to give me a value between 0 and 1. It turns out
      that is precisely the range of values that the
      CSS grayscale filter takes, so we can
      pass that value in to that. Now as an image approaches the
      middle of the window, it should have a quick fade to color
      effect.
    
    As a last technique, let's look at how we can connect scrolling to triggering the play of a multimedia object like audio or video material.
      First let's add a video object to the page. I'll replace the
      second image, named one-wilshire-meet-me-room.jpg
      with a >video> tag:
      
      <video class="left">
	<source src="video/antenna.mp4" type="video/mp4">
	  Your browser does not support the video element.
      </video>
      We could specify this as autoplay, using
      that attribute in the <video> tag itself, but
      let's leave that off and triffer it by scrolling. We do that by
      adding another scroll event handler, with some
      changes:
      
    $(window).on("scroll", function() {
	var halfwayPoint = window.innerHeight / 2;
	$("video").each(function() {
	    var videoY = $(this).get(0).getBoundingClientRect().y;
	    var distanceFromCenter = Math.abs(videoY - halfwayPoint);
	    if ( distanceFromCenter < 50 ) {
		$(this).trigger("play");
	    }
	});
    });
      This time we're calling .each() on all
      the video elements. And for each one we are again
      getting the y position in pixels of the video
      element: $(this).get(0).getBoundingClientRect().y;,
      and we are again calculating the distance between this element
      and the middle of the window. But this time, if that distance is
      less than 50, we're triggering the video to
      play: $(this).trigger("play").
    
    
      Try this and see what happens. If you're using Chrome it won't
      work. Why? Open up the console and try again. You might need to
      reload. The error message I got included a URL point
      to this
      help page. That explained that Google Chrome now disables
      autoplay unless the user first interacts somehow with the
      window, and apparently just scrolling does not count as an
      interaction. They do however allow autoplay if the
      video is muted. So let's add the muted attribute to
      our <video> tag:
      
      <video class="left" muted>
      Now I believe it should work!!
    
    We have been working on three files during the course of this lesson. I hope you take the time to work through the instructions and discussion above step-by-step to try to code these files yourself. If you would like to see how the resulting three files should probably look after doing all these exercises, you can find them all here: