build widgets

Post on 18-Dec-2014

2.613 Views

Category:

Technology

5 Downloads

Preview:

Click to see full reader

DESCRIPTION

These are the slides I used at the JTEL winterschool to describe how to create widgets for use in Wookie.

TRANSCRIPT

Lets Build Some Widgets!

Anatomy of a Widget

• Config.xml <- W3C Widgets P&C Spec• icon.png• index.html <- HTML start file• JavaScript code, CSS

• Zip it up, change ext to .wgt, and you’redone

Widget metadata• Id• Height, Width• Name• Description• Version• Features• Author info• License

A Silly Example: config.xml<?xml version="1.0" encoding="utf-8"?><widget xmlns="http://www.w3.org/ns/widgets"

id="http://www.getwookie.org/widgets/tea"version="1.0” height="150” width="125"><name>Tea</name><description>A silly Tea widget</description><author>Scott Wilson</author>

</widget>

A Silly Example: index.html<html>

<body><img src="tea.jpg" /><p>Time for a break, mate</p>

</body></html>

Make your own basic widget

1. Make an index.html file2. Make a config.xml file3. Zip them up, and change suffix to “.wgt”4. Upload to a wookie server

Uploading

• Go to http://192.168.2.161/wookie• Click “admin”• Login with java/java• Click “add new widget”• Find your .wgt file• OK!

Previewing a widget

• Go to 192.168.2.161:8080/wookie• Click “View Widget Gallery”• Click the “demo” link under your widget• Your widget will show

Preferences

• You can store preferences for an instance ofa widget using:

widget.preferences.setItem(“key”, “value”)widget.preferences.getItem(“key”)

Collaborative Widgets

• State and Participants

• State is shared across widgets with the sameIRI in the same shared context.

• State is propagated to related widgets usingan event callback

• State is set by submitting deltas

State examplewave.setStateCallback(stateUpdated);

stateUpdated = function(){ var keys = wave.getState().getKeys(); for (var i = 0; i < keys.length; i++) {

alert(wave.getState().get(keys[i])); }};

wave.getState().submitValue(“key”, “value”);

Participants

• Register callbacks with:wave.setParticipantCallback(myfunction);

• Methods:– getViewer() - get the current user– getParticipants() - get map of all participants

• Model:– getId(), getDisplayName(), getThumbnailUrl()

Making a collaborative app

• This requires some more planning

1. Draw up a design2. Create a working test page3. Implement models, action handlers and

event handlers4. Create the config.xml, icon.png, zip it up

and run it

Design

• Start with the view - what the widget lookslike

• Create the model - what are the objects inthe state model?

• Add the actions - how you interact with it• Wire it all up…

Prototyping

• Make a regular html page to test out yourview. Populate it with fake model, and don’twire up the actions yet

• You can reuse this for the real widget - justtake out your fake state info sections

Implementing

• Create a “Model” object for your statemodel

• Create a “Controller” object, and a methodin it for each action

• Register the participant and state eventhandlers with an “update view” method thatpopulates the view when running

function Task(id,name,status,assigned){ this.task_id = id; this.name = name; this.status = status; this.assigned_to = assigned;}Task.prototype.save = function(){wave.getState().submitValue(this.task_id, JSON.stringify(this));}

Models• Models can be implemented in typical “bean” fashion• Save/Find methods need to access wave state• Can use JSON (e.g. with json.js) or just plain strings for storage

Task.create = function(json){ var obj = JSON.parse(json); var task = new Task(obj.task_id,

obj.name,obj.status,obj.assigned_to); return task;}

Task.find = function(task_id){ var keys = wave.getState().getKeys(); for (var i = 0; i < keys.length; i++) { var key = keys[i]; if (key == task_id){ return Task.create(task_id, wave.getState().get(key)); } } return null;}

Task.findAll = function(){ var tasks = {}; var keys = wave.getState().getKeys(); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var task = Task.create(key, wave.getState().get(key)); tasks[key] = task; } return tasks;}

Static model methods

• Typically needmethods to turn statestrings back intomodel instances

• Also finder methods toget a particular modelobject

• This isn’t the only wayto do this, but is anOK pattern

/** * The Controller object * This is used to wire up the view and model with actions */var Controller = {

// Action handlers

// Toggle task state between completed and to-do toggleTask: function(task_id){ },

// Create a new task newTask: function(){ },

// Abandon task for someone else to do abandonTask: function(task_id){ },

// Claim a task (assign to self) claimTask: function(task_id){ }}

Controllers

• Methods for eachaction, makingchanges to the model

• You usually don’tneed to do any codethat interacts withHTML, as the eventhandlers should dothat

// Update the view when state has been updated stateUpdated: function(){ var tasks = Task.findAll(); if (tasks && tasks != null){ var tasklist = ""; for (key in tasks) { var task = tasks[key]; tasklist += // the task stuff to show dwr.util.setValue("tasklist", tasklist, {

escapeHtml:false }); var objDiv = document.getElementById("tasklist"); objDiv.scrollTop = objDiv.scrollHeight; } }, participantsUpdated: function(){ Controller.updateUser(); }

Event HandlersThese fire whenever the state or participants

are updated (e.g. by another instance).

Event handlers need to be registered like so:

wave.setStateCallback(Controller.stateUpdated);wave.setParticipantCallback(Controller.participantsUpdated);

Also useful to have these methods calledfrom onLoad() in an init() function tocreate initial view

You can import JQuery if you like forsetting the view content, or do it usingDOM

Packaging

You need to add this to your config.xml to tellWookie to include the Wave Gadget APImethods:

<featurename="http://wave.google.com"required="true"/>

Uploading, debugging and testing

• You need acollaborativeenvironment to testyour widget properly

• I’ve set up a Moodleinstance at:

192.168.2.XXX

Login as ws1,ws2,ws3,or ws4

Other stuff…

• AJAXIf you want to call

external sites fromwithin the widget, callmyurl =widget.proxify(url)first to call it via proxy.Also need to add thesite to the serverwhitelist.

• Camera accessIf you want to access the

user’s camera from awidget, there is anexample of how to dothis in the moodlecourse (topic 3)

top related