You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

193 lines
53 KiB

import { addBanner, addArticle, addHeader, addSubHeader, addParagraph, addCaption, addQuote } from '/scripts/article.js';
import { addInset, addInsetList, addInsetCodeListing, addInsetBulletList } from '/scripts/inset.js';
import { addImageWithCaption, addButtonGroup } from '/scripts/visuals.js';
import { menu } from "/scripts/web_dev_buttons.js";
const main = document.querySelector("main")
main.append(addBanner("jQuery Essential Training", "Joe Marini : September 2016", "A QUICK INTRODUCTION TO jQUERY"))
main.append(addArticle())
const article = document.querySelector("article")
article.append(addHeader("Your First jQuery-Enabled Page"))
article.append(addParagraph("We will start to explore jQuery by prducing a very simple web page that makes use of it. The web page will"))
article.append(addInsetCodeListing(["Link to the jQuery library.", "Set up an event handler that is triggered when the DOM is loaded.", "Insert some content confirming that jQuery has loaded and is working as expected."]))
article.append(addParagraph("Linking to the jQuery library is simply a matter of using a script tag like this"))
article.append(addInset("<script src=\"/jQuery/jquery-3.6.3.js\"></script>"))
article.append(addParagraph("We will insert the event handler into the webpage in the head and it looks like this."))
article.append(addInsetCodeListing(["<script>", " $(\"document\").ready(function() {", " $(\"#content\").append(\"<p>The page just loaded</p>\");", " })", "</script>"]))
article.append(addParagraph("In line 2, we use the $ sign which usually indicates that you are using a variable and in this case, this is from jQuery and in effect, we are grabbing the document - the actual web page - so that we can reference it in our code. We are then passing the ready function to it. This is a jQuery function and this sets up an event listener that will be triggered when the page's DOM is fully parsed. Notice that this takes a callback function as an argument so what we are saying to the ready function - so to speak!! - is please execute this callback function when the DOM has been fully parsed."))
article.append(addParagraph("Just as we had grabbed the document, the callback function is grabbing an HTML element and we can see that it is using CSS syntax to reference that element. In other words, it is using the hash symbol to denote an id so it is getting the HTML element from the DOM that has that id, with the id being content at this stage. Again, this allows us to reference the element in code and we are passing the append function to it. That function is using a fully formed HTML element as an argument so we are attaching this element to the element with that id."))
article.append(addParagraph("At this point, my HTML page doesn't have any content so I will insert an H1 element which displays the text 'First jQuery Page' and a div element with the id, content, but the element itself will be empty."))
article.append(addParagraph("The body of this HTML page would therefore look like this"))
article.append(addInsetList["<body>", "<h1>First jQuery Page</h1>", " <div id=\"content\">", " <!-- we start with an empty document -->", "</div>", "<\body>"])
article.append(addParagraph("Assuming that this all works as we think it will, when you open the page you should see the header followed by the paragraph that should be added by the callback function as soon as the DOM has been parsed completely. To see that in action, click <a href='./samples/firstjquerypage.html' target='_blank'>here</a>."))
article.append(addParagraph("Just a quick note regarding the ready function. This is quite similar to the onload function. The main difference is that the onload function waits for the whole page to be loaded so that can take quite a bit longer, particularly if the page has a lot of multimedia components such as images or video files. In comparsion, these elements only have to be parsed - that is, they have to be added to the DOM tree - in order for ready to be called, they don't have to be fully loaded."))
article.append(addParagraph("In order to get a better idea of how jQuery simplifies our code, it might be interesting to see the code that would acheive the same thing if we didn't have jQuery available. The code is as follows:"))
article.append(addInsetCodeListing(["&lt;script&gt;", " // Inserting content the old way using the DOM ", " window.addEventListener(\"DOMContentLoaded\", function(evt) {", " var elem = document.getElemen yId(\"content\");", " var para = document.createElement(\"p\");", " var text = document.createTextNode(\"The page just loaded.\");", " para.appendChild(text);", " elem.appendChild(para);", " });", "&lt;/script&gt;"]))
article.append(addParagraph("In this case, we are using the addEventListener function to add a listener to the window object. The event is called DOMContentLoaded so this corresponds to the ready function. "))
article.append(addParagraph("Again, we are passing in a callback function. Within the function, we are creating a variable to reference the element with id, content. We then create a paragraph element and a text element. The text element is added to paragraph and the paragraph is then added to the target element in the page (remember, this is has an id of content)."))
article.append(addParagraph("So, the jQuery callback function required a single line of code, but without jQuery, we needed 5 lines of code. Both functions, however, acomplish exactly the same thing."))
article.append(addParagraph("To show that this is the case, I have revised the HTML page to include both methods and you can see the result <a href='./samples/firstjquerypage2.html' target='_blank'>here</a>."))
article.append(addHeader("Selectors and Filters"))
article.append(addParagraph("Selectors and filters are very important in jQuery and they use a CSS-like syntax in order to target DOM elements. In order to demonstrate how this works, we have a fairly basic HTML page with a variety of headers, paragraphs and divs as shown below."))
article.append(addInsetCodeListing(["&lt;body&gt;", " &lt;h1 id=\"intro\"&gt;Introduction to jQuery Selectors and Filters&lt;/h1&gt;", " &lt;div id=\"content\"&gt;", " &lt;p&gt;Selectors and Filtersprovide a way of finding and extracting information from Web pages.&lt;/p&gt;", "", " &lt;h2 class=\"selectors\"&gt;Selectors&lt;/h2&gt;", "&lt;p&gt;Selectors are used to select parts of the Web page using a common CSS-style syntax.&lt;/p&gt;", " &lt;p&gt;For example, &lt;code&gt;$(\"p\")&lt;/code&gt; will select all of the paragraph tags in a document and return them as a list that can be further operated upon.&lt;/p&gt;", "", " &lt;h2 class=\"filters\"&gt;Filters&lt;/h2&gt;", " &lt;p&gt;Filters are used to further refine the results returned from selectors.&lt;/p&gt;", " &lt;p&gt;For example, &lt;code&gt;$(\"p:first\")&lt;/code&gt; will select the first paragraph in the returned set from &lt;code&gt;$(\"p\")&lt;/code&gt;.&lt;/p&gt;", " &lt;/div&gt;", "&lt;/body&gt;"]
))
article.append(addParagraph("We also have a little bit of jQuery which we will use to target these elements this is shown below."))
article.append(addInsetCodeListing(["&lt;script type=\"text/javascript\"&gt;", " $(\"document\").ready(function() {", " //$(\"p\").css(\"border\", \"3px solid red\");", " //$(\".selectors\").css(\"border\", \"3px solid red\");", " //$(\"#intro\").css(\"border\", \"3px solid red\");", " //$(\"p:first\").css(\"border\", \"3px solid red\");", " //$(\"h2:not(.selectors)\").css(\"border\", \"3px solid red\");", " });", "&lt;/script&gt;"]))
article.append(addParagraph("The lines in the callback function have all been commented out so that we can see the effect of the different lines of code in a controlled manner. Let's start by looking at the page with all the lines commented out whucge we can see <a href='./samples/selectors1.html' target='_blank'>here</a>."))
article.append(addParagraph("If I enable this line"))
article.append(addInset("$(\"p\").css(\"border\", \"3px solid red\");"))
article.append(addParagraph("Here, we are using p as a selector and it will select all p elements in the document. We are then using the method css to apply some CSS rules to the selected elements and the result is shown <a href='./samples/selectors2.html' target='_blank'>here</a>."))
article.append(addParagraph("We are passing a couple of things over to the css function. The first is \"border\" which specifies a CSS property amd the second is the value we want to set."))
article.append(addParagraph("In CSS this would look something like"))
article.append(addInsetList["p {", " border: 3px solid red", "}"])
article.append(addParagraph("As you can see (and probably could have guessed), the effect is to put a border with a width of 3 pixels and a colour of red around every paragraph element."))
article.append(addParagraph("I will comment that line out again and this time enable the second line"))
article.append(addInset("$(\".selectors\").css(\"border\", \"3px solid red\");"))
article.append(addParagraph("This is similar to the first line in that we are using a selector and following CSS syntax so the . at the start of the selector name indicates that we are selecting any element that has a class of selectors. It might be worthing noting at this point that when you are writing code like this either using jQuery or just writing standard CSS rules, the first step in understanding what selector you should use or that the effect of it will be is to look at the HTML code. There, we can see that there is just one element with the class selectors and that is the first h2 element so we would expect that and only that to now have a red border. We can see <a href='./samples/selectors3.html' target='_blank'>here</a> that this is exactly the result we are getting."))
article.append(addParagraph("The third line"))
article.append(addInset("$(\"#intro\").css(\"border\", \"3px solid red\");"))
article.append(addParagraph("is very similar to the second. Again, we are using CSS syntax so the # symbol represents an id which means that we are targetting an element with the id of intro. One important difference here is simply the difference between a class and an id in that with the class, we were targetting a single element because only one element has that class. However, we could apply that class to other elements if we wanted to so we can use a class selector to target a set of elements. You might also turn that around and say that we can apply the class to a number of elements if we want to be able to work on them as a set."))
article.append(addParagraph("Again, we can inspect our HTML to see what is being targetted here, this time it is the second h2 element and we can see in the HTML page <a href='./samples/selectors4.html' target='_blank'>here</a> that the border is around the second h2 element."))
article.append(addParagraph("The next line looks a little different to what we have seen before."))
article.append(addInset("$(\"p:first\").css(\"border\", \"3px solid red\");"))
article.append(addParagraph("The syntax here is definitely CSS-like at the very least but I am not completely sure if this is genuinely valid CSS. It does look like a CSS pseudo-class selector. For example, the CSS selector"))
article.append(addInset("p:first-of-type"))
article.append(addParagraph("can be used in CSS to target the first p element. In jQuery"))
article.append(addInset("p:first"))
article.append(addParagraph("does exactly the same thing so it's not complete;y unreasonable to consider it to be CSS syntax. In any case, the result we would expect to see is that the first paragraph only now has a red border and we can confirm that <a href='./samples/selectors5.html' target='_blank'>here</a>."))
article.append(addParagraph("This is an example of using a filter or at least, what is referred to as a filter in jQuery. I would probably not consider to be a filter because it is selecting out an element based on its position in the code rarther than on its value but that's just a personal opinion sidebar! In any case, the filter does allow us to select one p element out of all of them."))
article.append(addParagraph("The last line is"))
article.append(addInset("$(\"h2:not(.selectors)\").css(\"border\", \"3px solid red\");"))
article.append(addParagraph("is probably the most difficult to guess the meaning of but it is another example of using a filter in jQuery to target specific elements. In this case, we are selecting h2 elements. The filter is specifying that the element or elements should not have a class of selectors so again, we can look at the HTML code. Remember, we had two h2 elements, one of which has a class of selectors with the other having an id of intro so we this tells us that the filter will select the second h2 element since that is the one that doesn't have selectors as a class. We can confirm that by checking out the website <a href='./samples/selectors6.html' target='_blank'>here</a>."))
article.append(addParagraph("There are a couple of things I want to mention before we finish this section. Firstly, all of the selectors and filters we demonstrated here selected a single type of element and in some cases such as when we use a tag selector as we did in the first example or the id selector in the third example, then we will always see a single type of element being returned. In the first case, this is because we are selecting elements of a single specific type and in the third because an id has to be unuique so it can only select a single element so we can't select different elements or different element types with a single id selector."))
article.append("Secondly, we really just skipped over selectors and elements here and you will see that a lot in this chapter. This is deliberate since it is intended to be just a very quick introduction to jQuery but we will go into more detail on specific topics such as selectors and filters in subsequent chapters.")
article.append(addHeader("Creating and Modifying Page Content"))
article.append(addParagraph("In this section, we will take a quick look at how we can use jQuery to create and modify the content of a web page. We will start with a basic web page with the body as shown below"))
article.append(addInsetCodeListing(["&lt;body&gt;", " &lt;h1 id=\"intro\"&gt;Using jQuery to Create/Change Content&lt;/h1&gt;", " &lt;div id=\"content\"&gt;", "", " &lt;p&gt;jQuery makes it very easy to create new page content and change existing page content.&lt;/p&gt;", " &lt;h2 id=\"creation\"&gt;Content Creation&lt;/h2&gt;", " &lt;p&gt;Creating new content is as simple as passing a string of HTML to the $() function.&lt;/p&gt;", " &lt;p&gt;For example, &lt;code&gt;$(\"&lt;p&gt;\")&lt;/code&gt; creates a new, empty paragraph tag. To add new content to the paragraph, you could simply write &lt;code&gt;$(\"&lt;p&gt;\").append(\"&lt;em&gt;Hello there&lt;/em&gt;\")&lt;/code&gt;.&lt;/p&gt;", " &lt;h2 id=\"changing\"&gt;Changing Content&lt;/h2&gt;", " &lt;p&gt;There are multiple ways to change page content using jQuery, depending on your needs.&lt;/p&gt;", " &lt;p&gt;The &lt;code&gt;html()&lt;/code&gt; and &lt;code&gt;text()&lt;/code&gt; functions can be used to directly manipulate the contents of elements, and there are ways to control how content can be inserted and moved around in the page.&lt;/p&gt;", " &lt;div id=\"example\"&gt;", " &lt;/div&gt;", " &lt;/div&gt;", "&lt;/body&gt;"]))
article.append(addParagraph("We also have some jQuery code in the head which is commented out so once again we will enable various lines and examme the effect that each one has."))
article.append(addInsetCodeListing(["&lt;script type=\"text/javascript\"&gt;", " $(\"document\").ready(function () {", " //create some new content", " //var newP = $(\"&lt;p&gt;\");", " //newP.append(\"&lt;em&gt;Hello There&lt;/em&gt;\");", " //", " //$(\"#example\").html(newP);", " //", " //$(\"#creation\").prepend(\"Watch This! \");", " //", " // change the existing content", " //$(\"#example\").html(\"&lt;h2&gt;This is a new H2&lt;/h2&gt;\");", " //", " //$(\"#example\").text(\"&lt;h2&gt;This is a new H2&lt;/h2&gt;\");", " });", "&lt;/script&gt;"]))
article.append(addParagraph("You can click <a href='./samples/create1.html' target='_blank'>here</a> to see what the page looks like before any of the jQuery code is enabled."))
article.append(addParagraph("I will enable the first two lines of the jQuery code"))
article.append(addInsetList(["var newP = $(\"&lt;p&gt;\");", "newP.append(\"&lt;em&gt;Hello There&lt;/em&gt;\");"]))
article.append(addParagraph("You should think about what difference, if any, this will make before clicking <a href='./samples/create2.html' target='_blank'>here</a> to see what the effect is."))
article.append(addParagraph("If you were expecting there to be no change, you would be right, so let's look at what both of these lines of code are doing. The first line is creating a new variable called newP and it's setting a value for that variable. Essentially, the value is a type in HTML terms with the overall effect that we are creating an HTML paragraph."))
article.append(addParagraph("The next line is adding text to that paragraph, providing its content. So we have a paragraph and it has some content, but it hasn't been added to the page yet. In order to make it appear on the page, we will enable the next lie of code."))
article.append(addInset("$(\"#example\").html(newP);"))
article.append(addParagraph("Before we look at what this does, let's quickly check whether this has caused our new paragraph has appeared by clicking <a href='./samples/create3.html' target='_blank'>here</a> and we should see that it has been added on to the end of the file."))
article.append(addParagraph("Figure 1 shows the page in a browser with the web developer tools shown to the left and this is showing the page HTML."))
article.append(addImageWithCaption("./images/create1.png", "Figure 1 - Inspecting the HTML for our page after the new paragraph has been added."))
article.append(addParagraph("We can see the paragraph that has been added near the bottom and we can see that it is enclosed in an em tag, which in turn is inside a p tag - this is the HTML we added. Note also that this is inside a div element and that div element has an id of example."))
article.append(addParagraph("Going back to the jQuery code, we have a selector which is an id with a value of example, so we are targetting that div element. We are passing the html method to it and in jQuery, this function can set or return the content of an HTML element - for more info on this, see <a ref='https://www.w3schools.com/jquery/html_html.asp'>jQuery html() method</a> on <a href='https://www.w3schools.com/jquery/default.asp'>w3schools.com</a>. So we are setting the innerHTML (or content) of that div element with the new paragraph and that's exactly what we see in the HTML shown in figure 1."))
article.append(addParagraph("To sum up, we have added a paragrpah to our HTML page using jQuery and this was a three step process."))
article.append(addInset("Step 1 - we used jQuery to create an HTML element referenced by the variable newP."))
article.append(addInset("Step 2 - we used the append method to set the content of newP."))
article.append(addInset("Step 3 - we used an id selector to target the empty div in the HTML and the html method to set the content of that div to newP."))
article.append(addParagraph("Note that the html function is setting the value of the div element. In this case, it was empty but if it already had some content, this would overwrite the existing content with newP."))
article.append(addParagraph("For the next example, I have commented out these three lines again and enabled the line"))
article.append(addInset("$(\"#creation\").prepend(\"Watch This! \");"))
article.append(addParagraph("Again, you might want to think about what this does. It is using a selector to target the element with an id of creation and from the HTML, we can see that this corresponds to the first of the two h2 elements. Without being familiar with the prepend function, we could guess that it is tacking the text provided as an argument to the front of the existing content. We can check if that is the case by clicking <a href='./samples/create4.html' target='_blank'>here</a>."))
article.append(addParagraph("So we can see that the text has been added to the content of the h2 element at the front and from the way it is styled - that is, the text is the same size as the text that was already in the h2 element and the same colours have been applied - we can reasonably assume that it has become part of the element rather than being added as a new element in front of it. To check this, again we can inspect the HTML using the web developer tools as shown in figure 2."))
article.append(addImageWithCaption("./images/create2.png", "Figure 2 - Inspecting the HTML for our page after some has been prepended to the first h2 element."))
article.append(addParagraph("Note the contents of that h2 element in particular which are also shown below."))
article.append(addInsetList(["&lt;h2 id=\"creation\"&gt;", " &lt;h2&gt;", " Watch This!", " Content Creation", "&lt;/h2&gt;"]))
article.append(addParagraph("This confirms that the text we predended onto the h2 element has been added to the content of that element at the front."))
article.append(addParagraph("I have now commented that line out again and enabled the line"))
article.append(addInset("$(\"#example\").html(\"&lt;h2&gt;This is a new H2&lt;/h2&gt;\");"))
article.append(addParagraph("It might not be immediately clear what this does, but we have already seen that the html function in jQuery sets the content for an element and unlike prepend, it overwrites ay content that was already there. The selector has targeted the p element, the one that has example as an id and recall that this is an empty element. We did add some content to it in our first example, but those lines of code were the commented out so as things stand, the element is empty again. You should bear in mind that the h2 opening and closing tags are part of the innerHTML and so must be included."))
article.append(addParagraph("If you open the page for this example by clicking <a href='./samples/create5.html' target='_blank'>here</a>, you will see, as expected, that we now have a new h2 element at the bottom of the page as shown in figure 3."))
article.append(addImageWithCaption("./images/create3.png", "Figure 3 - The new HTML element added to the bottom of the HTML document inside the div element with the id example."))
article.append(addParagraph("We can also see by inspecting the HTML that the new h2 element has been placed inside the example id. As an experiment, I am going to diverge slightly from the course and try amending the statement so that it reads"))
article.append(addInset("$(\"#changing\").html(\"&lt;p&gt;This is a new P&lt;/p&gt;\");"))
article.append(addParagraph("So this time, we are targetting the second h2 element which already contains some text wrapped up in h2 tags, but we are going to change this so that the content is replaced by a paragraph. This is intended to show that we can use the html method to change element types and if that is the case, looking at the page with the converted code, we should see that there is now only onw h2 element with the second one being converted to a paragraph with the text - this is a new P. To see if this worked as expected, click <a href='./samples/create5a.html' target='_blank'>here</a>."))
article.append(addParagraph("The result is also shown in figure 4 and I think this is a useful lesson in that it didn't work quite as I though that it would. I had forgotten to take into account the fact that we are adding the new text as the content of an existing h2 element but the content is inside the h2 element. This means that we have done something that looks weird in the HTML, we have placed a p element inside an h2 element. So the text is a p element but because it is inside the h2 element, it has inherited the styling"))
article.append(addImageWithCaption("./images/create4.png", "Figure 4 - The result of our experiment using the html function to change the type of a element."))
article.append(addParagraph("In order to prove that the text inside the header is a paragraph, I have added a new rule to the CSS which changes the background colour of a paragraph to lime green. The results are shown in figure 5."))
article.append(addImageWithCaption("./images/create5.png", "Figure 5 - The result of our experiment using the html function to change the type of a element showing a restyled p lelement."))
article.append(addParagraph("You may already know that CSS rules determine which rules are applied to a particular element when there is a conflict. In this case, h2 elements have a background colour of aqua and p elements have a lime green background. These are both tag selectors so they have equal weight but I also placed the new CSS rule for p after the rule for h2 just to be certain that the rule would be picked up. The results don't look great so please don't think I am presenting this as a good example of styling a web page. We can see that all of the paragraphs have the lime green background."))
article.append(addParagraph("This includes the p element we inserted into a h2 element. Notice, however, that it has a blue background. This is because the h2 element still has a background colour of aqua and the contained p element does not entirely fill its h2 container - there are margin rules in place. As a result, we can see that an element with a lime green background is placed on top of an element with a blue background so we this also shows us what part of this element the paragraph occupies and it also shows us what portion of the viewport that the h2 element is occupying."))
article.append(addParagraph("That was just a fun diversion and it shows that you can kind of use html to change an elements type to an extent, but you would need to be careful about how you do that and be aware of what sort of element is going to be containing the new element. However, even if you do it correctly, the results could be unpredictable in terms of CSS rules being applied and can be messy in terms of the HTML that it generates."))
article.append(addParagraph("Personally, I would say that this technique cannot be recommended. You could think of it this way. If you were hand-coding your HTML, would you put a p element inside an h2 element? If the answer is no, then if you generate HTML like that using jQuery, it is reasonable to say that this is a bad usage for the jQuery - that is, it is generating bad HTML code."))
article.append(addParagraph("I would guess that jQuery does provide a method for changing the type of an element, but I would say with some degree of certainty that the html function is NOT the way to do that!"))
article.append(addParagraph("The last line of our jQuery code looks pretty similar to the line before."))
article.append(addInset("$(\"#example\").text(\"&lt;h2&gt;This is a new H2&lt;/h2&gt;\");"))
article.append(addParagraph("It looks as though it will do at least roughly the same thing as the prevous statement but using the text rather than the html function. Rather than looking up the function to see what it does, let's try it out, inspect the HTML that is generated and see if we can figure what, if anything is different when we use the text function rather than the html function. Let's start with ehat we already know!"))
article.append(addParagraph("So, it is using the same selector as in the previous example and it is targeting the empty element. It is passing it the text method with a string containing a replacement for the elements content - possibly! The result can be seen <a href='./samples/create6.html' target='_blank'>here</a> as well as in figure 6 along with the generated html."))
article.append(addImageWithCaption("./images/create6.png", "Figure 6 - The result of our experiment using the html function to change the type of a element showing a restyled p lelement."))
article.append(addParagraph("We can see in the displayed page and the HTML seen in the developer tools that the text has been added to the div element, but the tags themselves have been included in the text. In other words, the string has been interpreted strictly as a literal string rather than being passed so the element as something that could be parsed as HTML. Think of it this way, if you display some text in HTML that looks like this."))
article.append(addInset("&lt;p&gt;This is a paragraph.&lt;/p&gt;"))
article.append(addParagraph("this would be interpreted as a p element in HTML so you would get the output as simply"))
article.append(addInset("This is a paragraph"))
article.append(addParagraph("If you compare this to what happens when the text looks like this"))
article.append(addInset("&amp;lt;p&amp;gt;This is a paragraph.&amp;lt;/p&amp;gt;"))
article.append(addParagraph("the output looks like this."))
article.append(addInset("&lt;p&gt;This is a paragraph.&lt;/p&gt;"))
article.append(addParagraph("Note that when I say - looks like this - I mean as displayed here. The HTML entities are how I am able to display HTML code as HTML code - that is, with the tags shown - without the browser interpreting the tags so I guess something like this is happening with that text function."))
article.append(addParagraph("If you look up <a href='https://www.w3schools.com/jquery/html_text.asp'>jQuery text() method</a> on the w3schools.com site, it describes the function as being designed to set the text content of the selected element. You can also use it without an argument if you want to just get the current text of that element."))
article.append(addParagraph("So the two methods, html() and text() are quite similar but html() is used to insert some HTML code - in other words, some text wrapped in HTML tags whereas text() is used to just insert some text into an HTML element."))
article.append(addHeader("Handling Events"))
article.append(addParagraph("Most modern websites, if not all, have to have some form of event handling so we will briefly introduce the topic here. We'll start by looking at an example and this time, it is a fully formed webpage - nothing is being commented out. We will start by clicking <a href='./samples/events1.html' target='_blank'>here</a> to look at the page and how it behaves."))
article.append(addParagraph("Note that this requires some of the CSS created for this course whereas I have been using my own CSS so I have copied the rules from the CSS file in the Exercise Files foder into my own. This allows the code in the events example to work but it also means that if you look at previous examples, these will now look a little different than the screenshots shown above. This is just a matter of styling and doesn't affect the functioning of any of the examples at all."))
article.append(addParagraph("Back to the example. The page is listening for a number of events including mouse movement, mouse click, mouse entering the blue area and mouse leaving the blue area. Let's look at the code, starting with the HTML."))
article.append(addInsetCodeListing(["&lt;body&gt;", " &lt;h1&gt;jQuery Event Handling&lt;/h1&gt;", " &lt;div id=\"content\"&gt;", "", " &lt;p&gt;jQuery normalizes an event structure across browsers and provides cross-browser consistency for properties such as the event name, the page coordinates of the mouse, the element where the event originated along with any other element related to the event, and information such as whether a meta-key or specific mouse button was pressed.&lt;/p&gt;", " &lt;div id=\"example\"&gt;", " &lt;/div&gt;", " &lt;/div&gt;", "&lt;/body&gt;"]))
article.append(addParagraph("There is nothing particularly noteworthy about the HTML. The jQuery code is a little more interesting."))
article.append(addInsetCodeListing(["&lt;script type=\"text/javascript\"&gt;", " $(\"document\").ready(function() {", " $(\"#example\").on(\"mousemove\", onMouseOver);", " $(\"#example\").on(\"click\", onMouseClick);", " $(\"#example\").on(\"mouseleave\", onMouseLeave);", " });", "", " function onMouseOver(evt) {", " $(\"#example\").text(evt.type + \": \" + evt.pageX + \", \" + evt.pageY + \"\n\" + \"Button: \" + evt.which + \" Key: \" + evt.metaKey);", " }", " function onMouseClick(evt) {", " $(\"#example\").text(evt.type + \": \" + evt.pageX + \", \" + evt.pageY);", " $(\"#example\").off(\"mousemove\", onMouseOver);", " }", " function onMouseLeave(evt) {", " $(\"#example\").text(\"mouseleave\");", " }", "&lt;/script&gt;"]))
article.append(addParagraph("In jQuery, events are reasonably straightforward and we have a couple of functions, on and off which are used to start listening and stop listening for an event respectively. As you can see in the jQuery code, we have added these event handlers to the ready function so as soon as the DOM has been parsed, the events are being added. Let's take one example of that and break it down."))
article.append(addInset("$(\"#example\").on(\"mousemove\", onMouseOver);"))
article.append(addParagraph("From the selector, we can see that the HTML element we are targetting is the element that has the id example and this is an empty div as we can see in the HTML. We are using the on function so we are telling this element to start listening for some event and we have two parameters. The first is the name of the event and the second is the function that is executed when that event is triggered."))
article.append(addParagraph("For each of the events we added a callback function and each callback function accepts something called the jQuery unified event object as a parameter - this is the evt parameter. We will go into that in more detail in the chapter covering events, but for the moment we could say that we are passing the event over to the event handler. This is someting that jQuery uses in part to allow jQuery to standardise the data that is being passed over as part of the event regardless of the browser being used."))
article.append(addParagraph("Within the functions, we can see that they are making use of the data that has been passed over as part of the event. For example, the onMouseClick uses the coordinates of the event. What I mean by that is that when the mouse is clicked, which is an event, the x and y coordinates are captured as part of the event so the handler can use that data to output the coordinates of the mouse when the click occured. These are the evt.pageX and evt.pageY variables shown in the function. These look like object attributes which reinforces the notion that the event is an object, which of course it is! We also have the evt.type which is used to identify, not surprisingly, the type of the event and these are used with the text() function to set the text in the HTML element so that it is displayed on the page."))
article.append(addHeader("Animating Page Content"))
article.append(addParagraph("Again, we will start by looking at the page for this example which demonstrates some very simply animation and you can see this <a href='./samples/events1.html' target='_blank'>here</a>."))
article.append("The HTML for the page is fairly straightforward.")
article.append(addInsetCodeListing(["&lt;body&gt;", " &lt;h1&gt;Quick jQuery Animation Intro&lt;/h1&gt;", " &lt;div id=\"content\"&gt;", " &lt;p&gt;jQuery provides some basic animation features for showing and hiding elements, as well as a low-level animation function that can be used to animate several CSS properties (as long as they are numeric).&lt;/p&gt;", " &lt;button id=\"go\"&gt;Start Animation&lt;/button&gt;", " &lt;div id=\"testDiv\"&gt;&lt;/div&gt;", " &lt;/div&gt;", "&lt;/body&gt;"]))
article.append(addParagraph("The jQuery is inside a script tag in the head of the HTML document."))
article.append(addInsetCodeListing(["&lt;script type=\”text/javascript\”&gt;", " $(\”document\”).ready(function() {", " $(\”#go\”).click(function() {", " $(\”#testDiv\”).animate({width: 400}, 300) ", " .animate({height: 300}, 400) ", " .animate({left: 200}, 500) ", " .animate({top: \”+=100\”, borderWidth: 10}, \”slow\”)", " });", " });", "&lt;/script&gt;"]))
article.append(addParagraph("We also have some CSS which is inside style tags in the head of the document."))
article.append(addInsetCodeListing(["&lt;style&gt; ", " #testDiv {", " position: relative; ", " width: 150px; ", " height: 100px; ", " margin: 10px; ", " padding: 20px; ", " background: #b3c8d0; ", " border: 1px solid black; ", " font-size: 16pt; ", " cursor: pointer; ", " }", "&lt;/style&gt; "]))
article.append(addParagraph("You may know that CSS is useful in creating animations. In this example it is simply setting up the initial state so it is setting, for example, the position value, cooridinates, border paramters and so on."))
article.append(addParagraph("The actual animate is handled by the animate function in jQuery and this worth by setting CSS for the box which is being animated. So essentially, what you see as animation is actually jQuery manipulating the CSS values to change the width, height, position relative to the left side of the screen and finally position relatibe to the top whilst simultaneously increasing the border width."))
article.append(addParagraph("Let's look at a couple of the calls to the animate function to better understand this. Be aware that simply changing the value of a CSS property will not give you an animation effect. For instance, if you change a value in your CSS, let's say the width of a box, save the changes and refresh the page, or of you implement a CSS rule in response to some event, the user will just see a change. To further explain, consider this line of code."))
article.append(addInset("$(\"#testDiv\").animate({width: 400}, 300)"))
article.append(addParagraph("This is going to get the testDiv element from the HTML and apply a new width rule. Notice that the animate function takes two arguments. First is a key value pair with a CSS property as the key and the value being the value we want to set it to. The second argument is the time (in milliseconds) for the transformation to take place."))
article.append(addParagraph("The course doesn't go into detail regarding the animate function and how it achieves this and I would guess that it is likely beyond the scope of this course. Remember, the purpose of the course is to learn jQuery and jQuery provides functions like animate so that you can use them without having to be able to write them yourself so you can think of it like a black box. As long as you know what values to feed into it, it will churn out the desired effect. That being said, jQuery is open-source so you can check it out to find out how it achieves the effect if you are interested. Personally, I think that it is healthy for a developer to be interested in how the function works so I would recommend studying it or any of the fuctions you may be interested in, but I will not include that here unless it is covered by the course."))
article.append(addParagraph("What we do need to know is that the animate function will not just set the width of our div to 400, it will calculate the steps required to get there from the current value and then change the width incrementally so that the change happens gradually over the period of time specified. The result is that the user will perceive the change in width as an animation."))
article.append(addParagraph("The next two commands are very similar but these set the values for height and left. Notice that in each of these three cases, the values are absolute. For example, the width is set to 300 regardless of whath the previous value was and I will come back to that in a moment. Before I do that, the fourth call to the animation function is a little bit more interesting."))
article.append(addInset(".animate({top: \"+=100\", borderWidth: 10}, \"slow\")"))
article.append(addParagraph("As before, the animate function is taking two values but the first value contains two CSS rules setting the position relative to the top of the screen and also setting the width of the border. Notice that the value specified for top is relative to the current value. It specifies the current value plus 100 so it is not moving the div to a specific position, it is moving it 100 pixels further away from the top than it was when the function was called. The second argument is also interesting in that it is a non-numeric value so rather than specify the amount of time the transformation should take, we have just said that it should be slow. The w3schools site has a good reference for the function under <a href='https://www.w3schools.com/jquery/eff_animate.asp'>jQuery animate() Method</a> and this gives you a list of the CSS styles you can use with the animate function. It doesn't specify exactly how many milliseconds slow takes so I would guess that this is browser-specific - in other words, different browsers may define different amounts of time for that."))
article.append(addParagraph("In any case, since we set two properties in one call, these transformations appear to happen at the same time so this gives us a more interesting animation effect."))
article.append(addParagraph("Bearing in mind the four animation effects - to recap these were:"))
article.append(addInsetBulletList(["Changing the width of the element to 400px over 300ms.", "Changing the height of the element to 300px over 400ms", "Changing the position from the left edge of the viewport to 200px over 500ms", "Changing both the height to 100px greater than it's current position and the border width to 10px with a speed of slow"]))
article.append(addParagraph("What do you think would happen if we press the Start Animation button again. The event handler was attached to the button - the element with id go - and the animations are part of the callback function called when the button is clicked so all four animation functions are called again. If you try it, you will see that the element moves down the page but we don't see any other changes."))
article.append(addParagraph("The reason for this is probably obvious and it comes back to the notion of absolute and relative positions. The width, height and left settings are set to an absolute value as is the border width so when we click it again, we are setting these values to the same value that the element already has. For example, we are changing the width from 300px to 300px."))
article.append(addParagraph("This raises an important point which is that in order ro fully control the animation effect, you need to be aware of where it is starting from as well as where you want to move it too."))
article.append(addParagraph("Consider this example, let's say that we want to display a div that is essentially a box on the screen and we want it centred. But rather than just have it appear fully formed, we want it to start as being not visible and then we want it to expand so that it covers a good portion of the screen and then display some text. How would we acheive this?"))
article.append(addParagraph("That's not as easy a question as I first thought it would be, but essentially, you want to position the div in the centre of the screen, giving it an intial width and height of 0px. You can then use the animate function to increase it's size and then add the text elements. Positioning the div was something I wasn't able to do (I didn't want to spend too much time on it, so this was done very quickly). In the end, I just positioned it in such a way that when it reaches the target size, it is central, but it doesn't expand from the centre outwards. I also wasn't able to add the text via jQuery although I tried several different ways to do this so I have just added this directly to the HTML."))
article.append(addParagraph("Given that this was just a quick experiment and it is the first animation with jQuery that I have produced myself, I don't think that the results are too bad and you can check them out by clicking <a href='./samples/animation2.html'>here</a>."))
article.append(addParagraph("I want to start working on an online resume soon and this, or something like it, might end up being a nice landing page for that with the user then clicking to view the actual resume. This may change after the chapter on animations, of course!"))
article.append(addHeader("Working with AJAX"))
article.append(addParagraph("Before we start, it is perhaps worth mentioning that the nature of AJAX is such that it is usually performing some task that involves getting or loading information from the internet. In the example we are going to see here, it is loading either a text file or an HTML document, depending on which option you select. Essentially, this means it is grabbing some data from the local machine. Not all browsers will allow AJAX to work like that although Firefox will so to run the AJAX examples here, your options would be"))
article.append(addInsetCodeListing(["Use a broswer like Firefox that allows AJAX to access local files.", "Use an IDE such as Brackets or VS Code that allows you to spin up a live server.", "Put the files on an actual live Web Server."]))
article.append(addParagraph("Since I am using a live web server, the third option is the best for me and to keep things as simple as possible, I have copied the sample text and HTML files to the samples directory for this course so they are in the same folder as the page they are accessed from allowing me to access them by referencing only their name. I don't need to specify a path. You can view the demo page by clicking <a href='./samples/ajax1.html' target='_blank'>here</a>."))
article.append(addParagraph("As you might expect, this is a more complex example than any we have seen previously and this is refelcted in the jQuery code shown below."))
article.append(addInsetCodeListing(["&lt;script type=\"text/javascript\"&gt;", " $(\"document\").ready(function() {", " $(\"#getcontent\").click(getContent);", " $(\"#loadhtml\").click(loadHTML);", " });", "", " function getContent() {", " $.ajax(\"sampletextcontent.txt\" { success: setContent, type: \"GET\", dataType: \"text\" });", " }", "", " function setContent(data, status, jqxhr) {", " $(\"#example\").text(data);", " }", "", " function loadHTML() {", " $(\"#example\").load(\"samplehtml.html\");", " }", "&lt;/script&gt;"]))
article.append(addParagraph("I won't show the HTML for the demo here because it is pretty much what you see in the browser - it contains a header, a paragraph, an unordered list, an empty div with an id of example and two buttons with the ids getcontent and loadhtml. All of this except the header is inside a div with an id of content."))
article.append(addParagraph("As you can see in the jQuery code, we are using the ready function on the document so this makes a call to its callback function when the DOM has been parsed. In this function, we are adding a couple of event handlers, one to each of the buttons and these event handlers call another function when clicked. Clicking the button with id loadHTML leads to the loadHTML function being executed. Clicking the button with id getContent causes the getContent function to be executed."))
article.append(addParagraph("Perhaps surprisingly, the loadHTML function is the simpler of the two. It just sets the HTML value of the example div to the samplehtml.html document so it is actually displaying that HTML document inside the div. So, we are grabing an HTML element (that's the example div) and passing a method to it (that is the load method). The load method itself takes an argument which is the URL of the HTML document we want to load into the div. Notice that this is given as"))
article.append(addInset("\"samplehtml.html\""))
article.append(addParagraph("We don't need anything else other than that because the samplehml file is in the same directory as the page from which the method is being called so I don't have to tell the server where to find it. If it were stored in a different directory, I might have to provide a more detailed relative path or an absolute path and if we were calling in some HTML document stored somewhere else on the internet, we would need a full URL."))
article.append(addParagraph("What does full URL mean? If we go into a browser and type something like osztromok.com in the URL bar, that's enough for the browser to locate and load the page but would that also work here? To find out, I have replaced the URL with osztromok.com and you can find out if that works by clicking <a href='./samples/ajax2.html' target='_blank'>here</a> with the result being shown in figure 7."))
article.append(addImageWithCaption("./images/ajax2page.png", "Figure 7 - Using the loadHTML function to try to load osztromok.com into the example div."))
article.append(addParagraph("You may not be surprised to see that didn't work! If we wanted it to work here, we would have to do use a more sophisticated functionality that converts our partial URL to a full URL, which is what a browser like Firefox does. Notice I have thr web developer tools open and I can see that a 404 error occured when I clicked on Load HTML. As you can see, the page wasn't found and the page that it was looking for has a URL of"))
article.append(addInset("http://osztromok.com/temp/jqueryessentialtraining/samples/osztromok"))
article.append(addParagraph("As with samplehtml.html, we are essentially telling the server that the page that we want is in the same folder as the page we are calling the function from so it is not being found."))
article.append(addParagraph("We'll try it again, but this time specifying the URL as http://osztromok.com with the results being shown <a href='./samples/ajax3.html' target='_blank'>here</a> in figure 8."))
article.append(addImageWithCaption("./images/ajax3page.png", "Figure 8 - Using the loadHTML function to try to load http://osztromok.com into the example div."))
article.append(addParagraph("That did work, to some extent so we can see the basic HTML file although it doesn't look anything like it would if I went to the same page in Firefox or Chrome. Again, this is because I am in effect using a very basic browser inside the Firefox browser so we are not getting any of Firefox' functionality - for instance, our CSS and JavaScript files are not being loaded so we are essenitally seeing more or less unstyled HTML. There is some styling because the example div is inside a web page that has some styling attached and that is being applied by Firefox, but we are not getting any of the styling associated with osztromok.com."))
article.append(addParagraph("Moving on to the getContent function. Here, we are using jQuery's ajax function and passingi it the text file we want to load into the example div along with an object. The obkect is a little bit of JSON containing three items, sucess, type and dataType. If the file was found, this is a success and so we call the setContent function and set type to GET (that's the HTTP method we want to use) amd dataType to text."))
article.append(addParagraph("The setContent takes three arguments, these being data, status and this weird looking argument, jqxhr. Let's look at these in turn. Data is the contents of the text file that had been returned by the ajax function. Status is a confirmation of whether or not the ajax function successfully returned the requested data. That weird looking argument is the broweser underlying native xml http request object and we need to include that if we want to work with it. I won't explain it any further here because this is just an introduction and we are going to be working with AJAX in more depth in chapter 7."))
article.append(addParagraph("The main thing to understand here is that we have a couple of relatively simple function calls to display either some text or HTML inside an element in our page so it demonstates how easy jQuery makes it to work with AJAX. One question you might ask yourself, and I think it does look a little strange, is why we used two functions to set the content to some text but only one for setting it to some HTML, which you would expect to be the more complicated task."))
article.append(addParagraph("The reason is simply that these tasks are very common when working with AJAX so jQuery is providing a function, the load function that takes away the added complexity and that's why the loadHTML function looks much simpler. As a matter of fact, we can get rif od the getContent and setContent functions and instead, use a function, we'll call it ladText, that looks exactly like the loadHTML function but specifies a text file rather than an HTML document. The loadText function would look like this."))
article.append(addInsetCodeListing(["function loadText() {", " $(\"#example\").load(\"sampletextcontent.txt\");", "}"]))
article.append(addParagraph("In reality, there is not any real difference between how this works with text files compared to html files, it just servers to demonstrate the fact that jQuery is providing this load function to make the coding a bit easier."))
article.append(addParagraph("To demonstrate this, I have rewritten the jQuery in <a href='./samples/ajax3.html' target='_blank'>ajax3.html</a> so that it also uses the load function and if you clck on the link, you will see that there is no difference in the way it works."))
main.append(menu("jQuery"))