Table of Contents generated with DocToc
- HX-JS: HarvardX Standard Javascript and CSS
- Currently Working On...
- How to Implement HXJS in your course
- Simple Appearance Changes
- Pretty boxes
- Sidebar Tables
- Visibility Toggle
- Highlighter Toggle
- Code Syntax Highlighting
- Pop-ups for clickable images
- Automated Footnotes
- Image Slider
- Text Sliders
- Video Links
- Easter Egg
- Jump To Time
- Pop-up Assessments
- Automated Table of Contents for Long Pages
- Forum Tricks
- Backpack
- Editor
- Future Features
- Full List of Preferences and Settings
This project collects a large number of javascript and css tricks that have been used in various HX courses and puts them all in one place so that they're easier to implement.
Nothing in specific.
- Various functionality additions.
- Getting this to work globally throughout a course without needing to load it on each page.
First, download HXHelper Files.zip unzip it, and upload all of the things therein to your Files & Uploads section. This will let you use...
- Video Links,
- Pop-Up Problems,
- Slick-style image sliders,
- intro.js text-based walkthroughs with some accessibility improvements,
Also upload the three files from this repo:
- hx.js, which puts all the javascript in one place
- hx.css, which is all the css in one file
- hxGlobalOptions.js, which sets the global options for hx.js
Once you've done that, copy the lines below into a Raw HTML element:
<script src="/static/hx.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="/static/hx.css" />
Or, if you're using the minified versions from hx-min.zip:
<script src="/static/hx-min.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="/static/hx-min.css" />
That will enable hx.js for all components on that page. It should be doing exactly nothing so far. You can test whether it's working by entering the Konami Code.
To make other things happen, you'll need to add specific classes to your HTML, and in some cases make little changes to your hxGlobalOptions.js file. Here's the full list of awesome stuff:
All of these are classes that you add to various elements.
- For drop caps that are text rather than an image, do
<span class="hx-dropcap">A</span>
on the first letter. - For small-caps headers, do
class="hx-smallcaps"
. Works with h3 or h4. - For a superbold white header with a solid color background, do
class="hx-superbold"
. You can do small caps with this. - For an underlined header, do
class="hx-underline"
. You can do small caps with this. - For images or divs that hang down on the right-hand side, use
class="hx-hangright"
. - For images or divs that hang down on the left-hand side, including image-based drop-caps, use
class="hx-hangleft"
. - To get rid of the top navigation "ribbon" and bottom left/right buttons, add
hxLocalOptions.collapsedNav = true;
to a script tag on your page. Warning: By doing this you are intentionally removing students' ability to get to other units in this subsection. Only do this in subsections that have just a single unit. - To add a UTC clock on the right-hand side of the "pages" section, add
hxLocalOptions.showClock = true;
to a script tag on your page. - Image maps are automatically rescaled to fit images if edX's responsive design changes the size of the image. To turn this off, set
hxLocalOptions.resizeMaps = false
in a script tag on your page.
Blue boxes:
<div class="hx-bluebox">
<h4>Box Header</h4>
<p>Other things in box</p>
</div>
Red boxes:
<div class="hx-redbox">
<h4>Box Header</h4>
<p>Other things in box</p>
</div>
Grey (or gray) boxes:
<div class="hx-greybox">
<h4>Box Header</h4>
<p>Other things in box</p>
</div>
Also available: orangebox, greenbox, magentabox, purplebox, bluebox2.
Sidebars (must combine with box style):
<div class="hx-sidebar">
<h4>Box Header</h4>
<p>Other things in box</p>
</div>
Quotation/excerpt boxes (should combine with greybox):
<div class="hx-excerpt">
<h4 class="hx-smallcaps">Quotation Header</h4>
<p>Actual honest-to-god quotation</p>
<p class="hx-quote-source">Abraham Lincoln</p>
</div>
Just give your table tag class="hx-hangleft"
or class="hx-hangright"
and it'll be ready to go. Note that you shouldn't do more than two columns, or three if your headers and data are very compact.
If you need a really compact table, add hx-compact-table
to the class.
In hxGlobalOptions, set markExternalLinks: true,
in order to add FontAwesome external link markers to all links outside of edX. Note that links to other courses within edX will NOT currently get the markers.
This part makes the button:
<p><button class="hx-togglebutton1">Toggle the sidebar on or off</button></p>
Then you match the number on -togglebutton# to your toggle target:
<div class="hx-toggletarget1 hx-sidebar">
<p>I am all the stuff you want to toggle on and off.</p>
</div>
Button 1 toggles target 1, button 2 toggles target 2, etc. If you toggle something that's offscreen (and if there's only a single target) then the target will scroll quickly into view.
If you want to have multiple buttons where clicking one disables the others, use a toggleset in their container:
<p class="hx-toggleset">
<button class="hx-togglebutton1">These buttons</button>
<button class="hx-togglebutton2">Are exclusive</button>
<button class="hx-togglebutton3">Of one another</button>
</p>
If you want the buttons to remember (via HTML5 local storage) whether they're hidden or shown, add the hx-toggleremember
class.
<p>
<button class="hx-togglebutton1 hx-toggleremember">
Toggle the sidebar on or off and keep it that way
</button>
</p>
If you want to clear the memory, use the hx-clearmemory
class. Without a number it clears everything; with a number it just clears that particular entry in the memory.
<p>
<button class="hx-clearmemory7">Forget my selection for toggle 7.</button>
</p>
This part makes the button:
<p><button class="hx-highlighter1">Highlight Important Things</button></p>
Match the number on -highlighter# with the class in the following code:
<span class="hx-highlight1">Thing To Highlight</span>
Each button highlights all the things with matching numbers. You don't need a different number for each highlight; you need a different number for each set of highlights.
If you have a <code>
element on the page, hx-js will find it and load Prism for syntax highlighting, using the Coy theme. The currently included languages are:
- Python
- MATLAB
- r
- LaTeX
- HTML/XML
- JavaScript
- CSS
To have these show up, put your code blocks in the following format:
<pre><code class="lang-xxxx"> Code Goes Here
More Lines of Code
End of Code
</code></pre>
...and replace lang-xxxx with lang-matlab, lang-r, lang-latex, or whatever you need for your course.
More can be added, but each one increases the download size, so be judicious about adding them.
You will need an image map already prepared. I recommend https://www.image-maps.com/ to create one quickly.
Here's an example:
<p class="hx-centered">
<img
src="https://placebear.com/500/300"
alt="placeholder bear"
usemap="#TheBearMap"
/>
</p>
<map id="BearMap1" name="TheBearMap">
<area
id="Area1"
class="Bear1 hx-popup-opener"
title="Bear 1"
shape="rect"
coords="150,0,320,120"
alt="Bear number one"
/>
<area
id="Area2"
class="Bear2 hx-popup-opener"
title="Bear 2"
shape="rect"
coords="90,120,350,300"
alt="Bear number two"
/>
</map>
Note the classes, Bear1 and Bear2. You can name them anything you want, but they need to be the first class. The hx-popup-opener
class is also necessary, but don't put it first. The javscript will then look for divs with matching classes. They need to be divs. Here's an example:
<div class="Bear1 hx-popup-content">
<p>I am bear #1!</p>
</div>
<div class="Bear2 hx-popup-content">
<p>I am bear #2!</p>
</div>
You can put them anywhere; they'll hide until you need them. When you click on the areas, the divs pop up.
Underneath, the javascript will automatically create a list with all of the targets, based on their "title" attribute. This list will also pop up the dialogs. If you would like to NOT have this (because you're going to write that list by hand), then you should include the following attribute on the map: data-make-accessible-list="false"
.
First, make a Raw HTML component at the bottom of your page with this in it:
<h3>Footnotes</h3>
To insert the link to the footnote, use this format:
<span class="hx-footnote1">[1]</span>
Replace the number 1 with the appropriate number. They don't need to be in order, or even to be numbers, strictly speaking. Then, farther down, insert a div like this one:
<div class="hx-footnote-target1">
<p>1. I am footnote number one.</p>
</div>
Make sure that the -target# at the end matches your -footnote# above.
You can put these divs anywhere; the javascript will move them to the end of the footnote component.
For an image slider, copy the HTML below and alter to fit your purposes. Keep the classes.
<div class="hx-sliderbox">
<div class="hx-slider">
<p>
<img
src="https://placebear.com/300/300"
alt="placeholder bear"
/>Placeholder Bear
</p>
<p>
<img
src="https://placebear.com/250/250"
alt="placeholder bear"
/>Placeholder Bear
</p>
<p>
<img
src="https://placebear.com/180/180"
alt="placeholder bear"
/>Placeholder Bear
</p>
<p>
<img
src="https://placebear.com/150/150"
alt="placeholder bear"
/>Placeholder Bear
</p>
<p>
<img
src="https://placebear.com/240/240"
alt="placeholder bear"
/>Placeholder Bear
</p>
<p>
<img
src="https://placebear.com/240/240"
alt="placeholder bear"
/>Placeholder Bear
</p>
<p>
<img
src="https://placebear.com/240/240"
alt="placeholder bear"
/>Placeholder Bear
</p>
<p>
<img
src="https://placebear.com/240/240"
alt="placeholder bear"
/>Placeholder Bear
</p>
<p>
<img
src="https://placebear.com/100/100"
alt="placeholder bear"
/>Placeholder Bear
</p>
<p>
<img
src="https://placebear.com/200/200"
alt="placeholder bear"
/>Placeholder Bear
</p>
<p>
<img
src="https://placebear.com/200/200"
alt="placeholder bear"
/>Placeholder Bear
</p>
</div>
</div>
For a paired slider, where the top one acts as the navigation for the bottom one, copy the HTML below and alter to fit. Keep the classes.
<div class="hx-sliderbox">
<div class="hx-navslider">
<p><img src="/static/img1.png" alt="" height="120px" /></p>
<p><img src="/static/img2.png" alt="" height="120px" /></p>
<p><img src="/static/img3.png" alt="" height="120px" /></p>
<p><img src="/static/img4.png" alt="" height="120px" /></p>
<p><img src="/static/img5.png" alt="" height="120px" /></p>
<p><img src="/static/img6.png" alt="" height="120px" /></p>
<p><img src="/static/img7.png" alt="" height="120px" /></p>
<p><img src="/static/img8.png" alt="" height="120px" /></p>
</div>
<div class="hx-bigslider">
<p>
<a href="/static/img1.png" target="_blank"
><img src="/static/img1.png" alt=""/></a
>Comments on image 1
</p>
<p>
<a href="/static/img2.png" target="_blank"
><img src="/static/img2.png" alt=""/></a
>Comments on image 2
</p>
<p>
<a href="/static/img3.png" target="_blank"
><img src="/static/img3.png" alt=""/></a
>Comments on image 3
</p>
<p>
<a href="/static/img4.png" target="_blank"
><img src="/static/img4.png" alt=""/></a
>Comments on image 4
</p>
<p>
<a href="/static/img5.png" target="_blank"
><img src="/static/img5.png" alt=""/></a
>Comments on image 5
</p>
<p>
<a href="/static/img6.png" target="_blank"
><img src="/static/img6.png" alt=""/></a
>Comments on image 6
</p>
<p>
<a href="/static/img7.png" target="_blank"
><img src="/static/img7.png" alt=""/></a
>Comments on image 7
</p>
<p>
<a href="/static/img8.png" target="_blank"
><img src="/static/img8.png" alt=""/></a
>Comments on image 8
</p>
</div>
</div>
You can put text into the image slider above. However, we've also made a dynamic text slider, that pulls its slides from a CSV file and loads them only when needed. This is great for larger collections of data that students might want to examine and explore in detail. This takes a little more custom work.
See the text slider folder for more detail.
This one is a little complex. Look at the structure below, which you can copy to use as a template. Paste it into a Raw HTML component directly beneath your video.
<div id="hx-vidlinks-static-1" class="hx-vidlinks">
<div data-time="9">
<a href="http://astronomy.fas.harvard.edu/people/dimitar-sasselov">
<img src="/static/hx_tiny_white.png" />
Dimitar Sasselov - Harvard University
</a>
</div>
<div data-time="17">
<a href="https://en.wikipedia.org/wiki/Solar_System">
<img src="/static/hx_tiny_white.png" />
Our Solar System - Wikipedia
</a>
</div>
<div data-time="27">
<a href="http://planetquest.jpl.nasa.gov/">
<img src="/static/hx_tiny_white.png" />
Exoplanets - NASA.gov
</a>
</div>
</div>
The outer div has hx-vidlinks-static-1
, because it's for video number one - the first one on the page. If I have a second video, it should say hx-vidlinks-static-2
and so forth.
The inner divs have data-time="9"
where the 9 means the link is going to show up nine seconds into the video. You can also specify times in minutes:seconds format, or even hours:minutes:seconds.
The image inside is a little HX. It's 25 pixels tall. Feel free to replace it with a different image that's also 25 pixels tall.
The javascript will turn this set of divs into a list of static links, for folks who can't see or get to the pop-up links.
If you don't want to load this on a page, for instance on a page with a lot of videos that don't need links, you must set hxLocalOptions.dontLoadVideoStuff
to true
. You can't do this as a global option, because the global options are loaded along with the other scripts. It has to be done within the page.
Up up down down left right left right B A
Write a link that looks like this:
<a href="#video1" class="hx-vidtime" data-time="0:34">Go to 34 seconds</a>
The pound sign at the beginning of the href is a pound sign. The number at the end of the href tells us which video you want on the page (the top one is #1). The time can be given in hh:mm:ss format, or mm:ss, or just in seconds.
The link will jump you to the appropriate video, cue it up to the right time, and start it playing.
This will even work with /jump_to_id/
links! Just add the #video1
or #video2
or whatever at the end of URL.
If you want to go to a particular time in a video on the same page, that's simpler. Write this instead:
<a href="3:24" class="jumptime">Go to 3:24</a>
It'll affect the top video on the page. Optionally, you can add a data-for-vidnum="N"
attribute to go to the Nth video on the page (the top one is video number 1).
This is a little complicated. First, make a Raw HTML component right above or below your video.
Then, make a <script>
tag in that component and put a "timer" objet into it like so:
<script>
var HXPUPTimer = [
{ time: '8.5', title: 'What Happened?' },
{ time: '4', title: 'What Game?' },
{ time: '12', title: 'What Was That?' },
{ time: '16', title: 'Collision' },
{ time: '18', title: 'Poll' }
];
</script>
The time can be in seconds, or in mm:ss, or hh:mm:ss format. The title is the exact name of one of the problems farther down on your page. It should work with any problem type except for Peer-Evaluated.
Then, add this block of HTML for your controls. You shouldn't need to change anything here.
<button id="hx-popUpPlayPause" aria-label="Start">
<span id="hx-playpauseicon" class="hx-VQControls">‣</span>
<span id="hx-playpauseword">Play</span>
</button>
<button id="hx-popUpReset" aria-label="Answer Video Problems From Beginning">
<span class="hx-VQControls">↩</span> Restart
</button>
<button id="hx-backOneProblem" aria-label="Go Back One Question">
<span class="hx-VQControls">⇤</span> Back One
</button>
<button id="hx-problemToggle" aria-label="Toggle Video Problems On/Off">
<span id="hx-sunmoon" class="hx-VQControls">☼</span>
<span id="hx-onoff">Problems are On</span>
</button>
HX-js will do the rest!
To include items that do not have an h3 heading, such as a Word Cloud, make a small raw HTML component that includes the tag <span style="display:none" class="hx-includer">includenext</span>
, and place that component directly before the one that you want to include. HX-js will display both items at once.
If you don't want to load this on a page, for instance on a page with a lot of videos that don't need pop-up videos, you must set hxLocalOptions.dontLoadVideoStuff
to true
. You can't do this as a global option, because the global options are loaded along with the other scripts. It has to be done within the page.
Either set makeTOC: true,
in your hxGlobalOptions.js file, or put this little bit into a Raw HTML component on the page.
Warning: Once students see an Auto-TOC on one page, they'll see it on the rest of the pages in that subsection. You will probably want to set this to "true" or "false" manually on each page in a particular subsection.
<script>
var hxLocalOptions = { makeTOC: true };
</script>
This will auto-generate a hyperlinked table of contents from all visible h3 and h4 elements on your page, and drop it in the top-right-hand corner of the page.
Don't use this on pages where a video is the first thing. It will overlap and look ugly.
Either set markExternalLinks: true,
in your hxGlobalOptions.js file, or put this little bit into a Raw HTML component on the page.
<script>
var hxLocalOptions = { markExternalLinks: false };
</script>
Every link that is not to an edx.org site will be marked with a box-and-arrow image to let students know that it's an external link. It's even accessible for screen readers! Naturally, this only works on pages where you have HX-JS enabled, so you may need to manually need to add it in a few places where javascript doesn't work (like the wiki).
Maybe you want in-page discussions, but you want them open right away so everyone can see all the different threads. Set openPageDiscussion: true,
in your hxGlobalOptions.js file to automatically open every inline discussion as soon as someone comes to a page.
First, follow the setup instructions for the Learner Backpack javascript problem.
When HX-JS is running you will be able to use the javscript functions:
hxSetData('whatever', stuff)
will store thestuff
object in thewhatever
variable.hxGetData('whatever')
will get the contents of thewhatever
variable.hxGetAllData()
will get all stored variables and their contents as a single object.hxClearData('whatever')
will empty thewhatever
variable.hxClearAllData('whatever')
will empty the entire backpack.
This data is stored in the edX server, up to about 100k per student per course.
Once you have the Backpack (see above) set up, you can create a rich-text editor for your learners to use!
In a Raw HTML component, insert this code:
<div class="hx-editor" data-saveslot="journaling"></div>
HX-JS will automatically find it and turn it into an editor, via Summernote.
The data-saveslot
attribute lets you select a different slot for each editor, or reuse them within the course. If you have two editors with the same save slot, learners will see the same thing in each one. What they typed before is stored in the backpack and retrieved when they load a page.
Instructors can provide pre-filled text by just putting some HTML inside that div. If you want it taller, just add a bunch of <p> </p>
in there. You can also set it to pull from a previous editor, like so:
<div class="hx-editor" data-saveslot="Second_Draft" data-from-slot="First_Draft"></div>
Learners can save, load, rename, and delete multiple "files", and can download an HTML version. The editor auto-saves every 60 seconds. If they're running long, they get a message that they're running out of characters (but it won't actually stop them from saving) (but it will just throw out changes to their data when it gets too big).
The accessibility for this is pretty damn good, really.
(coming - but difficult.)
(coming - Luis is working on this.)
The object below is the full set of default settings for hx-js. You can override these either by putting them into the hxGlobalOptions.js file (higher priority), or by putting this hxLocalOptions object into a raw HTML element on your page (highest priority).
<script>
var hxLocalOptions = {
// Table of Contents
makeTOC: false,
// Remove a lot of the navigation "chrome" - use only if you have just one page per unit.
// This should only be used for older versions of OpenEdX before the 2017 navigation overhaul.
collapsedNav: false,
// Remove the "Add a Post" button and/or auto-open the on-page discussions.
removeAddPostButton: false,
openPageDiscussion: false,
// Resize image maps when an image shrinks because of screen size
resizeMaps: true,
// Marks all external links with an icon.
markExternalLinks: false,
// Highlighter: Yellow highlights that start turned off and go back to transparent afterward.
highlightColor: '#ff0',
highlightBackground: 'rgba(0,0,0,0)',
highlightState: true,
// Code syntax highlighting
highlightCode: true,
// Default options for the Slick image slider
slickOptions: {
arrows: true,
dots: true,
focusOnChange: true,
infinite: true,
slidesToShow: 3,
slidesToScroll: 3
},
// Default options for image slider navigation
slickNavOptions: {
asNavFor: '.hx-bigslider',
variableWidth: true,
focusOnSelect: true,
slidesToShow: 3,
slidesToScroll: 1
},
// Default options for single big image slider paired to nav.
slickBigOptions: {
asNavFor: '.hx-navslider',
arrows: false,
dots: true,
fade: true,
focusOnChange: true,
adaptiveHeight: true,
slidesToShow: 1,
slidesToScroll: 1
},
// Default options for pop-up problems
PUPOptions: {
width: 800,
effect: 'fade',
effectlength: 200,
myPosition: 'center',
atPosition: 'center',
ofTarget: window
},
// Default options for in-video links
VidLinkOptions: {
hideLinkAfter: 5, //seconds
effect: 'slide',
hide: { direction: 'down' },
show: { direction: 'down' },
speed: 500,
location: 'bl' // Bottom Left. bl, br, tl, and tr are all ok.
}
};
</script>