Author: scottbw
Date: Wed Aug 17 14:59:46 2011
New Revision: 1158758
URL: http://svn.apache.org/viewvc?rev=1158758&view=rev
Log:
Cleaned up the Widget API implementation code and added more code comments to
make it more readable. Also did a very small bit of refactoring for setting up
accessor methods in one place rather than two - I've checked this against
Safari, Opera and Firefox however it should also be checked with IE8 and IE9.
Modified:
incubator/wookie/trunk/WebContent/shared/js/wookie-wrapper.js
Modified: incubator/wookie/trunk/WebContent/shared/js/wookie-wrapper.js
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/WebContent/shared/js/wookie-wrapper.js?rev=1158758&r1=1158757&r2=1158758&view=diff
==============================================================================
--- incubator/wookie/trunk/WebContent/shared/js/wookie-wrapper.js (original)
+++ incubator/wookie/trunk/WebContent/shared/js/wookie-wrapper.js Wed Aug 17
14:59:46 2011
@@ -1,3 +1,4 @@
+
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,226 +13,383 @@
* limitations under the License.
*/
- /*
+var widget;
+
+/*
* WidgetPreferences, singleton class
* Calls to this object replace the legacy
setPreferenceForKey/preferenceForKey methods
* Implements HTML 5 Storage API
*/
-WidgetPreferences = new function WidgetPreferences(){
- // the internal preferences map
- this.prefs = {};
- // SPEC: The length attribute must return the number of key/value pairs
currently present in the list associated with the object.
- this.length = 0;
- // Resets the length attribute
- this.calcLength = function(){
- var x = 0;
- for (key in this.prefs) x++;
- this.length = x;
- return x;
- }
- this.key = function(n){
- var x=0;
- for (key in this.prefs){
- if (x == n) return key;
- x++;
- };
- }
- this.getItem = function(key){
- if (!this.prefs[key]) return undefined;
- return this.prefs[key]["dvalue"];
- }
- this.setItem = function(key,value){
- // Make a preference object
+var WidgetPreferences = new function WidgetPreferences() {
+
+ /*
+ * the internal preferences map
+ */
+ this.prefs = {};
+
+ /*
+ * the number of key/value pairs currently present in preferences
+ */
+ this.length = 0;
+
+ /**
+ * Resets the length attribute
+ */
+ this.calcLength = function () {
+ var x = 0;
+ for (var key in this.prefs) {
+ x++;
+ }
+ this.length = x;
+ return x;
+ };
+
+ /**
+ * Returns the tuple for the key
+ * @param key the key to return the tuple for
+ */
+ this.key = function (n) {
+ var x = 0;
+ for (var key in this.prefs) {
+ if (x == n) {
+ return key;
+ }
+ x++;
+ }
+ };
+
+ /**
+ * Returns the value of a key
+ * @param the key to return the value for
+ */
+ this.getItem = function (key) {
+ if (!this.prefs[key]) {
+ return undefined;
+ }
+ return this.prefs[key]["dvalue"];
+ };
+
+ /**
+ * Create getters and setters for a preference
+ * @param key the key to set
+ * @param value the value to set (for IE)
+ * @param pref the preference object to set (for IE)
+ */
+ this.createAccessorMethods = function (key, value, pref) {
+ try {
+ eval("Widget.preferences.__defineGetter__('" + key + "',
function(){return Widget.preferences.getItem('" + key + "')})");
+ eval("Widget.preferences.__defineSetter__('" + key + "',
function(v){return Widget.preferences.setItem('" + key + "',v)})");
+ eval("Widget.preferences.prefs[\"" + key + "\"]=pref;");
+ }
+ catch (err) {
+
+ //
+ // cant use __defineGetter__ so try to setup for IE9
+ //
+ try {
+ eval("Object.defineProperty(Widget.preferences,'" + key + "',
{get: function get() { return Widget.preferences.getItem('" + key + "');},set:
function set(value) {Widget.preferences.setItem('" + key + "',value)}});");
+ eval("Widget.preferences.prefs[\"" + key + "\"]=pref;");
+ }
+ catch (err2) {
+
+ //
+ // Catch IE 8 error. See WOOKIE-44
+ //
+ eval("Widget.preferences");
+
+ //
+ // If eval went fine, populate with data, See WOOKIE-151
+ //
+ if (typeof Widget.preferences != "undefined") {
+ widget.preferences[key] = value;
+ widget.preferences.prefs[key] = pref;
+ }
+ }
+ }
+ };
+
+ /**
+ * Sets a key to a value
+ * @param key the key to set
+ * @param value the value to set
+ */
+ this.setItem = function (key, value) {
+ //
+ // Make a preference object and set its properties
+ //
var pref = {};
pref.dvalue = value;
pref.key = key;
pref.readOnly = false;
- var existing = this.prefs[key];
+ //
+ // Check if the preference already exists
+ //
+ var existing = this.prefs[key];
- if (existing){
- if (existing["readOnly"] == true){
- window.DOMException.code =
DOMException.NO_MODIFICATION_ALLOWED_ERR;
- throw (window.DOMException);
+ //
+ // If it does exist, check it isn't read-only
+ //
+ if (existing) {
+ if (existing["readOnly"] === true) {
+ window.DOMException.code =
DOMException.NO_MODIFICATION_ALLOWED_ERR;
+ throw (window.DOMException);
}
} else {
- // Setup prototype methods
- try{
- eval("Widget.preferences.__defineGetter__('"+key+"',
function(){return Widget.preferences.getItem('"+key+"')})");
- eval("Widget.preferences.__defineSetter__('"+key+"',
function(v){return Widget.preferences.setItem('"+key+"',v)})");
- eval("Widget.preferences.prefs[\""+key+"\"]=pref;");
- }
- catch(err){
- // cant use __defineGetter__ so try to setup for IE9
- try{
-
eval("Object.defineProperty(Widget.preferences,'" + key + "', {get: function
get() { return Widget.preferences.getItem('"+key+"');},set: function set(value)
{Widget.preferences.setItem('"+key+"',value)}});");
-
eval("Widget.preferences.prefs[\""+key+"\"]=pref;");
- }
- catch(err){
- // Catch IE 8 error. See WOOKIE-44
-
- eval("Widget.preferences");
- //If eval went fine, populate with data, See
WOOKIE-151
- if(typeof Widget.preferences != "undefined") {
- Widget.preferences[key] = value;
- Widget.preferences.prefs[key] = pref;
- }
- }
- }
- }
- this.prefs[key] = pref;
- Widget.setPreferenceForKey(key, value);
- this.calcLength();
- }
- this.removeItem = function(key){
- var existing = (this.prefs[key]);
- if (existing){
- if (existing["readOnly"] == true){
- window.DOMException.code =
DOMException.NO_MODIFICATION_ALLOWED_ERR;
- throw (window.DOMException);
+ //
+ // Setup getters and setters for the new tuple
+ //
+ this.createAccessorMethods(key, value, pref);
+ }
+
+ //
+ // Set the pref in the preferences collection
+ // and persist it
+ //
+ this.prefs[key] = pref;
+ widget.setPreferenceForKey(key, value);
+
+ //
+ // Recalculate the length of the preferences collection
+ //
+ this.calcLength();
+ };
+
+
+ /**
+ * Removes a tuple from the preferences collection
+ * @param key the key of the tuple to remove
+ */
+ this.removeItem = function (key) {
+ var existing = (this.prefs[key]);
+ if (existing) {
+ if (existing["readOnly"] === true) {
+ window.DOMException.code =
DOMException.NO_MODIFICATION_ALLOWED_ERR;
+ throw (window.DOMException);
} else {
- delete this.prefs[key];
- Widget.setPreferenceForKey(key,null);
- this.calcLength();
-
-
+ delete this.prefs[key];
+ widget.setPreferenceForKey(key, null);
+ this.calcLength();
+ }
+ }
+ };
+
+ /**
+ * Clears all tuples from the preferences collection
+ */
+ this.clear = function () {
+ for (var key in this.prefs) {
+ try {
+ this.removeItem(key);
+ } catch (e) {
+ // swallow errors, as this method must never throw them
according to spec.
}
}
- }
- this.clear = function(){
- for (key in this.prefs){
- try{
- this.removeItem(key);
- } catch (e){
- // swallow errors, as this method must never
throw them according to spec.
- }
- }
- }
-}
+ };
+};
-/*
+/**
* Widget object
*/
var Widget = {
- instanceid_key : null,
- proxyUrl : null,
- // this should be assigned by the calling JS app
- onSharedUpdate : null,
- // initialised below as a singleton
- preferences: null,
-
- init : function(){
- /*
- * This page url will be called with e.g.
idkey=4j45j345jl353n5lfg09cw03f05
- * so grab that key to use as authentication against the server.
- * Also get the proxy address and store it.
- */
- var query = window.location.search.substring(1);
- var pairs = query.split("&");
- for (var i=0;i<pairs.length;i++){
- var pos = pairs[i].indexOf('=');
- if (pos >= 0){
- var argname = pairs[i].substring(0,pos);
- if(argname=="idkey"){
- // This gets the id_key and assigns it
to instanceid_key.
- this.instanceid_key =
pairs[i].substring(pos+1);
- }
- //TODO - remove this & use a callback instead
of having it in the URL
- if(argname=="proxy"){
- this.proxyUrl =
pairs[i].substring(pos+1);
- }
- }
- }
-
- // Instantiate a Widget Preferences object, and load all values
- // Note we do this synchronously, as widgets are likely
- // to ask for a handle on this as an onLoad() event
- this.preferences = WidgetPreferences;
- dwr.engine.beginBatch();
- WidgetImpl.preferences(this.instanceid_key, this.setPrefs);
- WidgetImpl.metadata(this.instanceid_key, this.setMetadata);
- dwr.engine.endBatch({async:false});
- },
-
- setMetadata: function(map){
- for (var key in map){
- Widget.setMetadataProperty(key, map[key]);
- }
- },
-
- setMetadataProperty: function(key, value){
- if (key == "width" || key == "height") value = Number(value);
- try{
- Widget.__defineSetter__(key,
function(){window.DOMException.code =
DOMException.NO_MODIFICATION_ALLOWED_ERR;throw (window.DOMException);});
- Widget.__defineGetter__(key, function(){return value});
- } catch(err){
- try{
- // cant use __defineGetter__ so try to setup
for IE9
- Object.defineProperty(Widget, key, {
- set: function
set(){window.DOMException.code = DOMException.NO_MODIFICATION_ALLOWED_ERR;throw
(window.DOMException)},
- get: function get(){return value}
- }
- );
- } catch(err2){// catch IE8
- eval("Widget."+key+"='"+value+"';");
- }
- }
- },
-
- setPrefs: function(map){
- this.preferences = WidgetPreferences;
- this.preferences.prefs = {};
- for (i in map){
- obj = map[i];
- key = obj["dkey"];
- try{
- eval("Widget.preferences.__defineGetter__('"+key+"',
function(){return Widget.preferences.getItem('"+key+"')})");
- eval("Widget.preferences.__defineSetter__('"+key+"',
function(v){return Widget.preferences.setItem('"+key+"',v)})");
- eval("this.preferences.prefs[\""+key+"\"]=obj;");
- }
- catch(err){
- // cant use __defineGetter__ so try to setup for IE9
- try{
- eval("Object.defineProperty(Widget.preferences,'" + key
+ "', {get: function get() { return
Widget.preferences.getItem('"+key+"');},set: function set(value)
{Widget.preferences.setItem('"+key+"',value)}});");
- eval("this.preferences.prefs[\""+key+"\"]=obj;");
- }
- catch(err){
- // Catch IE 8 error. See WOOKIE-44
- eval("this.preferences.prefs[\""+key+"\"]=obj;");
- }
- }
- }
- this.preferences.calcLength();
- },
-
- setPreferenceForKey : function(wName, wValue){
- WidgetImpl.setPreferenceForKey(this.instanceid_key, wName,
wValue);
- },
-
- getInstanceKey : function(){
- return this.instanceid_key;
- },
-
- getProxyUrl : function(){
- return this.proxyUrl;
- },
-
- proxify : function(url){
- return this.proxyUrl + "?instanceid_key=" +
this.instanceid_key + "&url=" + url;
- },
-
- toString: function(){
- return "[object Widget]";
- }
-
-}
-// very important !
-Widget.init();
-widget = Widget;
-window.widget = Widget;
+ /**
+ * The ID key issued by wookie
+ */
+ instanceid_key : null,
+
+ /**
+ * The URL to the server-side proxy
+ */
+ proxyUrl : null,
+
+ /**
+ * Method called whenever widget shared data is updated. Used by Wave
feature to register its state change callback.
+ */
+ onSharedUpdate : null,
+
+ /**
+ * The preferences object; instantiated below
+ */
+ preferences: null,
+
+ /**
+ * Set up the widget object
+ */
+ init: function () {
+
+ //
+ // This page url will be called with e.g.
idkey=4j45j345jl353n5lfg09cw03f05
+ // so grab that key to use as authentication against the server.
+ // Also get the proxy address and store it.
+ //
+ var query = window.location.search.substring(1);
+ var pairs = query.split("&");
+ for (var i = 0; i < pairs.length; i++) {
+ var pos = pairs[i].indexOf('=');
+ if (pos >= 0) {
+ var argname = pairs[i].substring(0, pos);
+
+ //
+ // get the id_key and assign it to instanceid_key.
+ //
+ if (argname == "idkey") {
+ this.instanceid_key = pairs[i].substring(pos + 1);
+ }
+
+ //
+ // TODO - remove this & use a callback instead of having it in
the URL
+ //
+ if (argname == "proxy") {
+ this.proxyUrl = pairs[i].substring(pos + 1);
+ }
+ }
+ }
+
+ //
+ // Instantiate a Widget Preferences object, and load all values
+ // Note we do this synchronously, as widgets are likely
+ // to ask for a handle on this as an onLoad() event
+ //
+ this.preferences = WidgetPreferences;
+ dwr.engine.beginBatch();
+ WidgetImpl.preferences(this.instanceid_key, this.setPrefs);
+ WidgetImpl.metadata(this.instanceid_key, this.setMetadata);
+ dwr.engine.endBatch({async: false});
+ },
+
+ /**
+ * Set the metadata collection for this widget instance
+ * @param map the map of metadata items, consisting of a key and value
+ */
+ setMetadata: function (map) {
+ for (var key in map) {
+ Widget.setMetadataProperty(key, map[key]);
+ }
+ },
+ /**
+ * Set an individual metadata property.
+ * @param key the metadata key
+ * @param value the metadata value
+ */
+ setMetadataProperty: function (key, value) {
+
+ //
+ // The height and widget metadata items use Number values
+ //
+ if (key == "width" || key == "height") {
+ value = Number(value);
+ }
+
+ //
+ // Set up getters and setters; note that setters must return a
+ // NO_MODIFICATION_ALLOWED_ERR as metadata properties are read-only
+ //
+ try {
+ Widget.__defineSetter__(key, function () {
+ window.DOMException.code =
DOMException.NO_MODIFICATION_ALLOWED_ERR;
+ throw (window.DOMException);
+ });
+ Widget.__defineGetter__(key, function () {
+ return value;
+ });
+ } catch (err) {
+ try {
+ //
+ // cant use __defineGetter__ so try to setup for IE9
+ //
+ Object.defineProperty(Widget, key, {
+ set: function set() {
+ window.DOMException.code =
DOMException.NO_MODIFICATION_ALLOWED_ERR;
+ throw (window.DOMException);
+ },
+ get: function get() {
+ return value;
+ }
+ });
+ } catch (err2) {
+ //
+ // catch IE8
+ //
+ eval("Widget." + key + "='" + value + "';");
+ }
+ }
+ },
+
+ /**
+ * Set the preferences collection for this widget instance
+ * @param map the map of preference items, consisting of key, value and
readonly flag
+ */
+ setPrefs: function (map) {
+ this.preferences = WidgetPreferences;
+ this.preferences.prefs = {};
+ for (var i in map) {
+ var obj = map[i];
+ var key = obj["dkey"];
+
+ //
+ // Define getters and setters for each preference item
+ //
+ this.preferences.createAccessorMethods(key, obj["dvalue"], obj);
+
+ //
+ // Add the item to preferences collection
+ //
+ eval("this.preferences.prefs[\"" + key + "\"]=obj;");
+ }
+ this.preferences.calcLength();
+ },
+
+ /**
+ * Persist a preference object in the server backend
+ */
+ setPreferenceForKey : function (wName, wValue) {
+ WidgetImpl.setPreferenceForKey(this.instanceid_key, wName, wValue);
+ },
+
+ /**
+ * Get the instance id key for this instance
+ */
+ getInstanceKey : function () {
+ return this.instanceid_key;
+ },
+
+ /**
+ * Get the URL for the server-side proxy
+ */
+ getProxyUrl : function () {
+ return this.proxyUrl;
+ },
+
+ /**
+ * Convert a given URL into a proxified version
+ * @param url the URL to convert
+ */
+ proxify : function (url) {
+ return this.proxyUrl + "?instanceid_key=" + this.instanceid_key +
"&url=" + url;
+ },
+
+ /**
+ * Return Widget as the object type
+ */
+ toString: function () {
+ return "[object Widget]";
+ }
+};
+//
+// Initialize the widget object
+//
+Widget.init();
+//
+// Avoid lower/uppercase confusion for the widget object
+//
+widget = Widget;
+//
+// Add widget object to the window object
+//
+window.widget = Widget;
\ No newline at end of file