PSU 2012 JavaScript: Intermediate

PSU 2012
JavaScript: Intermediate
JavaScript: Intermediate
The purpose of customizing PowerSchool with JavaScript is to make it easier for people in your district
to use PowerSchool in a way that matches the unique circumstances they face. The activities in this
class focus on the JavaScript you need to know most so you can make similar changes later at your
school, even if you find you don't need the exact results of these activities.
In this course you will:
•
Learn how to traverse and manipulate the DOM by creating a tabbed enrollment page with
indicators for when a section is completed
•
Master event delegation by creating a method for reverting a field value back to its original
value
•
Use AJAX to automate the entry of the next student number
Traversing and Manipulating the DOM
Like a family tree stretching back many generations, the DOM, or Document Object Model, with its
many parent and child nodes, can get complicated. The jQuery library has multiple JavaScript
functions you can use to pinpoint specific elements in the DOM (traversing) and make changes to
them (manipulating). Exploring these functions will help you tackle complicated customization projects
in PowerSchool.
It can be difficult to remember which of all the functions available in jQuery are for manipulating and
traversing the DOM. Fortunately, with the jQuery APIs at http://www.jquery.com, you won't have to
memorize them. However, it can be useful to familiarize yourself with a number of functions used
frequently.
The table below lists common jQuery methods for traversing and manipulating the DOM.
Method
Explanation
.children()
Traversing method. Get the children of each element in the set of
matched elements, optionally filtered by a selector. For example,
$j('.box-round').children('table') would select the table
elements of PowerSchool's main content area, but not select table
elements elsewhere.
.parents()
Traversing method. Get the ancestors of each element in the
current set of matched elements, optionally filtered by a selector.
For example, $j('.psDateWidget').parents('.evenRow,
.oddRow') would select the table row elements that have a
PowerSchool date widget as a child.
.next()
Traversing method. Get the immediately following sibling of each
element in the set of matched elements. For example,
$j('h1').next() would select the paragraph with student header
information.
.prev()
Traversing method. Get the immediately preceding sibling of each
element in the set of matched elements, optionally filtered by a
selector.
JavaScript: Intermediate
Method
Explanation
.html()
Manipulation method. Get the HTML contents of the first element in
the set of matched elements. For example, $j('#contentmain').html() would return all of the HTML content in the
content-main div. If you provide an argument, it sets the content.
For example, $j('#content-main').html('<div>Content
hidden</div>') would erase the existing main content area and
display the text "Content hidden."
.val()
Manipulation method. Get the current value of the first element in
the set of matched elements. For example,
$j('#lastName').val() would return the current value of the last
name field. If you provide an argument, it sets the value for the
element. For example, $j('#lastName').val('Hanson') would
replace the existing value in the field with "Hanson."
.attr()
Manipulation method. Get the value of an attribute for the first
element in the set of matched elements. For example,
$j('#lastName').attr('maxlength') would return the value for
the maxlength attribute for the last_name field. You could change
the value by adding another argument:
$j('#lastName').attr('maxlength', '60')
.append()
Manipulation method. Insert content, specified by the parameter,
to the end of each element in the set of matched elements. For
example, $j('#content-main tr').append('<td>New
col</td>') would create a new table data element, or new
column, in every table.
.after()
Manipulation method. Insert content, specified by the parameter,
after each element in the set of matched elements. For example,
$j('#lastName').after('<span>Req</span>') would place "Req"
after the last name field.
.before()
Manipulation method. Insert content, specified by the parameter,
before each element in the set of matched elements. For example,
$j('#lastName').before('<span>*</span>') would place an
asterisk before the last name field.
Copyright © 2012 Pearson
Page 2
JavaScript: Intermediate
Activity 1 – Traverse and Manipulate the DOM in PowerSchool
For your first project, the district has created a tabbed enrollment page with certain required fields.
Starting with PowerSchool 7.1, required fields are indicated using the class “required.” However, your
district wants to provide an additional indicator for the enrollment office to see when all the required
fields of a tab are filled. Your goal is to evaluate each tab's fields and update the tab if all the required
fields in the content area have a value.
This activity will help you become more familiar with existing methods for traversing and manipulating
the DOM. Using Firebug or your browser's developer tools, enter jQuery code in the console to
manipulate the following elements on the home page and the standard General Demographics page
for a student.
For example, given the instructions to remove all content in the usercontext-bar div, you might enter
$j('#usercontext-bar').empty();
Usually you can accomplish each task more than one way; remember that you can chain methods
when traversing to select the right elements.
For example, $j('.box-round').children('table').next() would select the button row which is a
sibling to the table element.
Instructions: On the lines below, write the jQuery command that would cause the result described in
each item.
1.
General Demographics page: Remove the text General Demographics from the page
Answer: _________________________________________________________
2.
General Demographics page: Change the value of the ethnicity field
Answer: _________________________________________________________
3.
Home page: Add another list item after the Reports header
Answer: _________________________________________________________
4.
Home page: Add a link to the Other Options section of the home page
Answer: _________________________________________________________
Copyright © 2012 Pearson
Page 3
JavaScript: Intermediate
Activity 2 – Identify Elements in a DOM
Before you tackle activity 3, examine the DOM you will navigate during that activity to help
understand what elements are important. Below is a sample DOM as rendered by the browser.
Why would you examine a rendered page rather than the source? The browser-rendered page is the
same page that will be running your JavaScript, so viewing the page on the server is not a complete
representation of the DOM.
<div class="tabs ui-tabs ui-widget ui-widget-content ui-corner-all">
<ul class="group ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header uicorner-all">
<li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active"><a
href="#main">Main</a></li>
<li class="ui-state-default ui-corner-top"><a href="#addresses">Addresses</a></li>
...
</ul>
<div id="main" class="ui-tabs-panel ui-widget-content ui-corner-bottom">
<table border="0" cellspacing="0" cellpadding="4" class="linkDescList">
<colgroup><col style="width:20%"><col></colgroup>
<tbody><tr class="oddRow alt">
<td class="bold">Name (last, first MI)</td>
<td>
<input type="text" name="UF-001005139" value="Fisher" size="17"
maxlength="20" id="lastName" class="required" data-validation="{"maxlength":"20",
"required":"true", "type":"text"}"><em>*</em>,
...
</div>
1.
Circle or highlight the element for the Main tab and the associated div element below it
Now think through what will happen in the DOM. When you change a field, like the last name field,
in order to update the tab correctly, you must identify the section or div to which the field belongs.
2.
Looking at what you have marked, do you see any "hooks" that will help you to select the
element?
3.
Now examine the element that creates the tab. What commonality can you use to select the
correct tab element?
With these questions in mind, proceed to the next activity.
Copyright © 2012 Pearson
Page 4
JavaScript: Intermediate
Activity 3 – Fill in the JavaScript Traversing Functions
Even the most experienced coders try to minimize the amount of code they need to enter by hand.
But they still understand what the code is doing. In this activity, you will enter in functions for
traversing to set the values of the variables you’ll need to use when evaluating each tab.
1.
Use your favorite browser to open the index.html file in the fill_in_blank folder of the activity
files
2.
Follow the directions to complete the activity and enter in the functions to set the values of
the variables needed to the correct elements
Refer to the HTML code above, if needed.
3.
When all the answers are filled in correctly, copy the code from the revealed textarea
4.
Paste the code between the script tags in the tabdemo.html file in your activity files folder
5.
In the user folder provided by the instructor, create a file called tabdemo.html using Custom
Page Management
6.
Copy the contents of the tabdemo.html file from your activity files, and paste it into your new
tabdemo.html page in Custom Page Management and click Publish
7.
In PowerSchool, navigate to an individual student page, such as Demographics, making sure
to remove the page from the frame
8.
In the URL, replace the path of the current page with the path of yours, making sure to
maintain the student frn data at the end
For example, if the current URL reads
/admin/students/generaldemographics.html?frn=0014728
and your assigned folder number is 13, you would modify the path to be
/admin/13/tabdemo.html?frn=0014728
Activity 4 – Count the Required Fields
Now that you have the elements selected, it is time to count all the required fields that have values
filled in to see if it matches up with the total number of required fields.
1.
In your tabdemo.html file, on the line reading allReqsLength = allReqs.length; change the
semicolon to a comma so it reads allReqsLength = allReqs.length,
2.
Add another variable named a and set it to 0; complete the string of variable names by
inserting a semicolon at the end
3.
Use the jQuery each method to run a function for each element assigned to the allReqs
variable
4.
Evaluate each element using $j(this)
If the element has a value, increment a by 1
5.
Publish your file to save your changes
Copyright © 2012 Pearson
Page 5
JavaScript: Intermediate
Activity 5 – Manipulate with Class
With the code in place to count the number of filled required fields, write the JavaScript to determine
whether the number is equal to the total number of fields in the content area for the tab.
1.
Replacing the comment, //Modify classes, insert an if-else statement
2.
Between the parentheses of the if statement, evaluate if a is equal to the total required fields
3.
If the statement is true, add a class of psc-filled to the tab and remove the psc-unfilled
class
4.
If the statement is false, add a class of psc-unfilled and remove the psc-filled class from
the tab
5.
Publish and test your page
6.
Notice how the page doesn't show incomplete fields accurately in tabs initially?
How could you get the evalTabs function to run when the page loads?
Answer: _________________________________________________________
7.
Add in a line to run the evalTabs function for a field in each tab
8.
Publish and test your page
Using Event Delegation
Now that you can traverse and manipulate the DOM, the browser window is a very dynamic place. The
increased interaction is good, but when you are working with many elements at once, it can become
difficult to manage.
For example, what if you wanted to add a large number of buttons to a page and each of those
buttons performed some action when clicked?
You would need to place event listeners on every single one of the buttons.
Some browsers can handle a large number of listeners, but others may have difficulty
processing so many.
And then, what if you had to remove a button when it was clicked, but cause other buttons to appear
as the user interacts with the page?
Adding and removing listeners on those dynamic elements could become unmanageable.
Sound like a disaster waiting to happen? It can be, but in this next project, you'll tackle this very
problem. Perhaps you’ll be able to apply it to similar customization projects.
This next project involves another enhancement on the demographics page. Because the page is very
long, sometimes users change a value by mistake. If many other fields have been modified already, to
avoid submitting the incorrect data, users would need to refresh the page and start over unless they
remembered the old value.
In the case of a phone number, it is unlikely that an existing value will be remembered, so to help
people who work with the page, you are going to implement a "revert" function on every field so that
when any value is modified, the original value is kept and a button is added next to the field. When
clicked, the button will replace the value of the field with its original value.
Copyright © 2012 Pearson
Page 6
JavaScript: Intermediate
Imagine having many buttons like you see in the image above. These buttons would appear and
disappear as the user interacts with the page. Each time one is created, you would need to place a
listener like this: $j('.psc-revert').click(clickHandler); on the click interaction.
Rather than trying to manage the constant changing of buttons on the page, you can use event
delegation to set a listener once that will work for all buttons, no matter how many buttons you add.
The pattern for delegating events in jQuery is: $j('parent-with-listener').delegate('childelement-who-triggers-event','event',handlerFunction)
You select the parent element to which you will assign the listener. Then, using the delegate function,
provide three arguments:
•
First is the child element that should trigger the event
•
The second is the type of event, such as a change, click, or mouseover
The reality is, if you delegate a click event, any click on the parent element will trigger an
action. However, the handler function will not run unless the delegated child element is the
target of the action.
•
Third is the function to run when the event occurs, otherwise known as the handler
Important Note: Starting with jQuery 1.7, a new method has superseded the delegate function.
However, the new method, .on(), has a very similar syntax that you can use once you understand
the delegate function. As PowerSchool is still using jQuery 1.4.2, the .on() function is not available to
use yet. But if you use the jQuery API, it will be important to note this difference.
Activity 6 – Understand Event Delegation
View a simple example of event delegation to help you understand how it will be applied in the
project.
1.
Use a text editor to open the index.html page in the event_delegation_example folder
2.
Replace the comment //Event listeners with a listener on the “Add a List Item” button so it
will run the addListItem function when clicked
3.
Save the page, and test it in your browser by creating several list items
4.
Now add a listener on all li elements so the removeListItem function will run when one is
clicked
5.
Save the page and test it in your browser by creating several list items and then clicking them
to delete them
6.
Why aren’t the list items deleted?
Answer: _________________________________________________________
7.
Remove the listener on the list items, and write the code to use event delegation on the
parent container for the list items, the ul element
Copyright © 2012 Pearson
Page 7
JavaScript: Intermediate
Activity 7 – Delegate Events
Use what you have learned about event delegation to trigger events when any input field or select
menu is changed, and when any revert button is clicked. Some of the JavaScript is entered in already
to create the buttons and cache the original values of the fields.
1.
Directly after the JavaScript entered previously, using #content-main as the parent element,
write the code to trigger the addRevert function when a select menu or an input that is not
hidden is changed
2.
Again while using #content-main as the parent element, write the code to trigger a function
when an element with the psc-revert class is clicked
3.
In the function, create two variables named rev and curEl and assign them the values of
$j(this) and the previous sibling of rev
4.
Set the value of curEl to the value of the data-orig-val attribute of the same element
5.
Remove rev from the DOM
6.
Publish and test your page by changing a few values and clicking the revert button that
appears
Activity 8 – Troubleshoot
After testing the revert buttons, you may have noticed a couple of problems. First, if you change the
field two times in a row, two buttons appear. Second, if you change the value of the field manually to
the original value, you still get another button. In this activity, you will sort lines of code and
comments to construct a new addRevert function.
1.
Examine the JavaScript program you have written so far
Why does a second button get added when you change the same field twice?
Answer: _________________________________________________________
2.
What conditions should be true in order for a button to be added?
Answer: _________________________________________________________
3.
In your favorite browser, open the index.html page of the code_soup folder in the activity files
4.
Drag the lines of JavaScript and place them in the correct order
5.
After you have sorted all the lines correctly, copy the code that appears in the textarea below
the sorting activity
7.
Paste the code in your revertdemo.html page, replacing the existing addRevert function
6.
Publish and test your page
Applying AJAX
Most customization efforts begin with a problem. For example, some districts have very specific
patterns for their student numbers. They might have student numbers that begin with the initial grade
level or the expected year of graduation when a student enters the district followed by a four or five
digit number that increments for each new student enrolled. If you use the expected year of
graduation as the first four digits, the PowerSchool feature to automatically assign the student number
sequentially is not an option. While a district could assign a number manually, keeping track of which
number is next in the sequence is a time-consuming task.
Copyright © 2012 Pearson
Page 8
JavaScript: Intermediate
Assume this is your district and you want to create a button that will fill in the student number with
the next in the sequence for any new student being enrolled. In the past you have used a page that
tells you what that number is, but your schools have to type the URL each time:
/admin/students/nextsn.html?gradyear=2015.
Changing the gradyear value would return the next number in the sequence for students with the
same graduation year. You think, "If only I had a way to get the next student number result into the
Student number field of the Enroll New Student page." Of course, there is a way! It's called AJAX.
AJAX was originally an acronym for “Asynchronous JavaScript and XML.” The term has become used
much more broadly to refer to any request that is made to the server after the page is first loaded in
the browser (not just XML), or a request that is made separately from the main content of the page.
The purpose of using AJAX is to avoid having an entire page refresh when all you need to do is update
a portion of the page.
In your situation, for example, all you want to do is insert the next student number into the field.
AJAX makes that possible by avoiding the need to navigate elsewhere.
Activity 9 – AJAXify Your Page
Write the JavaScript code required to make a request to the nextsn.html page, passing the gradyear
data along with it. Write the code to handle the returned data if the request is successful.
1.
Create a new file in your folder of the Custom Page Management tool named newstudent.html
2.
Open the newstudent.html page in the activities folder, copy the source, and paste into your
newly created newstudent.html file in the Custom Page Management tool
3.
Replacing the comment //insert AJAX code here, write the jQuery function for making an
asynchronous request with an empty object as the argument
4.
In the request object, create three keys: url, data, and success
5.
Initialize the url and data keys to empty strings and the success object to a function with an
argument of data
6.
As the URL value, enter this URL between the quotes: /admin/students/nextsn.html
7.
As the data value, enter gradyear= between the quotes and concatenate the gradyear
variable to the string
8.
In the success function, change the value of the student number field to the data variable of
the function
9.
Publish the page and test the button
Summary
Now you are prepared to use JavaScript to traverse and manipulate the DOM in response to user
interaction on a PowerSchool page. In addition, you have learned the principles of event delegation so
you can set up event listeners and handlers appropriately for a frequently-changing page. And finally,
with AJAX, you can update portions of a page quickly, helping PowerSchool users in your district save
time by not having to wait for page refreshes.
Copyright © 2012 Pearson
Page 9