• Like
Build Widgets
Upcoming SlideShare
Loading in...5

Thanks for flagging this SlideShare!

Oops! An error has occurred.

Build Widgets


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

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

Published in Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads


Total Views
On SlideShare
From Embeds
Number of Embeds



Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

    No notes for slide


  • 1. Lets Build Some Widgets!
  • 2. 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’re done
  • 3. Widget metadata • Id • Height, Width • Name • Description • Version • Features • Author info • License
  • 4. 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>
  • 5. A Silly Example: index.html <html> <body> <img src="tea.jpg" /> <p>Time for a break, mate</p> </body> </html>
  • 6. Make your own basic widget 1. Make an index.html file 2. Make a config.xml file 3. Zip them up, and change suffix to “.wgt” 4. Upload to a wookie server
  • 7. Uploading • Go to • Click “admin” • Login with java/java • Click “add new widget” • Find your .wgt file • OK!
  • 8. Previewing a widget • Go to • Click “View Widget Gallery” • Click the “demo” link under your widget • Your widget will show
  • 9. Preferences • You can store preferences for an instance of a widget using: widget.preferences.setItem(“key”, “value”) widget.preferences.getItem(“key”)
  • 10. Collaborative Widgets • State and Participants • State is shared across widgets with the same IRI in the same shared context. • State is propagated to related widgets using an event callback • State is set by submitting deltas
  • 11. State example wave.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”);
  • 12. Participants • Register callbacks with: wave.setParticipantCallback(myfunction); • Methods: – getViewer() - get the current user – getParticipants() - get map of all participants • Model: – getId(), getDisplayName(), getThumbnailUrl()
  • 13. Making a collaborative app • This requires some more planning 1. Draw up a design 2. Create a working test page 3. Implement models, action handlers and event handlers 4. Create the config.xml, icon.png, zip it up and run it
  • 14. Design • Start with the view - what the widget looks like • Create the model - what are the objects in the state model? • Add the actions - how you interact with it • Wire it all up…
  • 15. Prototyping • Make a regular html page to test out your view. Populate it with fake model, and don’t wire up the actions yet • You can reuse this for the real widget - just take out your fake state info sections
  • 16. Implementing • Create a “Model” object for your state model • Create a “Controller” object, and a method in it for each action • Register the participant and state event handlers with an “update view” method that populates the view when running
  • 17. 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 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)); }
  • 18. Static model methods 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; • Typically need } methods to turn state Task.find = function(task_id){ var keys = wave.getState().getKeys(); for (var i = 0; i < keys.length; i++) { strings back into var key = keys[i]; if (key == task_id){ model instances return Task.create(task_id, wave.getState().get(key)); } } • Also finder methods to } return null; get a particular model Task.findAll = function(){ object var tasks = {}; var keys = wave.getState().getKeys(); for (var i = 0; i < keys.length; i++) { • This isn’t the only way var key = keys[i]; var task = Task.create(key, wave.getState().get(key)); tasks[key] = task; to do this, but is an } return tasks; OK pattern }
  • 19. Controllers /** * The Controller object * This is used to wire up the view and model with actions • Methods for each */ var Controller = { action, making // Action handlers changes to the model // Toggle task state between completed and to-do toggleTask: function(task_id){ • You usually don’t }, need to do any code // Create a new task newTask: function(){ }, that interacts with // Abandon task for someone else to do HTML, as the event abandonTask: function(task_id){ }, handlers should do // Claim a task (assign to self) claimTask: function(task_id){ that } }
  • 20. Event Handlers // Update the view when state has been updated These fire whenever the state or participants stateUpdated: function(){ are updated (e.g. by another instance). var tasks = Task.findAll(); if (tasks && tasks != null){ var tasklist = ""; Event handlers need to be registered like so: for (key in tasks) { var task = tasks[key]; wave.setStateCallback(Controller.stateUpdated); wave.setParticipantCallback(Controller.participantsUpdated); tasklist += // the task stuff to show dwr.util.setValue("tasklist", tasklist, { escapeHtml:false }); Also useful to have these methods called var objDiv = document.getElementById("tasklist"); from onLoad() in an init() function to objDiv.scrollTop = objDiv.scrollHeight; create initial view } }, participantsUpdated: function(){ You can import JQuery if you like for Controller.updateUser(); setting the view content, or do it using } DOM
  • 21. Packaging You need to add this to your config.xml to tell Wookie to include the Wave Gadget API methods: <feature name="http://wave.google.com" required="true"/>
  • 22. Uploading, debugging and testing • You need a • I’ve set up a Moodle collaborative instance at: environment to test your widget properly 192.168.2.XXX Login as ws1,ws2,ws3, or ws4
  • 23. Other stuff… • AJAX • Camera access If you want to call If you want to access the external sites from user’s camera from a within the widget, call widget, there is an myurl = example of how to do widget.proxify(url) first to call it via proxy. this in the moodle Also need to add the course (topic 3) site to the server whitelist.