Skip to content

Accessing Badge Metadata

SueSmith edited this page Sep 15, 2014 · 4 revisions

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.

How does it work?

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.

Selecting Assertion Items

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:

Displayed Badges

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.

Clone this wiki locally