Purdue Home Page
Overview
Tech
- Task Runner
- Gulp.js
- CSS
- new components structured with BEM and written/compiled in SCSS
- JS
- JS modules bundled with Browserify + Watchify and minified via Uglify
- Back-end
- PHP for handling scheduled components
- CMS
- UI built & data stored in Cascade Server and compiled via Apache Velocity
Responsibilities
- review design for accessibility issues
- use Git and GitHub for version control and tracking progress
- implement custom features according to WCAG 2.0
- test for browser inconsistencies
- implement all content management within Cascade Server
Development Notes
Customization Feature
Background
From the very beginning, the team wanted the Purdue home page to be a door to the University that quickly sent the user where they wanted to go. In the previous iteration of the home page, the main content consisted completely of featured links. These links were chosen by our team based on the date and/or analytics. The difficulty with choosing these links came in determining the audience we were catering to.
Often, we would decide that prospective and/or current students were the main audience and choose links accordingly; however, we would then receive complaints/requests from other organizations on campus that desired something more alumni-focused or faculty/staff-focused.
Solution
To handle the numerous audiences, we decided to give our users a way of self-identifying to filter relevant links, and allow them to determine what they want to see on the home page.
Customization in Action
Implementation
When determining how to go about implementing this feature, I had considered using a JS framework, such as React or Angular, to generate that portion of the page. In the end, I decided that it would be better to not add an entire framework that would only be used on a small portion of the page. Since the Purdue templates were already "married" to jQuery via Bootstrap, it was better to instead create JS modules, using Browserify, for the various elements:
- tiles
- customization button
- modal
- custom audience dropdown
- checkboxes
The above modules act similarly to components in React. Unfortunately, I didn't have the benefit of using React's virtual DOM, so I needed to implement some measures to improve performance.
Performance
To improve performance, I decided to have each module interact with the DOM as little as possible. Modal states, checkbox states, checkbox visibility, etc. were all stored as properties of a module. Instead of reading the DOM to determine whether a checkbox was checked or unchecked, I was able to access the property value and have the script act accordingly. All animations were implemented via CSS and activated by class toggling.
Accessibility
One of the more time consuming elements of this update was ensuring that the customization met accessibility standards.
Keyboard Support
Ensuring there were easily identifiable focus styles on each element of the page was simple with CSS. Usually, I would just add CSS properties applied on hover while also implementing an extra visual identifier such as an outline.
/* example of applied focus styles */
.tiles {
&__tile {
&--customize {
&:link,
&:visited {
background-color: #c28e0e;
color: #000;
}
&:hover,
&:active,
&:focus {
background-color: lighten(#c28e0e, 10%);
color: #000;
}
&:focus {
outline: solid 1px #c28e0e;
outline-offset: 2px;
}
}
}
}
The issue with this approach is that you may not want to apply focus styles for every focused element. For example, when a user would open a dropdown, it would apply a focus style to the toggler. We wanted this focus style to appear for keyboard navigators, but not for mouse navigators.
To only apply focus styles for keyboard users, I implemented a script that toggled a class on an element if it was interacted with via a mouse.
// jQuery used since it's already implemented for Bootstrap
this.element.bind("mousedown keypress", function (e) {
if (e.type === "mousedown") {
// the container was interacted with a mouse
this.element.classList.add("tiles__tile--mouse");
} else if (e.type === "keypress") {
// the container was interacted with a keyboard
this.element.classList.remove("tiles__tile--mouse");
}
});
Now that we have identified when an element has been interacted with via a mouse, we can implement CSS to prevent focus styles from displaying.
.tiles {
&__tile {
&--customize {
&:link,
&:visited {
background-color: #c28e0e;
color: #000;
}
&:hover,
&:active,
&:focus {
background-color: lighten(#c28e0e, 10%);
color: #000;
}
&:focus {
outline: solid 1px #c28e0e;
outline-offset: 2px;
}
}
&--mouse {
&:focus {
outline: none;
}
}
}
}
Other keyboard support features included implementing the recommended keyboard controls for custom elements listed in WAI-ARIA Best Authoring Practices. More information about using those best practices can be found in the next section.
Screen Reader Support
While the tiles being customized are easily interacted with as links, the customization modal was an entirely different story. Modals aren't pre-baked into browsers, so it was important to build a way to communicate with screen-reader-users about how to interact with the customization component. On top of that, the design called for creating custom elements that mimicked elements pre-built into the browser.
Luckily, there is already a way to communicate this through Accessible Rich Internet Applications (ARIA). By following WAI-ARIA Best Authoring Practices, I was able to setup these custom elements in a way that users would expect. The following patterns were most useful:
- Dialog (Modal) — used when setting up the modal
- Checkbox — used when creating the custom checkbox elements
- Listbox — used when creating the custom dropdown element