At the time of this writing, user preferences don't function on Orkut in the same way they do on iGoogle. Also, gadgets.prefs still has a few kinks that need ironing out.
I put together this basic preference getter/setter object for use in some iWiddit applications. It uses appData requests to store and retrieve OWNER data (essentially preferences). You all are more than welcome to use all or part of this code in your own apps.
Note that this functionality should be replaced by gadgets.prefs once they get the kinks ironed out.
How to use it:
You'll want to initialize the object first, and you'll likely want to send in a callback method and default data to make sure
that subsequent method calls will actually return something other than null.
Note that the iw_prefs.init method callback argument should be used to delay your script
until this data is available, that is, the data won't be available until the init method has completed. If you try to retrieve data before the init method
completes (using .get or .getAll) you will retrieve either your default values, or a null value if you didn't set defaults.
The get and getAll methods are fairly straight forward. The only caveat is that the init method must have completed prior to calling the get method. To get
a user preference with a specific key, simply call iw_prefs.get( key ) and the correct value will be returned.
Note that the init method has already populated this
data into the iw_prefs object, so any calls to iw_prefs.get( x ) will NOT fire an AJAX request. This means you don't have to feel bad about using multiple gets sequentially.
Alternatively, if you simply wish to itterate through the appData for this OWNER, you can call iw_prefs.getAll() and you'll get back a JSON object containing matching key/value pairs. To access the data, simply use
returned_data[key]. Iteration can be accomplished by using a for.. in construct.
Setting preferences is also fairly straight forward. Using the success_callback and error_callback you should be able to split your application flow on this method depending on success/failure. Also,
the keys argument is an object, so you can send a JSON key/value map straight into here and it will update ALL of the data contained. An example JSON key/value map looks like this:
{
"preference_1": "Value_1",
"preference_2": "Value_2",
"preference_3": "Value_3"
}
Note that after the data is updated, any subsequent calls to iw_prefs.get or iw_prefs.getAll will return the correct updated data. You don't have to call the iw_prefs.init() method again.
The Methods: The iw_prefs object currently contains (4) public methods:
Finally... the code:
/*
Copyright 2008 -- www.iWiddit.com
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 iw_prefs = {
// storage for owner app data values
preference_data:null
// default values sent to init function
,default_data:null
/***** Public Methods
*
* Initialize the object, set default values
* @param :: call_back_ :: optional :: the function to call when the init process has completed
* @param :: default_data_ :: optional :: the default data object
* this is the data that is returned in case there are no user-specific values for OWNER
* e.g. fresh install
* @public
*/
,init:function( call_back_, default_data_ ){
// make sure the call_back is actually a function
var call_back = call_back_ || function(){};
// store default data
this.default_data = default_data_ || {};
// initialize preference_data to default data
this.preference_data = this.default_data;
// instantiate a DataRequest object
var reqObj = opensocial.newDataRequest();
// get the opensocial OWNER identifier
var os_owner = opensocial.DataRequest.PersonId.OWNER;
// queue a request for owner preferences
reqObj.add( reqObj.newFetchPersonAppDataRequest( os_owner, '*' ), 'owner_prefs' );
// queue a request for owner Person object
reqObj.add( reqObj.newFetchPersonRequest( os_owner ), 'app_owner' );
// store reference to 'this'
var _self = this;
// send the request
reqObj.send(
function( dat ){
_self.populate( dat, call_back );
}
);
}
/*
* Gets a preference value by key
* @param :: key :: the string preference key
* @returns :: the associated value, or default value if a preference doesn't exist
* @public
*/
,get:function( key ){
// make sure the preference object isn't null before checking properties
if( this.preference_data && this.preference_data[ key ] ) return this.preference_data[key];
// make sure the default data object isn't null before checking properties
if( this.default_data && this.default_data[ key ] ) return this.default_data[key];
// this case shouldn't occur
return null;
}
/*
* Gets the entire preference object ( all appData for the OWNER )
* @returns :: the entire appData object for the OWNER
* @public
*/
,getAll:function(){
return this.preference_data || this.default_data || {};
}
/*
* Sets a preference or list of preferences as appData for the app OWNER only if the current VIEWER == OWNER
* @param :: keys :: an object conaining the key/value pairs.
Example :: {
"var1": "value1",
"var1": "value2"
}
* @param :: success__ :: optional :: the callback method to fire upon success
* @param :: err_ :: optional :: the callback method to fire upon error
* @public
*/
,set:function( keys, success_, err_ ){
// make sure callbacks are functions
success = success_ || function(){};
err = err_ || function(){};
// get the opensocial VIEWER identifier
var os_viewer = opensocial.DataRequest.PersonId.VIEWER;
// instantiate a new data request
var reqObj = opensocial.newDataRequest();
// check for viewer object permissions
if( !opensocial.hasPermission( opensocial.Permission.VIEWER ) ) err();
// queue a request to retrieve the viewer object
reqObj.add( reqObj.newFetchPersonRequest( os_viewer ), 'current_viewer' );
// store reference to 'this'
var _self = this;
// send the request
reqObj.send(
function( dat ){
_self.verify( dat, keys, success, err );
}
);
}
/***** Private Methods
*
* Handles the returned data from the init method, stores this data for easy retrieval later on
* @param :: data_response :: the data response from the request
* @param :: call_back :: the callback function to be fired when the init process is complete
* @private
*/
,populate:function( data_response, call_back ){
// extract owner person to get object or null on failure
var owner_person = this.extract( data_response, 'app_owner' );
// extract preference_data to get object or null on failure
var preference_data = this.extract( data_response, 'owner_prefs' );
// make sure we have both owner and the preference data
if( !owner_person || !preference_data ) return;
// get person specific preferences
preference_data = preference_data[ owner_person.getId() ];
// count the number of preferences
var count = 0;
for( var x in preference_data ){
count++;
}
// use default data if preferences returned an empty object
this.preference_data = count > 0 ? preference_data : this.default_data;
// fire the callback method
call_back();
}
/*
* This is a movable method that checks a response object for errors and handles unsupported issues.
* @param :: response :: the response object
* @param :: expected_item_key :: the key of the data that is being requested
* @returns :: the data object, or null on failure
* @private
*/
,extract: function( response, expected_item_key ){
// get outer response object
var c_resp = response.get( expected_item_key );
// check for overall response error
if( typeof( c_resp.hadError ) == 'function' && c_resp.hadError() ) return;
// get responseItem object from the returned data
var rData = c_resp.getData();
// check for item specific error
if( typeof( rData.hadError ) == 'function' && rData.hadError() ) return;
// finally, return the data object
return rData;
}
/*
* Verifies that VIEWER == OWNER, then proceeds to update the appData preference for the OWNER
* @param :: data_response :: the data response containg the viewer object
* @param :: keys :: the keys object from the set method
* @param :: success :: the callback method to fire upon success
* @param :: err :: the callback method to fire upon error
* @returns :: null
* @private
*/
,verify:function( data_response, keys, success, err ){
// extract viewer from the data_response
var viewer_person = this.extract( data_response, 'current_viewer' );
// make sure viewer == owner
if( !viewer_person || !viewer_person.isOwner() ){
err();
return;
}
// create a new data request
var reqObj = opensocial.newDataRequest();
// get the opensocial VIEWER identifier
var os_viewer = opensocial.DataRequest.PersonId.VIEWER;
// itterate through the keys object and add the data update requests for VIEWER
// also update the current local preference_data object
for( var x in keys ){
reqObj.add( reqObj.newUpdatePersonAppDataRequest( os_viewer, x, keys[x] ) );
this.preference_data[x] = keys[x];
}
// send the request
reqObj.send( success );
}
}