-
Notifications
You must be signed in to change notification settings - Fork 6
Accessing Badge Metadata
When you use the Open Badges Displayer script to process baked badges in a Web page, your client-side code can access the resulting badge metadata. The Displayer will extract and parse the metadata for each badge in your page, storing the result in an array your code can process. Each item in the array includes the assertion data for one of the badges, together with the badge image element.
By default, the Displayer will attempt to parse all baked badge images in the page (or selected images if you pass it a class or ID selector). It will extract the data and present the badge name and description in an interactive component, appearing as an overlay on hover and in a lightbox on click. This default usage may be all you need, but you can optionally enhance it at client side, since the Displayer places the parsed assertion data in an array you can access in the browser - and therefore in your client-side code.
Let's assume that your page is using this code to create the Displayer instance:
window.openbadges.unbake();
You can then access the badge data as follows:
//badge metadata array, one entry for each badge
window.openbadges.badges; //[...]
//array item
window.openbadges.badges[0]; //{assertion: Object, img: img}
//badge image
window.openbadges.badges[0].img; //<img src="great-badge.png"/>
//badge assertion
window.openbadges.badges[0].assertion; //{recipient: "earner@example.org", badge: Object, verify: Object}
You could build some of this additional data into the page if that suits your project. Let's look at a trivial example page to demonstrate. You will need some familiarity with assertion structure, see Assertion Information for the Uninitiated if you're new to Open Badge assertions. In general, an assertion includes information about who earned a badge, what the badge represents and who issued it.
Let's try out retrieving some additional data items from the assertions for each badge, writing these into the page to enhance the default effect. For each badge, we will include a link to the issuer site and criteria page. We'll list these below each badge image, displaying these new items on user clicks. For demonstration, each baked badge image element will be placed in the following structure:
<div>
<div>
<img src="baked-badge.png" class="baked-badge"/>
</div>
<div>
<span onclick="showIssuer(this)">Who issued this? </span>
</div>
<div>
<span onclick="showCriteria(this)">What is required to earn this?</span>
</div>
</div>
We call functions on user clicks of these questions to show the issuer and criteria links. The functions will receive as a parameter the span element clicked, which shares a parent with the baked badge image. Your code will have access to the badges
array created by the Displayer script - each array entry includes the badge assertion plus the image element it was extracted from.
When the user clicks "Who issued this?" or "What is required to earn this?", we will first find the correct entry in badges
array, using the img
element, which is in the same tree as the clicked span - your own display implementations may be simpler than this, the intention here is to show how you can use the data returned from the Displayer.
The showIssuer
function will being as follows:
function showIssuer(elem){
//get the badge image with the same parent as the clicked span
var imgs=elem.parentNode.parentNode.getElementsByClassName('baked-badge');
//get the badge image source
var src=imgs[0].src;
//find the relevant badge in the array
}
We start by retrieving the image element for the badge with the same parent as the clicked span. We will find the correct badge in the Displayer badges
array by checking each one for the img
element src
. Depending on the layout of your page, you may be able to achieve this without searching the badges
array, for example by passing an index number from your clicked element.
Let's add a function to search the badges
array for an entry with a particular badge image src
:
function findBadge(src){
var b;
for(b=0; b<window.openbadges.badges.length; b++){
if(window.openbadges.badges[b].img.src===src) return b;
}
}
We'll pass the src
to the function, which checks each entry in the array and returns the index of the found badge. Now back in the showIssuer
function, we can call the function:
//find the relevant badge in the array
var badgeIndex=findBadge(src);
Now that we have the index for the badge in the array, we can begin retrieving the assertion data items we want. Still in showIssuer
, we can get the issuer name as follows:
var issuerName = window.openbadges.badges[badgeIndex].assertion.badge.issuer.name;
The assertion JSON will have a structure similar to this:
{
"recipient": "earner@example.org",
"badge": {
"name": "...",
"description": "...",
"criteria": "http://issuersite.com/criteria.html",
"issuer": {
"name": "Issuer Name",
"url": "http://issuersite.com",
...
},
...
},
"verify": {
"url": "http://issuersite.com/assertion.json",
"type": "hosted"
}
}
Note that the badge assertion structure will vary for different versions of the specification.
Back in the function, after retrieving the issuer name, we can get the issuer site URL:
var issuerLocation = window.openbadges.badges[badgeIndex].assertion.badge.issuer.url;
The field may be url
or origin
depending on which spec version the assertion was built for.
Since we are going to build a link for both the issuer and criteria items, we could use a dedicated function:
function createMetaLink(display, destination){
var anchor = document.createElement('a');
//set link location and title to passed destination
anchor.setAttribute('href', destination);
anchor.setAttribute('title', destination);
//set passed issuer name as link display text
var anchorText = document.createTextNode(display);
anchor.appendChild(anchorText);
return anchor;
}
We create an anchor element with the passed display text and destination parameters, returning the resulting link element. Back in showIssuer
, we can call the function, passing the values we retrieved from the badge assertion:
var metaLink = createMetaLink(issuerName, issuerLocation);
We can finish the function by adding the new anchor element to the parent of the clicked span element, disabling the function for future clicks:
elem.parentNode.appendChild(metaLink); elem.removeAttribute('onclick');
We can use the same approach to show the criteria page link:
function showCriteria(elem){
//get badge image from same parent as clicked element
var imgs=elem.parentNode.parentNode.getElementsByTagName('img');
var src=imgs[0].src;
//find the badge corresponding to the image src
var badgeIndex=findBadge(src);
//get the criteria value from the assertion
var criteriaLocation = window.openbadges.badges[badgeIndex].assertion.badge.criteria;
//create a link to the criteria page
var metaLink = createMetaLink('View Criteria Page', criteriaLocation);
elem.parentNode.appendChild(metaLink); elem.removeAttribute('onclick');
}
If you try this out in a page, you should see clickable text next to each baked badge listed - clicking on the text should show the relevant links. This is how it looks with a little CSS:
Your own code will naturally be determined by the needs of your badge display project, but you should hopefully see from this simple example how you can access the metadata for baked badges in your pages using only client-side code.