You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by jo...@apache.org on 2008/01/03 02:20:37 UTC

svn commit: r608302 [3/3] - in /incubator/shindig/trunk: java/gadgets/ java/gadgets/src/main/java/org/apache/shindig/gadgets/ java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ java/gadgets/src/main/java/org/apache/shindig/util/ java/gadgets/s...

Added: incubator/shindig/trunk/javascript/gadgets/prefs.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/gadgets/prefs.js?rev=608302&view=auto
==============================================================================
--- incubator/shindig/trunk/javascript/gadgets/prefs.js (added)
+++ incubator/shindig/trunk/javascript/gadgets/prefs.js Wed Jan  2 17:20:35 2008
@@ -0,0 +1,363 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Provides access to user prefs, module dimensions, and messages.
+ *
+ * Clients can access their preferences by constructing an instance of
+ * gadgets.Prefs and passing in their module id.  Example:
+ *
+ *   var prefs = new gadgets.Prefs();
+ *   var name = prefs.getString("name");
+ *   var lang = prefs.getLang();
+ *
+ * Modules with type=url can also use this library to parse arguments passed
+ * by URL, but this is not the common case:
+ *
+ *   <script src="http://apache.org/shindig/prefs.js"></script>
+ *   <script>
+ *   gadgets.Prefs.parseUrl();
+ *   var prefs = new gadgets.Prefs();
+ *   var name = prefs.getString("name");
+ *   </script>
+ */
+
+var gadgets = gadgets || {};
+
+/**
+ * Stores preferences for the default shindig implementation.
+ * @private
+ */
+gadgets.PrefStore_ = function() {
+  var modules = {};
+
+  /**
+   * Returns the module named by moduleId
+   * @param {Number | String} moduleId The module id to fetch.
+   * @return {Object} An object containing module data.
+   */
+  function getModuleData(moduleId) {
+    if (!modules[moduleId]) {
+      modules[moduleId] = {
+        prefs:{},
+        msgs:{},
+        language:"all",
+        country:"all"
+      };
+    }
+    return modules[moduleId];
+  }
+
+  /**
+   * Adds a new user preference to the stored set for the given module id.
+   *
+   * @param {Number | String} moduleId The module id to add the pref for.
+   * @param {String} key The key to add. May be an object where keys = key and
+   *     values = value.
+   * @param {String} value The value for the key. Optional.
+   */
+  function setPref(moduleId, key, value) {
+    var module = getModuleData(moduleId);
+    if (typeof key !== "string") {
+      for (var i in key) {
+        module.prefs[i] = key[i];
+      }
+    } else {
+      module.prefs[key] = value;
+    }
+  }
+
+  /**
+   * Adds a new message to the stored set for the given module id.
+   *
+   * @param {Number | String} moduleId The module id to add the pref for.
+   * @param {String | Object} key The key to add. May be an object where keys =
+   *     key and values = value.
+   * @param {String} value The value for the key. Optional.
+   */
+  function setMsg(moduleId, key, value) {
+    var module = getModuleData(moduleId);
+    if (typeof key !== "string") {
+      for (var i in key) {
+        module.msgs[i] = key[i];
+      }
+    } else {
+      module.msgs[key] = value;
+    }
+  }
+
+  var defaultModuleId = 0;
+
+  /**
+   * @param {String | Number} moduleId The module id to set as default.
+   */
+  function setDefaultModuleId(moduleId) {
+    defaultModuleId = moduleId;
+  }
+
+  /**
+   * @return {String | Number} The default module id.
+   */
+  function getDefaultModuleId() {
+    return defaultModuleId;
+  }
+
+  /**
+   * @param {Number | String} moduleId The module id to set the language for.
+   * @param {String} language The language to use.
+   */
+  function setLanguage(moduleId, language) {
+    getModuleData(moduleId).language = language;
+  }
+
+  /**
+   * Sets the default country for this module id.
+   */
+  function setCountry(moduleId, country) {
+    getModuleData(moduleId).country = country;
+  }
+
+  // Export public API.
+  return {
+    setPref:setPref,
+    setMsg:setMsg,
+    setCountry:setCountry,
+    setLanguage:setLanguage,
+    getModuleData:getModuleData,
+    setDefaultModuleId:setDefaultModuleId,
+    getDefaultModuleId:getDefaultModuleId
+  };
+}();
+
+/**
+ * @constructor
+ * @param {String | Number} moduleId The module id to create prefs for.
+ */
+gadgets.Prefs = function(moduleId) {
+  if (typeof moduleId === "undefined") {
+    this.moduleId_ = gadgets.PrefStore_.getDefaultModuleId();
+  } else {
+    this.moduleId_ = moduleId;
+  }
+  this.data_ = gadgets.PrefStore_.getModuleData(this.moduleId_);
+  // This is used to eliminate one hash table lookup per value fetched.
+  this.prefs_ = this.data_.prefs;
+  this.msgs_ = this.data_.msgs;
+};
+
+/**
+ * Static pref parser. Parses all parameters from the url and stores them
+ * for later use when creating a new gadgets.Prefs object.
+ * You should only ever call this if you are a type=url gadget.
+ */
+gadgets.Prefs.parseUrl = function(moduleId) {
+  var prefs = {};
+  var msgs = {};
+  var country = "all";
+  var language = "all";
+  if (gadgets.Util) {
+    var params = gadgets.Util.getUrlParameters();
+    for (var i in params) {
+      if (i.indexOf("up_") === 0 && i.length > 3) {
+        prefs[i.substr(3)] = String(params[i]);
+      } else if (i.indexOf("msg_") === 0 && i.length > 4) {
+        msgs[i.substr(4)] = String(params[i]);
+      } else if (i === "country") {
+        country = params[i];
+      } else if (i === "lang") {
+        language = params[i];
+      } else if (i === "mid") {
+        moduleId = params[i];
+      }
+    }
+  }
+  gadgets.PrefStore_.setDefaultModuleId(moduleId);
+  gadgets.PrefStore_.setPref(moduleId, prefs);
+  gadgets.PrefStore_.setMsg(moduleId, msgs);
+  gadgets.PrefStore_.setLanguage(moduleId, language);
+  gadgets.PrefStore_.setCountry(moduleId, country);
+};
+
+/**
+ * Internal helper for pref fetching.
+ * @param {String} key The key to fetch.
+ * @return {String}
+ */
+gadgets.Prefs.prototype.getPref_ = function(key) {
+  var val = this.prefs_[key];
+  return typeof val === "undefined" ? null : val;
+}
+
+/**
+ * Retrieves the named preference as a string.
+ * @param {String} key The preference to fetch.
+ * @return {String} The preference. If not set, an empty string.
+ */
+gadgets.Prefs.prototype.getString = function(key) {
+  var val = this.getPref_(key);
+  return val === null ? "" : val;
+};
+
+/**
+ * Retrieves the named preference as an integer.
+ * @param {String} key The preference to fetch.
+ * @return {Number} The preference. If not set, 0.
+ */
+gadgets.Prefs.prototype.getInt = function(key) {
+  var val = parseInt(this.getPref_(key), 10);
+  return isNaN(val) ? 0 : val;
+};
+
+/**
+ * Retrieve the named preference as a floating point value.
+ * @param {String} key The preference to fetch.
+ * @return {Number} The preference. If not set, 0.
+ */
+gadgets.Prefs.prototype.getFloat = function(key) {
+  var val = parseFloat(this.getPref_(key));
+  return isNaN(val) ? 0 : val;
+};
+
+/**
+ * Retrieves the named preference as a boolean.
+ * @param {String} key The preference to fetch.
+ * @return {Boolean} The preference. If not set, false.
+ */
+gadgets.Prefs.prototype.getBool = function(key) {
+  var val = this.getPref_(key);
+  if (val !== null) {
+    return val === "true" || val === true || !!parseInt(val, 10);
+  }
+  return false;
+};
+
+/**
+ * Stores a preference.
+ * @param {String | Object} key The pref to store.
+ * @param {String} val The values to store.
+ */
+gadgets.Prefs.prototype.set = function(key, value) {
+  throw new Error("setprefs feature required to make this call.");
+};
+
+/**
+ * Retrieves the named preference as an array.
+ * @param {String} key The preference to fetch.
+ * @return {Array.<String>} The preference. If not set, an empty array.
+ *     UserPref values that were not declared as lists will be treated as
+ *     1 element arrays.
+ */
+gadgets.Prefs.prototype.getArray = function(key) {
+  var val = this.getPref_(key);
+  if (val !== null) {
+    var arr = val.split("|");
+    // Decode pipe characters.
+    for (var i = 0, j = arr.length; i < j; ++i) {
+      arr[i] = arr[i].replace(/%7C/g, "|");
+    }
+    return arr;
+  }
+  return [];
+};
+
+/**
+ * Stores a preference from the given list.
+ * @param {String} key The pref to store.
+ * @param {Array.<String | Number>} val The values to store.
+ */
+gadgets.Prefs.prototype.setArray = function(key, val) {
+  throw new Error("setprefs feature required to make this call.");
+};
+
+/**
+ * Fetches an unformatted message.
+ * @param {String} key The message to fetch
+ * @return {String} The message.
+ */
+gadgets.Prefs.prototype.getMsg = function(key) {
+  var val = this.msgs_[key];
+  return typeof val === "undefined" ? "" : val;
+};
+
+/**
+ * The regex pulls out the text before and after the positional argument
+ * and digs down for a possible example value in case no actual value
+ * was provided.  It is used by the function getMsgFormatted.
+ *
+ * Example: "Foo <ph name="number"><ex>bar</ex>%1</ph> baz."
+ * 0 = "Foo <ph name="number"><ex>bar</ex>%1</ph> baz." : match for the
+ *     whole regex.
+ *
+ * 1 = "Foo " : matches first (.*) in regex
+ *
+ * 2 = "<ph name="number"><ex>bar</ex>%1</ph>" : matches
+ *     (\<ph.*?\>\s*(\<ex\>(.*?)\<\/ex\>)?\s*%1\s*\<\/ph\>) in regex
+ * 3 = "<ex>bar</ex>" : matches (\<ex\>(.*?)\<\/ex\>)? in regex, since it
+ *     is an optional param it may have the value "undefined"
+ * 4 = "bar" : matches (.*?) in regex (it is a non-greedy regex)
+ *     if 3=undefined then 4 = "undefined".
+ *
+ * 5 = " baz." : matches final (.*) in regex
+ *
+ * TODO: this may need to be a single line even though it's > 80 characters
+ * because some browsers may not properly interepret the line continuation.
+ */
+gadgets.Prefs.MESSAGE_SUBST_REGEX =
+    /(.*)(\<ph.*?\>\s*(\<ex\>(.*?)\<\/ex\>)?\s*%1\s*\<\/ph\>)(.*)/;
+
+/**
+ * Returns a message value with the positional argument opt_subst in place if
+ * it is provided or the provided example value if it is not, or the empty
+ * string if the message is not found.
+ * Eventually we may provide controls to return different default messages.
+ *
+ * @param {String} key The message to fetch.
+ * @param {String} subst ????
+ * @return {String} The formatted string.
+ */
+gadgets.Prefs.prototype.getMsgFormatted = function(key, opt_subst) {
+  var val = this.getMsg(key);
+
+  var result = val.match(gadgets.Prefs.MESSAGE_SUBST_REGEX);
+  // Allows string that should be getMsg to also call getMsgFormatted
+  if (!result || !result[0]) {
+    return val;
+  }
+  if (typeof opt_subst === "undefined") {
+    var sub = result[4] || "";
+    return result[1] + sub + result[5];
+  }
+  return result[1] + opt_subst + result[5];
+};
+
+/**
+ * @return {String} The country for this module instance.
+ */
+gadgets.Prefs.prototype.getCountry = function() {
+  return this.data_.country;
+};
+
+/**
+ * @return {String} The language for this module instance.
+ */
+gadgets.Prefs.prototype.getLang = function() {
+  return this.data_.language;
+};
+
+/**
+ * @return {String | Number} The module id for this module instance.
+ */
+gadgets.Prefs.prototype.getModuleId = function() {
+  return this.moduleId_;
+};

Added: incubator/shindig/trunk/javascript/gadgets/setprefs.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/gadgets/setprefs.js?rev=608302&view=auto
==============================================================================
--- incubator/shindig/trunk/javascript/gadgets/setprefs.js (added)
+++ incubator/shindig/trunk/javascript/gadgets/setprefs.js Wed Jan  2 17:20:35 2008
@@ -0,0 +1,59 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ /* This library augments gadgets.Prefs with functionality to store prefs
+  * dynamically.
+  */
+
+/**
+ * Stores a preference.
+ * @param {String | Object} key The pref to store.
+ * @param {String} val The values to store.
+ */
+gadgets.Prefs.prototype.set = function(key, value) {
+  if (arguments.length > 2) {
+    // For backwards compatibility. This can take the form:
+    // prefs.set(key0, value0, key1, value1, key2, value2);
+
+    // prefs.set({key0: value0, key1: value1, key2: value2});
+    var obj = {};
+    for (var i = 0, j = arguments.length; i < j; i += 2) {
+      obj[arguments[i]] = arguments[i + 1];
+    }
+    gadgets.PrefStore_.setPref(this.moduleId_, obj);
+  } else {
+    gadgets.PrefStore_.setPref(this.moduleId_, key, value);
+  }
+  // TODO: Update user pref store somehow.
+};
+
+/**
+ * Stores a preference from the given list.
+ * @param {String} key The pref to store.
+ * @param {Array.<String | Number>} val The values to store.
+ */
+gadgets.Prefs.prototype.setArray = function(key, val) {
+  if (!val.length || !val.join) {
+    throw new Error("Value is not an array.");
+  }
+
+  // We must escape pipe (|) characters to ensure that decoding in
+  // getArray actually works properly.
+  for (var i = 0, j = val.length; i < j; ++i) {
+    val[i] = val[i].replace(/\|/g, "%7C");
+  }
+  gadgets.PrefStore_.setPref(this.moduleId_, key, val.join("|"));
+
+  // TODO: Update user pref store somehow. Where do we hook into the container?
+};
\ No newline at end of file

Added: incubator/shindig/trunk/javascript/gadgets/util.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/gadgets/util.js?rev=608302&view=auto
==============================================================================
--- incubator/shindig/trunk/javascript/gadgets/util.js (added)
+++ incubator/shindig/trunk/javascript/gadgets/util.js Wed Jan  2 17:20:35 2008
@@ -0,0 +1,130 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var gadgets = gadgets || {};
+
+/**
+ * General purpose utilities.
+ */
+gadgets.Util = function() {
+  /**
+   * Parses url parameters into an object.
+   * @return {Array.<String>} the parameters.
+   */
+  function parseUrlParams() {
+    // Get settings from url, 'hash' takes precedence over 'search' component
+    // don't use document.location.hash due to browser differences.
+    var query;
+    var l = document.location.href;
+    var queryIdx = l.indexOf("?");
+    var hashIdx = l.indexOf("#");
+    if (hashIdx === -1) {
+      query = l.substr(queryIdx + 1);
+    } else {
+      // essentially replaces "#" with "&"
+      query = [l.substr(queryIdx + 1, hashIdx - queryIdx - 1), "&",
+               l.substr(hashIdx + 1)].join("");
+    }
+    return query.split("&");
+  }
+
+  var parameters = null;
+
+  /**
+   * @return {Object} Parameters passed into the query string.
+   */
+  function getUrlParameters() {
+    if (parameters !== null) {
+      return parameters;
+    }
+    parameters = {};
+    var pairs = parseUrlParams();
+    var unesc = window.decodeURIComponent ? decodeURIComponent : unescape;
+    for (var i = 0, j = pairs.length; i < j; ++i) {
+      var pos = pairs[i].indexOf('=');
+      if (pos === -1) {
+        continue;
+      }
+      var argName = pairs[i].substring(0, pos);
+      var value = pairs[i].substring(pos + 1);
+      // difference to IG_Prefs, is that args doesn't replace spaces in argname:
+      // unclear on if it should do: argname = argname.replace(/\+/g, " ");
+      value = value.replace(/\+/g, " ");
+      parameters[argName] = unesc(value);
+    }
+    return parameters;
+  }
+
+  /**
+   * Creates a closure which is suitable for passing as a callback.
+   *
+   * @param {Object} scope The execution scope. May be null if there is no
+   *     need to associate a specific instance of an object with this callback.
+   * @param {Function} callback The callback to invoke when this is run.
+   *     any arguments passed in will be passed after your initial arguments.
+   * @param {Object} var_args Any number of arguments may be passed to the
+   *     callback. They will be received in the order they are passed in.
+   */
+  function makeClosure(scope, callback, var_args) {
+    // arguments isn't a real array, so we copy it into one.
+    var tmpArgs = [];
+    for (var i = 2, j = arguments.length; i < j; ++i) {
+     tmpArgs.push(arguments[i]);
+    }
+    return function() {
+      // append new arguments.
+      for (var i = 0, j = arguments.length; i < j; ++i) {
+        tmpArgs.push(arguments[i]);
+      }
+      callback.apply(scope, tmpArgs);
+    };
+  }
+
+  var features = {};
+
+  /**
+   * @param {String} feature The feature to get parameters for.
+   * @return {Object} The parameters for the given feature, or null.
+   */
+  function getFeatureParameters(feature) {
+    return typeof features[feature] === "undefined" ? null : features[feature];
+  }
+
+  /**
+   * @param {String} feature The feature to test for.
+   * @return {Boolean} True if the feature is supported.
+   */
+  function hasFeature(feature) {
+    return typeof features[feature] === "undefined";
+  }
+
+  /**
+   *  @param {Object} featureData The features that are supported, and
+   *    their parameters.
+   */
+  function init(featureData) {
+    features = featureData;
+  }
+
+  // Export public API.
+  return {
+    getUrlParameters: getUrlParameters,
+    getFeatureParameters: getFeatureParameters,
+    hasFeature: hasFeature,
+    makeClosure: makeClosure,
+    init: init
+  };
+}();
+
+// TODO: Check for any other commonly used aliases