Skip to content

Basic Web Plugin Example

Derrick Gold edited this page May 19, 2016 · 4 revisions

#Basic Web Plugin Example

##Use Case A basic web plugin consists typically of HTML, CSS, and or JavaScript code, and does not call any external programs to generate information to display. That is to say, these plugins run natively in the browser.

##Sample Plugin Description The sample plugin provided on this page will display a random comic strip from xkcd that will update every 5 minutes.

Sample Plugin ScreenShot

##Directory Structure Here is the layout for the sample plugin directory which should reside in the Smart Reflect Server plugin directory.

XKCDComic/
    plugin.conf
    xkcdcomic.html
    xkcdcomic.css
    xkcdcomic.js

The sample project code can be pulled from this repository.

##xkcdcomic.html Each plugin that is loaded into the mirror display has their own <div> container with the id set to the name of the plugin. When this sample plugin is loaded, the <div> container will have the id="XKCDComic", since that is the name of the plugin directory that correlates to the system name of the plugin.

HTML files for plugins are treated as partials, they will be injected into the <div> container that is created for the plugin it is associated with.

Here is the output of xkcdcomic.html

<div class="title"></div>
<div class="comic"></div>

When the plugin is loaded, there will exist a

that looks like:
<div id="XKCDComic">
    <div class="title"></div>
    <div class="comic"></div>
</div>

The

container for the plugin will be created regardless if the plugin has an associated HTML file or not. ##xkcdcomic.css With the HTML structure explained, setting the style through CSS is trivial.

xkcdcomic.css output:

#XKCDComic {
  position: absolute;
}

#XKCDComic .title {
  font-size: 14pt;
  text-align: center;
}

##xkcdcomic.js Here is the controller for the plugin. It's responsible for fetching and displaying the comic.

//jsonp callback function
var displayComic = null;

//This object will be instantiated when the plugin is loaded.
var XKCDComic = function(pluginConf) {

	var instance = this;

	this.lastComicID = null;
	this.containerDom = null;
	this.titleDom = null;
	this.comicDom = null;
	this.initInterval = null;
	this.updateInterval = null;
	this.comicScript = null;

	//set callback for comic retrieval
	displayComic = function(data) {
		//update last comic id
		if (instance.lastComicID === null)
			instance.lastComicID = parseInt(data.num);

		//update the plugin client
		instance.titleDom.innerHTML=data.title;
		instance.comicDom.src=data.img;
	}


	//get XKCD comic information via their api
	this.getComicMetaData = function(id, successCb, errorCb, otherCb) {

		var comicUrl = null;
		//no id specified, get the newest comic
		if (!id)
			comicUrl = "http://dynamic.xkcd.com/api-0/jsonp/comic/"
		else
			comicUrl = "http://dynamic.xkcd.com/api-0/jsonp/comic/" + id;

		//remove old script
		if (instance.comicScript)
			instance.comicScript.parentNode.removeChild(instance.comicScript);
		//get new script
		instance.comicScript = document.createElement('script');
		instance.comicScript.src = comicUrl + "?callback=displayComic";
		document.getElementsByTagName('head')[0].appendChild(instance.comicScript);
	}

	this.getComic = function() {
		var nextComicID = null;

		//if we don't have the last released comic's ID, we can't generate
		//a random number in the valid comic ID range. So first get the last
		//comic to determine the ID range.
		if (instance.lastComicID) {
			//otherwise, we have the last comic ID, pick a random comic from
			//0 - lastComicID
			nextComicID = parseInt(Math.random() * instance.lastComicID);
		}

		instance.getComicMetaData(nextComicID);
	}

	//set a timer to fetch a new comic every "newPeriod" seconds
	this.setPeriod = function(newPeriod) {
		newPeriod = parseInt(newPeriod);

		if (instance.updateInterval)
			window.clearInterval(instance.updateInterval)

		//convert period into seconds
		newPeriod = parseInt(newPeriod * 1000);

		instance.updateInterval = setInterval(function() {
	    	instance.getComic();
	    }, newPeriod);

	}

	//set callbacks for pluginConf settings as they are read
	pluginConf.onGet = function(resp) {

		//if comic time-to-live (TTL) value was returned, update the comic period
		if (resp.setting === "comicTTL") {
			instance.setPeriod(resp.value);
			console.log(resp);
		}
	}

	//constructor must be called init for the web frontend to initialize
	//when this plugin is loaded
	this.init = function() {
		//locate relevant doms for updating
		instance.titleDom = instance.containerDom.getElementsByClassName("title")[0];
		instance.comicDom = instance.containerDom.getElementsByClassName("comic")[0];

		//get the initial comic
		instance.getComic();

		//load update time
		pluginConf.get("comicTTL");
	}

	//destructor must be named 'destroy' for web frontend to cleanup
	//when unloading this plugin
	this.destroy = function() {
		//clear all set intervals
		if (instance.initInterval)
			window.clearInterval(instance.initInterval);

		if (instance.updateInterval)
			window.clearInterval(instance.updateInterval);

		//unset callback function
		displayComic = null;
	}

	//wait for HTML data to load before initializing
	this.initInterval = setInterval(function() {
		var container = document.getElementById('XKCDComic');
		//checks that the title class div object defined in xkcdcomic.html is
		//injected into the plugin client
		var domExists = container.getElementsByClassName("title")[0];
		loaded = (domExists !== undefined && domExists !== null);

		if (loaded) {
			instance.containerDom = container;
			window.clearInterval(instance.initInterval);
			instance.initInterval = null;
			instance.init();
		}

	}, 50);
};

##plugin.conf

This file contains references to the files that are required to run the plugin, as well as plugin specific settings.

#Plugin Configuration
css-path:0=xkcdcomic.css

js-path:0=xkcdcomic.js

html-path=xkcdcomic.html

#When javascript file loads, instantiate this object
#Must contain a destroy function (no arguments)
js-main-obj="XKCDComic"


#make plugin start on mirror load
start-on-load=true

#Settings used by the JavaScript Object

#Set comic time-to-live to 5 minutes (300 seconds)
#after 5 minutes, a new comic will be fetched
comicTTL=300
Clone this wiki locally