Implementation: the SoundSuggest application

The application that was built for this thesis is called SoundSuggest. It is a chrome extension that uses the D3 JavaScript library and the Last.fm API to inject the explanation system into the recommendations page of Last.fm. In this chapter we will discuss the technologies we have used to create the application, the software design of the application and some specifics about the implementation of the application.

5.1 Technologies

5.1.1 Chrome extensions

Chrome Extensions are applications written in HTML, JavaScript and CSS, that enhance the functionality of the Google Chrome web browser [15].

There are different types of extensions. Browser actions are applications that can be launched regardless of the web page you are at. They appear as a button with a specified logo in the toolbar of the Chrome browser. By clicking the browser action you can specify to open up a tooltip or a popup [13]. Page action extensions are meant to be shown when browsing specific web pages. They appear as an icon in the address bar. Page actions use content scripts to inject code into the web page [16].

The file manifest.JSON is one of the key areas of a chrome extension. It specifies the name and the version of your application as well as other important settings such as the type of the extension, scripts and security policies [14].

Many extensions use a two-layered structure in which you have a background page and UI pages or content scripts [16]. In the usual case the views are stateless and background pages are not. When the view needs some state, it requests the state from the background page. When the background page notices a state change, the background page tells the views to update [12]. Background pages can either be persistent or not. In the last case we are talking about so called event pages; they are opened and closed as needed [16].

There are various ways to use UI pages: you can open an HTML page in a popup, another tab or options page. The HTML pages inside an extension have complete access to each other’s DOMs, and they can invoke functions on each other [16].

Content scripts are JavaScript scripts that are used to interact with a webpage opened in a browser tab. An important remark is that you should consider a content script part of the webpage it is injected into, rather than its parent extension. It can modify the DOM of the webpage but not the DOM of its background page. However it can ask its background page for data through listeners in the background page’s script [16].

5.1.2 The Last.fm API

The Last.fm API offers great functionality such as the recommender system, Last.fm scrobbling and accessing and modifying your Last.fm profile information, aside from providing a large amount of data. To use the API, libraries have been developed for several technologies, such as JavaScript, PHP, Python and Actionscript among others [32].

To build an application using the Last.fm API, you have to create an API account first at http://www.last.fm/api/account/create. Once you have been registered, you will receive an API key and an API secret.

For testing purposes it will also be handy to have a Last.fm account of your own. So if you haven’t got one already sign up at their website. You might also want to one or more of their Scrobbler applications. This will collect data from your music players to generate profile information that will be used to generate recommendations [31].

There are already several interesting applications that make use of the Last.fm API. Even more interesting perhaps is that some developers distribute free JavaScript libraries that act like a facade on the Last.fm API. The JavaScript library we will be using here, can be found on GitHub and is written by Felix Bruns.

5.1.3 D3.js JavaScript Library

Visualizations for web applications can be built using scalable vector graphics (SVG). SVG is an XML-based language to describe two-dimensional graphics [60]. It is supported by most of the latest versions of most popular browsers, including Chrome, Firefox, Internet Explorer 9, Opera and Safari[36, 59].

D3.js is a JavaScript library that uses the W3C standards HTML, SVG and CSS to build data-driven documents [5]. There are various tutorials explaining the basics on how to use this library.

In short, to get started the library should be included in your web page. Next, using the D3 selectors, elements can be added and removed easily from the web page. The library also offers a number of built-in algorithms, as well as a series of example visualizations that can be customized as desired.

5.1.4 Additional libraries

In addition to the Last.fm API JavaScript library and D3.js, four other JavaScript libraries were used, namely:

  • jQuery: “jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers”[51].
  • jQuery UI: “jQuery UI is a curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library”[52].
  • Purl.js: a library built on the jQuery library to retrieve GET parameters from the web page’s URL.
  • Spinner.js: a library that creates a spinner element with given parameters for customization.

Software design and application architecture

The architecture of the application is shown in figure 5.1. Five distinct components can be identified that are of importance for the application:

  • Last.fm recommendations page: The HTML will we injected into this page. Although it is not a part of the source code, it poses certain limitations on the script. For example one should be careful not to override certain CSS definitions, and the injected code should fit into the page layout to achieve better looking results.
  • Content script: The content script creates the injected HTML elements, handles user input, and delegates calls to the Last.fm API to the background script.
  • Background script: the background script deals with local storage and calls to the Last.fm API.
  • Local storage: The local storage of the Chrome browser can be used to store preferences.
  • Last.fm API: The Last.fm API handles calls and returns the requested content.
architecture of the soundsuggest application

Figure 5.1 : The architecture of the application.

Figures 5.2 and 5.3 show the sequence diagrams of what happens when loading the application. The first time the application is loaded, the user will have to authenticate the application. If the user does this, the content script will retrieve the token from the callback URL, and get a session key from the Last.fm API. This session key then stored. When the application is started again, the stored key can be retrieved from the local storage. Similarly other settings are loaded from local storage. If none have been stored so far, the default settings are returned and stored.

getting session key

Figure 5.2 : Sequence diagram: opening the Last.fm recommendations page part 1: retrieving a session key.

settings

Figure 5.3 : Sequence diagram: opening the Last.fm recommendations page part 2: retrieving stored settings.

Algorithm 5.1 shows how the data structure is constructed from calls to the Last.fm API. The resulting data structure is an approximation of the utility matrix on a local scale, i.e., the neighbourhood of the active user and the top artists of the active user. The time complexity of the algorithm depends on the number of artists A, i.e., the number of recommendations R added to the number of top artists T, and the number of neighbours N involved. The resulting time complexity is quadratic, i.e., O(N^2), if A approaches N.

Algorithm 5.1 Loading the data for the visualization.
algorithm5.1

The corresponding sequence diagram is shown in figure 5.4. The two calls within the inner loop have a large impact on the performance of the algorithm. Caching parts of the data structure is possible. However, small changes in the data may have an impact on the rest of data structure. For example if a user gets promoted to a neighbour and another gets demoted, it is impossible to know which user has to be removed from the data structure without comparing the lists of updated neighbours to the old version. Next the relevant neighbours should be removed from the data set and the new ones added. For artists that are promoted to the status of recommendation, there is a similar scenario. In this case, note that all of the users should be compared to the new items as well.

load visualization

Figure 5.4 : Sequence diagram: loading the visualization.

5.2 Implementation

5.2.1 Configuration file manifest.JSON

Aside from the basic parameters in the manifest.JSON file, such as name, version, manifest_version, et cetera, there are several parameters that require some more attention. First of all, this extension is defined as a so-called page action. This is done by adding the page action with required attributes, namely certain icons and a default title, to the JSON file. The icon will become visible in the address bar when visiting a page defined in the content_scripts parameter. In this case the script will become active when visiting the recommendations page of the Last.fm website. The various CSS and JavaScript used in the extension are also listed together with the content script.

As the application makes use of the storage functionality, the storage option should be added to the permissions. Since the application does calls to the Last.fm audioscrobbler, this link should be added to the permissions as well. Note that SSL is required when making external calls, otherwise the application won’t even be accepted when uploading it to the chrome web store. The link should also be addded to the content_security_policy parameter of the manifest file.

To be able to access and load images, for example in the CSS definitions, it is necessary to add these to the web_accessible_resources parameter.

5.2.2 The visualization infovis

The visualization consists out of four main parts:

  • JSON data;
  • JavaScript script;
  • CSS style sheet;
  • Custom implementation of certain methods.

Data structure

The JSON file structure is shown in listing 5.1. It consists out of a list of artists and users that were retrieved using algorithm 5.1. It can be generated by using the output of algorithm 5.1 as input for algorithm 5.2. This is also a quadratic algorithm. However, its cost is much lower as it requires no expensive calls to the Last.fm API in its inner loop.

Listing 5.1 : The structure of the JSON file that is the input for the visualization script.

{
	"items" :
	[
		{
			"name"  : "item.SOME_ARTIST",
			"edges" :
			[
				"item.SOME_ARTIST.user.SOME_USER",
				...
			],
			"owners" :
			[
			"SOME_USER",
			...
			]
		},
		...
	],
	users :
	[
		{
			"name"      : "SOME_USER",
			"active"    : BOOLEAN
		},
		...
	]
}

Algorithm 5.2 Loading the data for the visualization.
algorithm5.2

The visualization script

Once the data structure has been constructed, it is plugged into the script. Listing 5.2 shows how this is done in JavaScript, assuming that the variables LAYOUT and DATA are known. The script uses the data to generate nodes, edges in an SVG element, and a list of users as LI elements in an UL element next to the visualization.

For this visualization, a D3.js hierarchical edge-bundling example by Michael Bostock [6] was adapted. The major changes to the original code are the extension of the original data structure as explained in the previous section, and the addition of extra CSS classes to support interactions with the user list, which are discussed in the next section. In conclusion, for a detailed description of the visualization code, we refer to the D3.js website.

Listing 5.2 Create a new Whitebox object for given settings and data.

var WHITEBOX = new Whitebox ();
WHITEBOX.setLayout ( LAYOUT );
WHITEBOX.setData ( DATA );
WHITEBOX.create ();

Style sheet

To support hover and click interactions, each node and each user LI element has an onmouseover, onmouseout, and click event listener attached to it. When one of these events is triggered, the appropriate classes are added or removed from these elements. Table 5.1 shows which classes are activated for which interaction. Each of these classes in also combined with another set of classes as listed in table 5.2. By changing the colour classes for nodes, edges and LI‘s, colour patterns chosen by the end user are applied on the fly.

Table 5.1 Overview of the classes that added for each supported interaction for each interaction target.

Interaction SVG Node in #chart svg User LI in ul#users
Click node .link-item-clicked .user-item-clicked
.node-item-clicked
Click user .user-clicked .user-clicked
.link-user-clicked
.node-user-clicked
Hover node .node-item-mouseover .user-item-mouseover
.user-item-mouseover
Hover user .node-user-mouseover .user.user-mouseover
.link-user-mouseover

Table 5.2 Overview of the classes that added for each supported colour.

Blue Green Red
Active user .blue-active .green-active .red-active
Mouseover .blue-mouseover .green-mouseover .red-mouseover
Click .blue-clicked .green-clicked .red-clicked
Advertisements