Document generated by Confluence on May 07, 2009 05:17 Page 1 Product : Ning Apps OpenSocial Documentation This page last changed on May 07, 2009 by ernie. Table of Contents • 1 Table of Contents • 2 Introduction • ° 2.1 About OpenSocial ° 2.2 OpenSocial on Ning ° -2.2.1 Porting from other Social Network Containers to Ning --2.2.1.1 Submitting your Ported Application to the Ning App Directory ° 2.3 Feedback • 3 Revision Log • 4 Developer Guide to Ning Apps • ° 4.1 Ning Apps Terminology ° 4.2 Anatomy of a Ning OpenSocial Application ° -4.2.1 Main Vew -4.2.2 Profile View -4.2.3 Canvas View -4.2.4 About View -4.2.5 Latest Activity module -4.2.6 The Ning App Directory ° 4.3 OpenSocial Examples ° -4.3.1 Hello, World! -4.3.2 Hello, World! in Different Views -4.3.3 UserPrefs and EnumValues -4.3.4 Sub-navigation in the Canvas View -4.3.5 Navigating Between Views and Passing Parameter Information -4.3.6 Displaying Profile Information -4.3.7 Displaying Friends' Information -4.3.8 Saving and Retrieving Persistent Data -4.3.9 Sending Messages Using requestSendMessage -4.3.10 Reading from and Writing to a Member's Latest Activity on their Profile Page via the Activity Stream -4.3.11 Accessing an External REST API via JSON -4.3.12 Accessing the OpenSocial RESTful/RPC Protocol -4.3.13 Example of a Ning OpenSocial Application: Weather Sharer -4.3.14 Ning Specific Methods --4.3.14.1 feature="ning" -4.3.14.2 Getting the Domain Prefix with ning.core.getNetworkDomain -4.3.14.3 Getting Person-Specific Information with ning.Person.Field -4.3.14.4 Getting Network Information with ning.app.getInfo -4.3.14.5 ning.core.getContainerVersion ° 4.4 Validating Signed Requests ° 4.5 Policies ° 4.6 Testing your Ning App ° -4.6.1 Adding your Application --4.6.1.1 Adding an Application by URL -4.6.1.2 Removing an Application -4.6.2 Canvas View -4.6.3 About View ° 4.7 Submitting your Application to the Ning App Directory • 5 Best Practices • ° 5.1 What You MUST Do ° 5.2 What You SHOULD Do ° 5.3 What NOT to do • 6 Feature Roadmap -What's coming next? • ° 6.1 Support Resources and References ° 6.2 Ning API Specific Resources ° 6.3 Policy Based LinksDocument generated by Confluence on May 07, 2009 05:17 Page 2 Introduction Welcome to OpenSocial on Ning! This document is designed to help developers get their OpenSocial applications up and running on the Ning platform as quickly and easily as possible. About OpenSocial The OpenSocial initiative was spearheaded by Google in the fall of 2007, and has since been adopted by a wide range of social media companies. It enables third-party applications to access member data, process friend relationships and perform network actions (such as activity feed updates) normally accessible only to a service's core features. OpenSocial on Ning With over a million social networks created on our platform to date, OpenSocial applications on Ning have access to an expansive and ever-growing audience. We're supporting a subset of OpenSocial 0.8.1 APIs and core Google Gadgets, with limited support for the legacy (iGoogle) APIs -you can find the list at our API page. If you're new to OpenSocial and would like more information about developing JavaScript applications using Google's Gadget API, click here --CodeRunner is also a fantastic resource for beginner developers, and can be used in conjunction with the many tutorials we have in this document. Porting from other Social Network Containers to Ning Ning is different from other social network containers in that members can create their own social networks on Ning that other members can join; as a result, members can freely access pages of a network outside of member profile page, and the "Main View" has been created to reflect this; the object variable "ning" has been created to get specific metadata related to a social network (See "Ning Specific Methods.") For maximum portibility, the OWNER object is the Network Creator. If you've previously created a Profile App on Ning or an OpenSocial Application on another social network container, here's a handy chart outlining the differences between Profile and Ning Apps: Profile Apps Ning Apps Primary View Profile Main Supplementary Views Supported Canvas (1), About View Profile (Optional), Canvas (Multiple), About View Who adds an application A member of a social network Network Creator of a social network Canvas view contains tabs in the navigation of social network? No Yes Activity Streams via Writes to the "Recent Activity" module on a member's specific profile page Writes to the "Recent Activity" module of the main page of a social network Alert Messaging via requestSendMessage Has the ability to message all friends of a member of a social network Has the ability to message all members of a social network via Alerts, the in-network messaging system. (Members of a network have the ability to get Alert notifications via e-mail.)Document generated by Confluence on May 07, 2009 05:17 Page 3 Submitting your Ported Application to the Ning App Directory Ning allows networks to be created about anything and we realize that some subject matter that is acceptable to one group can be offensive to other people. We are currently in the process of building more controls for Network Creators to allow particular applications available for their members; until then, all applications must be reviewed by the Ning team to make sure the content is appropriate for all members. Before you submit your application, please make sure that you have verified that the OpenSocial application has been tested properly on a social network on Ning. Please refer to the "Testing and Submitting Your Ning OpenSocial Application" section in this documentation for more information on how to test your OpenSocial Application on a network. You may also browse the Policies, Best Practices and our guides to testing your Ning App and submitting your Application to the Ning App Directory, and you can consult the Ning Developer Network at http://developer.ning.com for latest updates. Feedback We're actively looking for bug reports and enhancement suggestions to help make our OpenSocial implementation as friendly to developers as possible. Feel free to send feedback through our help center or Developer Forums. Thanks! Revision Log Date Description May 6, 2009 Official document released. Developer Guide to Ning Apps Ning Apps Terminology This document will use the following terms to describe components included in the Ning OpenSocial implementation. Term Description Network Ning allows anybody to create their own social network for anything. Each of these networks can be an OpenSocial container. Ning Apps Third party code that uses the Gadgets and OpenSocial APIs which are served on the main page of a social network. Formerly called Network Applications. Profile Apps Third party code that uses the Gadgets and OpenSocial APIs which are served on the primary page of a social network. Formerly called Profile Applications. Profile View Application when displayed as a module on Ning member profile pages. Canvas View Full page view of an Application. About View Full page view of an Application's information, including description and screenshot.Document generated by Confluence on May 07, 2009 05:17 Page 4 Activity stream Data feed that contains activities from one person. Latest Activity module The Latest Activity module displays the activity stream of a given user on his/her profile page. Main View [NEW!] Application when displayed as a module on the main page of a social network on Ning. The main view of a Ning App is viewable to all members of a social network on Ning but not to other social network containers, so it is unique to Ning only. Ning App Directory The directory where Network creators can add a Ning App to their social network, and will be accessible via the Manage menu. Profile App Directory The directory where members of a social network can add a Profile Application to their profile page. This was previously known as the Application Directory. Anatomy of a Ning OpenSocial Application An OpenSocial Application on Ning is comprised of the following parts, which combine to form a feature to complement any of the hundreds of thousands of social networks on Ning. As an Application Developer, here is a checklist of components which should be utilized, as well as an overview of the relationship between these components: 1. Main View [NEW!] 2. Profile View 3. Canvas View 4. About View 5. Latest Activity 6. The Ning App Directory Main Vew The Main View of an OpenSocial Application displays the application as a module in the center column of the main page of a social network. This view is specific to the Ning Platform and gives the Network Creator who adds the application direct access to an application's content and functionality to his or her members. This view is optional.Document generated by Confluence on May 07, 2009 05:17 Page 5 Here are the recommended dimensions: Width: 492px (Any feature less than this width will be centered in the column) Maximum height: There is currently no height restriction but will be in a future release. Profile View The primary view of a Ning App is on the main page of a social network, but the Profile View of an application gives the ability to add a profile-specific module in the profile page of every member in a social network. Installing a Ning App with a Profile View will automatically add the ProfileDocument generated by Confluence on May 07, 2009 05:17 Page 6 View component to the profile pages of all members on a social network. This view is optional. TECHNICAL NOTE: The OWNER and VIEWER objects differ between the main view and profile views --while the OWNER object in the main view belongs to the Network Creator, the OWNER object in the profile view refers to the member's profile page, similar to standard profile-based OpenSocial applications. Also note that the profile view of a Network App and a OpenSocial Application based on the profile view uses different application identifiers. As a result, if an application is installed on the profile page AND on the main page, data will not overlap. Here are the recommended dimensions: Width: 492px (Any feature less than this width will be centered in the column) Maximum height: There is currently no height restriction but will be in a future release.Document generated by Confluence on May 07, 2009 05:17 Page 7 Canvas View The Canvas View is the full-page view of an application. You can take advantage of a full page to expose more functionality than can be displayed in the Main View. The Canvas View can be accessed by clicking the 'View Application' link on the Main View. This view is required. Note that the Canvas view differs from the Canvas view in a Ning OpenSocial Profile Application in the following additional ways: • The Ning App can optionally have its own tab in the top-level navigation. Clicking on that tab displays this Canvas View. • Additionally, the application can have multiple canvas pages that can operate as closely as possible to the existing features of a social network. Applications can specify sub-navigation links that live outside the OpenSocial container that allow for navigation between the different canvas pages. Specifically to Ning, Ning Apps have the ability to include a secondary navigation structure through structure, which can emulate multiple canvas sub-pages through a parameter structure: Cannot resolve external resource into attachment. Here are the recommended dimensions: Width: 737px (Any feature less than this width will be centered in the column) Maximum height: There is no height restriction. About View The About View is your Application's information page, and allows members of the social network to view the description and screenshot of your application. In a subsequent release, we'll also include information about the developer and number of members using your application, as well as a button to add it to the viewer's profile page. Here are the recommended dimensions: Screenshot width: 502px Screenshot maximum height: 1000px Max file size: 150KB, non-transparent .gif/.jpg/.pngDocument generated by Confluence on May 07, 2009 05:17 Page 8 If a member has not added the OpenSocial Application, a member can click on the "Add to My Page" button in the upper right hand corner to add the application to their profile page:Document generated by Confluence on May 07, 2009 05:17 Page 9 Latest Activity module Your Latest Activity module shows all recent activity of members on a social network. As an Application Developer, you also have the ability to add updates relevant to your application in the Latest Activity module on the main page. This component is still under development; screen shots will be rolled out at a latter date during the beta testing. The Ning App Directory This is where Network Creators of a social networks can add Ning Apps to the main page of their social networks. Contrary to Profile Apps, the Network Creator will no longer have the ability to directly add an OpenSocial Application by URL, but developers can add an XML file manually by creating a social network development sandbox. (See the Testing Your Ning App section.) OpenSocial Examples Hello, World! (Note: Some of the tutorials and tutorial descriptions provided are based on the OpenSocial Tutorial for Orkut. Due to the open nature of OpenSocial, you may find that a lot of the Ning OpenSocial Applications that you create can easily be ported to other OpenSocial containers such as Orkut, hi5 and MySpace with very little additional development time, and vice versa.)Document generated by Confluence on May 07, 2009 05:17 Page 10 OpenSocial Applications are essentially XML files that adhere to the OpenSocial specifications. To create a quick "Hello World" application, paste the following code into the Google Gadget Editor, or an XML file: function init() { document.getElementById("handler").innerHTML = "Hello, world."; }gadgets.util.registerOnLoadHandler(function() { init(); }); ]]> You can view a live example of this on http://os.ning.com/apps/tutorials/hello-world.xml . Once the OpenSocial Application is loaded inside a container, registerOnLoadHandler is called. In this case, the function calls the Javascript init() function which writes "Hello, world." to the "handler" HTML element. A key element in this example is the use of as a parameter of the module declaration. This specifies the release of opensocial required by the module. Containers may or may not implement all possible versions of the OpenSocial API, and when they don't the member will see an error. contains the bulk of the gadget, including all of the HTML, CSS, and JavaScript (or references to such files). The content of this section should be treated like the content of the body tag on a generic HTML page. From there, you can simply save your gadget as a file in your network (through WebDav) in a new directory, OpenSocial, with the name for example helloworld.xml. You can also can develop your xml document off an external server. Once you have done that, you can add your XML file to the profile page of your social network. Detailed instructions on how to add your OpenSocial Application are listed later in this document: Testing Your Ning App. The process of editing an XML file, uploading it to a server and re-evaluating the code you just wrote can be a tedious process. Thankfully, Google has an OpenSocial Application called CodeRunner where you can cut and paste javascript code into a textbox, where the code is run client-side; this tool is pretty handly, especially with developers who are comfortable with Javascript and would just like to experiment with the more OpenSocial based methods. Due to the slightly different nature of Ning Apps, we have created an instance of the CodeRunner app that includes some Ning only properties. The file is available here: http://gadgetstore.ning.com/gadgets/coderunner/coderunner08.xml . Hello, World! in Different Views Once we understand the basic concept of the Content section and how it's used to show HTML, CSS and Javascript inside, we can expand that idea with the view attribute, used if you want to show conditional content based on if you're viewing the OpenSocial Application in the Main View, Canvas View or Profile View. This can be useful from a User Experience perspective, possibly showing less detailed information where the viewport is smaller. Document generated by Confluence on May 07, 2009 05:17 Page 11 Hello, ning.main view!
]]>
Hello, world! ]]> Hello, Profile View! ]]> Hello, Canvas View! ]]> In the following example, "Hello, Profile View!" and "Hello, Canvas View!" is shown is the Profile and Canvas Views, respectively. "Hello, world!" is displayed for the Main, Canvas and Profile Views. UserPrefs and EnumValues NOTE: This component is still under development and will be rolled out at a latter date during the beta testing. Sub-navigation in the Canvas View Cannot resolve external resource into attachment. Because of the distinct nature of Ning App, Applications can specify sub-navigation links that live outside the OpenSocial container that allow for navigation between the different canvas pages. Sub-navigation elements are specified via Ning namespaced elements in the gadget XML:
Document generated by Confluence on May 07, 2009 05:17 Page 12 Tab 1 param=tab1 Tab 2 param=tab2 link22=22 This is some HTML content in the Main View of a Ning App. ]]> key=value You can also set multiple URLParameter fields: Tab 2 param=tab2 link22=22 --> This is some HTML content in the Canvas View of a Ning App!
]]> Note that the main canvas view will returned "undefined," as no parameters were passed to the main canvas page. Navigating Between Views and Passing Parameter Information The requestNavigateTo method is used to navigate between different application views. You can pass parameter data between these views by passing appropriate data as a parameter in the previously mentioned method. The following sample code illustrates one such example:
Value One:
Value Two:
]]> For those needing to retrieve the parameters passed from the query string, the view-params object takes parameters in JSON format to be passed into applications. This is similar to the way that Orkut passes query string parameters via gadgets.util.getUrlParameters() in this URL: http://code.google.com/apis/orkut/docs/orkutdevguide.html. It is also possible to manually parse the parameters using location.href and using a string matching function or a regular expression. Displaying Profile Information Now you can begin creating the actual body of code that uses the OpenSocial API to display some useful information, such as the viewer's name and profile photo. You can fetch this data by creating an opensocial.newDataRequest object, populating it with a request to fetch the viewer (that's you), and sending the request to the server. This example uses the key opensocial.IdSpec.PersonId.VIEWER, or the enum value "VIEWER" for short -but you can also use the opensocial.IdSpec.PersonId.OWNER key. If Alice is viewing Bob's profile, then Alice is the viewer and Bob is the owner. You can access information about both users by specifying the appropriate key. To see this in action, replace the CDATA content in your gadget with the following JavaScript:Document generated by Confluence on May 07, 2009 05:17 Page 14
function response(data) { var viewer = data.get("viewer").getData(); var name = viewer.getDisplayName(); var thumb = viewer.getField(opensocial.Person.Field.THUMBNAIL_URL); var html = '
' + name; document.getElementById('dom_handle').innerHTML = html; }; function request() { var req = opensocial.newDataRequest(); //req.add(req.newFetchPersonRequest('VIEWER'), 'viewer'); var viewer = opensocial.IdSpec.PersonId.VIEWER; req.add(req.newFetchPersonRequest(viewer), 'viewer'); req.send(response); }; request(); ]]> Note that the send method within the request is asynchronous, and it takes a callback function -in our example, response -as a parameter. This callback function will be invoked when the response comes back from the server. Displaying Friends' Information This next portion of the tutorial builds on the previous, but in addition to showing your own information (as the viewer), it will describe how to fetch all of your friends and display their information within the gadget. First you need to modify your request to ask for the data about the viewer and the viewer's friends. You can batch this request for two data sets by modifying the request function like this: function request() { var params = { }; //params[opensocial.DataRequest.PeopleRequestFields.MAX] = 50; //params[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.HAS_APP; //params[opensocial.DataRequest.PeopleRequestFields.SORT_ORDER] = opensocial.DataRequest.SortOrder.NAME; var idspec = opensocial.newIdSpec({ "userId" : "VIEWER", "groupId" : "FRIENDS" }); var req = opensocial.newDataRequest(); req.add(req.newFetchPersonRequest("VIEWER"), "viewer"); req.add(req.newFetchPeopleRequest(idspec, params), "viewer_friends"); req.send(response);Document generated by Confluence on May 07, 2009 05:17 Page 15 } Note that you are adding a newFetchPeopleRequest, which will return a collection of many people, as opposed to a newFetchPersonRequest, which only returns one person. New to OpenSocial v0.8 is the IdSpec, which takes a Javascript object passing information on the type of information you'd like, whether it be the OWNER or VIEWER of the application, as well as the collection of friends for the previously mentioned objects. Check out http://code.google.com/apis/opensocial/articles/datarequests/datarequests-0.8.html for additional information about this. You can also add different parameters to the opt_params[] variable using constants from opensocial.DataRequest.PeopleRequestFields; adding the following line, for example, filters the set of VIEWER_FRIENDS to only include friends that have also added the same OpenSocial Application to your networks: params[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.HAS_APP; Now you can add code to the response method to print out your friends' profile photos and links to their profile pages. function response(data) { var viewer = data.get("viewer").getData(); var name = viewer.getDisplayName(); var thumb = viewer.getField(opensocial.Person.Field.THUMBNAIL_URL); var profile = viewer.getField(opensocial.Person.Field.PROFILE_URL); var html = '

' + '
' + name + ''; html += '
'; var viewer_friends = data.get("viewer_friends").getData(); viewer_friends.each(function(person) { var thumb = person.getField(opensocial.Person.Field.THUMBNAIL_URL); var profile = person.getField(opensocial.Person.Field.PROFILE_URL); html += '
' + '
' + ''; }); document.getElementById('dom_handle').innerHTML = html; //This function changes the height of the module. Make sure you add //
to your XML component. gadgets.window.adjustHeight(); } The object that contains your friends' data is a collection of Person objects. The above example uses the viewer_friends.each method to iterate through every Person in the collection. Now your Application will show all your friends smiling back at you! Saving and Retrieving Persistent Data Most OpenSocial calls involve building a DataRequest object, sending it to the container, and processing the response. Reading and writing Application data is included in this flow. To write a value to a specific key, create a DataRequest and add the result of calling newUpdatePersonAppDataRequest to it: var req = opensocial.newDataRequest(); req.add(req.newUpdatePersonAppDataRequest("VIEWER", "myKey", "myValue"), "set_data");Document generated by Confluence on May 07, 2009 05:17 Page 16 req.send(set_callback); The previous piece of code attempts to save the string myValue under the key of myKey, and the result is stored in set_data. It also specifies a callback function named set_callback that will get a DataResponse object indicating whether the update failed or succeeded. Note that as of this release, Ning allows a maximum of 10k of serialized data stored, including keys, values and serialization overhead. A function to handle this response could look something like this: function set_callback(response) { if (response.get("set_data").hadError()) { /* The update failed ... insert code to handle the error */} else { /* The update was successful ... continue execution */} }; If you would like more information about making DataRequest requests, please check out the OpenSocial API Developers' Guide, http://code.google.com/apis/opensocial/articles/persistence.html or the OpenSocial Data Requests reference at http://code.google.com/apis/opensocial/articles/datarequests/datarequests-0.8.html for more information. To retrieve the value of myKey you must create another DataRequest. This time, include a newFetchPersonAppDataRequest result: var req = opensocial.newDataRequest(); var idspec = opensocial.newIdSpec({'userId':'VIEWER', 'groupId':'SELF'}); req.add(req.newFetchPersonRequest(opensocial.IdSpec.PersonId.VIEWER), 'viewer'); req.add(req.newFetchPersonAppDataRequest(idspec, 'myKey'), 'get_data'); req.send(get_callback); To specify who you want to retrieve data for, you can pass any of the following as the first parameter to the newFetchPersonAppDataRequest function: • opensocial.IdSpec.PersonId.VIEWER • opensocial.IdSpec.PersonId.OWNER • opensocial.IdSpec.Group.VIEWER_FRIENDS • opensocial.IdSpec.Group.OWNER_FRIENDS The meaning of each of these values will be covered in depth later in this article. The callback specified by this function gets a DataResponse object back that contains the data that was stored, or an error message if something went wrong. A callback function implementation could look something like this: function get_callback(response) { if (response.get("get_data").hadError()) { /* the fetch failed ... insert code to handle the error */} else { var data = response.get("get_data").getData(); /* the fetch was successful ... "data" contains the app data */} }; Assuming that the request succeeded, the data variable in the function above will be assigned a JSON object with the following layout:Document generated by Confluence on May 07, 2009 05:17 Page 17 { XXXXXXXXXXXXXXXXXXX : { myKey : "" } } where XXXXXXXXXXXXXXXXXXXXX is the ID number of the user who the data belongs to. If your request specifies many people to fetch data for, then the result will look like this: { XXXXXXXXXXXXXXXXXXXX : { myKey : "" }, YYYYYYYYYYYYYYYYYYYY : { myKey : "" }, ZZZZZZZZZZZZZZZZZZZZ : { myKey : "" } } If you request multiple keys for each person, the keys will be scoped to each person's ID in the returned data object: { XXXXXXXXXXXXXXXXXXXX : { myKey1 : "", myKey2 : "" }, YYYYYYYYYYYYYYYYYYYY : { myKey1 : "", myKey2 : "" }, ZZZZZZZZZZZZZZZZZZZZ : { myKey1 : "", myKey2 : "" } } The following code snippet is a prototype that gets and saves a piece of persistent data in an OpenSocial Application. Note that the output function is a testing method used with an application such as CodeRunner, and any output function such as alert() can also work: /** * DEFAULT CODERUNNER SAMPLE CODE */function get_callback(response) { //response.get("oViewer").getData().getId(); var userid = response.get("oViewer").getData().getId(); if (response.get("get_data").hadError()) { /* the fetch failed ... insert code to handle the error */output("get callback failed"); } else { var data = response.get("get_data").getData(); output(data[userid]["myKey"]); /* the fetch was successful ... "data" contains the app data */output("get callback suceeded"); } }; function set_callback(response) { if (response.get("set_data").hadError()) { /* The update failed ... insert code to handle the error */output("set callback failed"); } else {Document generated by Confluence on May 07, 2009 05:17 Page 18 /* The update was successful ... continue execution */output("set callback succeeded"); get_request(); } }; function get_request() { var req = opensocial.newDataRequest(); req.add(req.newFetchPersonRequest("VIEWER"), "oViewer"); req.add(req.newFetchPersonAppDataRequest("VIEWER", "myKey"), "get_data"); req.send(get_callback); }; function request() { var req = opensocial.newDataRequest(); req.add(req.newUpdatePersonAppDataRequest("VIEWER", "myKey", "myValue"), "set_data"); req.send(set_callback); }; //Sets a value, and then gets that same value. request(); Sending Messages Using requestSendMessage Ning actively supports OpenSocial's requestSendMessage API, which requests Ning to send a message to a specific user or users. Rather than the application sending a standard e-mail, all messages will be directed to a section of the social network's messaging system, called alerts. A dialog box will appear for the OpenSocial Application user to confirm the message. We previously referenced Google's CodeRunner Application, a way to test OpenSocial APIs in real time. For this example, I am friends with one friend on a social network and ran the following code: var params = {}; params[opensocial.Message.Field.TYPE] = opensocial.Message.Type.EMAIL; params[opensocial.Message.Field.TITLE] = "This is my test subject"; var message = opensocial.newMessage("This is a test message with some random text.", params); //VIEWER, OWNER, VIEWER_FRIENDS, OWNER_FRIENDS or ids as a string or an array. opensocial.requestSendMessage("VIEWER_FRIENDS", message, function(resp){ if (resp.hadError()) { //put your error handling code here alert('There was an error!\nResponse code: '+resp.errorCode_+'\nResponse message: '+resp.errorMessage_); } else { //handle successful send message logic here. } }); Which brings up the following dialog box: Cannot resolve external resource into attachment. Once the message has been sent, the person who received the message will receive the message in the alerts portion of their Inbox. Cannot resolve external resource into attachment. NOTE: The requestSendMessage API has a quota of 35 invocations per member, per day. This means that a member can use the send message functionality 35 times per day across all apps. If a user enters multiple people in the 'to' field, that counts as a single invocation. The message body has a maximum character limit of 1000 characters and strips out HTML.Document generated by Confluence on May 07, 2009 05:17 Page 19 Reading from and Writing to a Member's Latest Activity on their Profile Page via the Activity Stream The following code will let an OpenSocial Application on Ning write to the Latest Activity module on a member's profile page, provided that the Application is installed on your profile page and you are viewing it: NOTE: The requestCreateActivity API has a quota of 5 invocations per member, per application, per day. This means that a member can call the functionality five times a day for each application. New Activity Feed data can only be written to a member's Profile Page, not the main page of a social network. With the exception of the tag, all HTML is stripped from the text before the API is invoked. Accessing an External REST API via JSON In order to allow your OpenSocial Application to work with data located on remote servers, you can use a function called makeRequest. makeRequest allows you to get data from remote servers, and send data to remote servers. Last.fm is an example of a site that uses web services to retrieve metadata, including artist photos. Here's an example of fetching Cher's photo from Last.fm: Accessing the OpenSocial RESTful/RPC Protocol Opensocial 0.8.1 offers a Server side API to communicate using a RESTful or RPC protocol. This component is still under development and will be rolled out at a latter date during the beta testing. Example of a Ning OpenSocial Application: Weather Sharer Cannot resolve external resource into attachment. We're now ready to combine all the things we've previously learned into one giant OpenSocial Application. Weather Sharer is a humble OpenSocial Application that allows the member to enter a zipcode, and then use a Google Weather REST API to display the weather conditions on their profile page. The Application also shows thumbnails of the member's friends who have also installed the Application, with links to their profile pages. For those who just want a direct link to the code, you will be able to find the XML and JS of this sample application available for download. Mind you, there are a lot of ways we can improve both the features and the performance of the Application, but this will hopefully inspire you to create a better OpenSocial Application. First off, we'll create a shell: ]]> Document generated by Confluence on May 07, 2009 05:17 Page 21 I'm using the YUI Javascript Library to handle all my Event Handling and DOM manipulation, but feel free to use the Javascript library you're most comfortable with. You'll also notice the addition of different feature attributes: dynamic-height, analytics, skins. These are necessary for different methods used by the Gadget object; anayltics are used with _IG_Analytics for the integration of Google Analytics, skins are used with gadget.skins to dynamically get the visual elements of a users theme. The first thing I've done is declare the user objects and set up the Settings panel. Because I'm imagining my Application to view someone else's API information and their friends list, I'll be getting the OWNER and OWNER_FRIENDS objects: getUserObjects: function() { req.add(req.newFetchPersonRequest("OWNER"), "oOwner"); //This optional parameter filters out friends that do NOT have your application installed var opt_params = []; opt_params[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.HAS_APP; req.add(req.newFetchPeopleRequest(opensocial.DataRequest.Group.OWNER_FRIENDS), "oOwnerFriends"); req.send(this.onGetUserObjects); }, onGetUserObjects: function(resp) { //No var statement -we want to store this in the class. objOwner = resp.get("oOwner").getData(); objOwnerFriends = resp.get("oOwnerFriends").getData(); console.log("onGetUserObjects -> objOwnerFriends:"); console.log(objOwnerFriends); if (objOwner.isViewer()) { //This uses YUI to create the innerHTML and attach the click handlers to the menu & button. $D.setStyle("statusbar", "display", "block"); $E.on("settings", "click", me.uiToggleSettings); $E.on("locbtn", "click", me.setUserLocation); } //This was originally in init(). We moved this here because we have to wait for objOwnerFriends to be populated. me.getUserFriends(); } The callback function is the onGetUserObjects method, which promptly stores the objects called from the getData method to the objOwner and objOwnerFriends variable inside our class, and we call objOwner.isViewer() -a way to find out if a member is viewing their own Profile Page. If so, we'll make the Settings link available for the member. We also build out our methods to save and retrieve persistent data. onSetLocation: function(resp) { console.log("onSetLocation"); if (resp.get("set_data").hadError()) { /* The update failed ... insert code to handle the error */console.log("set error"); } else { /* The update was successful ... continue execution */console.log("The update was successful ... continue execution"); }Document generated by Confluence on May 07, 2009 05:17 Page 22 }, setUserLocation: function() { //We just set a location in the Settings! We'll set the persistant data, turn the settings off, and move on with our lives. console.log("setUserLocation"); var locval = $("loc").value; req.add(req.newUpdatePersonAppDataRequest("VIEWER", "loc", locval), "set_data"); req.send(this.onSetLocation); me.uiToggleSettings(); me.getUserLocation(); }, The method setUserLocation calls the onSetLocation callback function to save a key/value pair of key "loc". We use a similar pair of methods when it's time for the member to retrieve data, through the form of getUserLocation and onGetLocation: onGetLocation: function(resp) { //Every user has a unique user id, different from the Ning ID. var userid = objOwner.getId(); if (resp.get("get_data").hadError()) { /* the fetch failed ... insert code to handle the error */alert("get callback failed"); } else { var data = resp.get("get_data").getData(); if (data[userid]) { val = data[userid]["loc"]; me.getAPIFeed(val); } else { //alert("Hmmm, looks like we couldn't find you yet. You should add your location in the settings.") $("mainpanel").innerHTML = "Hmmm, looks like we couldn't find you yet. You should add your location in the settings." } } gadgets.window.adjustHeight(); }, getUserLocation: function() { console.log("getUserLocation"); req.add(req.newFetchPersonAppDataRequest("OWNER", "loc"), "get_data"); req.send(this.onGetLocation); }, onGetLocation tries to find the information from the persitant data; if it doesn't find any appropriate data, it'll return an error -otherwise it goes to the getAPIFeed method where the information is tacked onto a XML REST API, the resulting XML parsed, and put inside the Profile Page module. onLoadAPI: function(obj) { console.log("onLoadAPI"); var objXML = obj.data; //Now we'll create a json structure that we can send as a parameter to uiDrawMainPanel. //Note that the XML structures are specific for this API. //A sample XML format is at http://www.google.com/ig/api?weather=94110 //TO DO: Fail safely.Document generated by Confluence on May 07, 2009 05:17 Page 23 var jsonInfo = { "city": objXML.getElementsByTagName("city")[0].attributes.getNamedItem("data").value, "condition": objXML.getElementsByTagName("condition")[0].attributes.getNamedItem("data").value, "temp_f": objXML.getElementsByTagName("temp_f")[0].attributes.getNamedItem("data").value, "icon": objXML.getElementsByTagName("icon")[0].attributes.getNamedItem("data").value } me.uiDrawMainPanel(jsonInfo); }, getAPIFeed: function(arg) { console.log("getAPIFeed of " + arg); var params = {}; params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM; url = "http://www.google.com/ig/api?weather=" + arg; //We're calling the XML API -the callback is onLoadAPI. gadgets.io.makeRequest(url, me.onLoadAPI, params); }, Here is what the code looks like with everything in one place: Document generated by Confluence on May 07, 2009 05:17 Page 27 ]]> Ning Specific Methods feature="ning" If you would like to use the Ning specific features, add the following line to your gadget.xml header: If you would like your application to soley run on Ning Networks, use this code instead: Running the XML above will fail with other social network containers. Additionally, you can use the hasFeature method to specifically check and implement Ning-specific code. if (gadgets.util.hasFeature("ning")) { [... you are running on ning ...] } else { [... you are *NOT* running on ning ...] }Document generated by Confluence on May 07, 2009 05:17 Page 28 Getting the Domain Prefix with ning.core.getNetworkDomain ning.core.getNetworkDomain is a Ning-specific method call which returns the domain name on which your Application has been installed. ning.core.getNetworkDomain() Running this code on "mynetwork.ning.com", returns 'mynetwork.ning.com'. Note that if the network has the domain-mapping premium service installed (e.g. mynetwork.com), the method will returned the domain-mapped name (mynetwork.com), NOT the Ning subdomain (mynetwork.ning.com). Note that using the common OpenSocial method: opensocial.getEnvironment().getDomain(); Will return "ning.com" in all cases. This is to offer developers a way to differeniate between Ning and other social containers. Getting Person-Specific Information with ning.Person.Field var env = opensocial.getEnvironment(); function response(data) { var user = data.get("req").getData(); output("User: " + user.getDisplayName()); if (env.supportsField(opensocial.Environment.ObjectType.PERSON, ning.Person.Field.CREATOR)) { var creator = user.getField(ning.Person.Field.CREATOR); output(creator ? "User is Network Creator!" : "User is not Network Creator!"); } else { output("Container does not support " + ning.Person.Field.CREATOR); } if (env.supportsField(opensocial.Environment.ObjectType.PERSON, ning.Person.Field.ADMIN)) { var creator = user.getField(ning.Person.Field.ADMIN); output(creator ? "User is Network Admin!" : "User is not Network Admin!"); } else { output("Container does not support " + ning.Person.Field.ADMIN); } gadgets.window.adjustHeight(); }; Getting Network Information with ning.app.getInfo It is possible to get a basic subset of information specific to the social network. Because this information is stored in the OpenSocial core code, the fields are retrieve through the method ning.app.Field, but through the callback function of the ning.app.getInfo method. function callback(foo) { if (foo.hadError()) { output("Error found!"); } else { for (var x in ning.app.Field) { if (ning.app.Field.hasOwnProperty(x)) {Document generated by Confluence on May 07, 2009 05:17 Page 29 if (foo.getField(ning.app.Field[x])) { output("Field " + x + ": " + foo.getField(ning.app.Field[x])); } } } } gadgets.window.adjustHeight(); }if (gadgets.util.hasFeature("ning")) { ning.app.getInfo(callback); } else { output("Not running on Ning!"); } As of this time, ning.app.Field supports the following read-only attributes: Field Description Sample Output ID 2962556 NAME The name of the social network prefix. This field will also return the prefix for networks that have domain forwarding enabled. PUBLISHED Boolean value of true BAZEL Boolean value of if this is a social network. true SEARCHABLE Boolean value that states whether the network has been indexed in social network searches. true CREATE_DATE Wed Mar 04 00:39:39 GMT 2009 UPDATED_DATE Fri Mar 06 00:49:39 GMT 2009 TAGS DOMAINS MEMBER_COUNT Contains the total number of members in the social network. 1 ning.core.getContainerVersion if (gadgets.util.hasFeature("ning")) { output("Current Container Version is " + ning.core.getContainerVersion()); } else { output("Not running on Ning!"); }gadgets.window.adjustHeight();Document generated by Confluence on May 07, 2009 05:17 Page 30 Validating Signed Requests A xoauth_signature_publickey certificate should now be available to validate signed requests using the makeRequest method, along with oauth_consumer_key, opensocial_owner_id, opensocial_viewer_id and opensocial_app_id parameters. The certificate is available at http://developer.ning.com/certificates/ning.cert. At this time, OpenSocial Applications on Ning aren't able to consume web services requiring three-legged OAuth authorization yet --that functionality will come in OpenSocial v0.8. NOTE: This component is still under development and will be rolled out at a latter date during the beta testing. In the case of the oauth_consumer_key, Ning differs from other social networking containers in that each social network on Ning maps to a unique consumer key. For example, "examplenetwork.ning.com" will be returned rather than "ning.com". Also note that domain-mapped social networks on Ning also will point to its corresponding non-mapped domain. THIS IS SUBJECT TO CHANGE IN FUTURE RELEASES. The way OpenSocial on Ning handles signed requests is based off of Orkut's methods of validating signed requests, with two major changes: • Replace Orkut's certificate with our certificate, tenatively available at http://developer.ning.com/certificates/ning.cert • Note that the variables sent are of the form opensocial_owner_id, not opensocial_ownerid. Policies • The method opensocial.getEnvironment().getDomain(); is a proven way to get the domain name of a social network. The format of the string returned is in the form of NETWORKNAME.ning.com, where NETWORKNAME is the name of your social network on Ning. Note that this is also the case for domain-mapped networks. • The requestSendMessage API has a quota of 35 invocations per member, per day. This means that a member can use the send message functionality 35 times per day across all apps. If a user enters multiple people in the 'to' field, that counts as a single invocation. • The requestCreateActivity API has a quota of 5 invocations per member, per application, per day. This means that a member can call the functionality five times a day for each application. New Activity Feed data can only be written to a member's Profile Page, not the main page of a social network. With the exception of the tag, all HTML is stripped from the text before the API is invoked. • As a Ning OpenSocial Application developer, you can access a Viewer's profile photo, profile name, profile link and friends list. All information on the platform is not exposed for privacy reasons. • On the Ning platform, a network member can have friends across many social networks on the platform. Because of this unique nature, VIEWER_FRIENDS and OWNER_FRIENDS apply to the set of friends on the specific social network where the OpenSocial Application is hosted; they are not a collection of your friends over all social networks on Ning. • If a member of Ning has a default profile name and photo and a different profile name and photo on a specific social network, the information on that network takes precedence when calling profilebased methods such as getDisplayName(). • Ning allows a maximum of 10k of serialized data stored, including keys, values and serialization overhead. • No HTML is allowed when writing to the Activity Stream. • Although OAuth is supported for Ning containers, you can not use OAuth to view a member's content at the present time. Testing your Ning App Adding your Application As an Application Developer, you can test your Ning App by creating a social network sandbox. This sandbox differs from standard social networks in that your social network offers the ability to add your XML URL manually, and is decentralized from the standard social network code. Also note that these social networks are meant for development purposes only. NOTE: Due to the private beta, we will only be granting Ning App access to a select group of social networks as well as social networks used for development purposes only. We will release full instructions to enable the ability to add a Ning App by URL after the public launch.Document generated by Confluence on May 07, 2009 05:17 Page 31 Adding an Application by URL To add your XML file, navigate to the following URL: *http://NETWORKNAME.ning.com/opensocial/ningapps/addByUrl * Note that NETWORKNAME is the name of the sandbox social network on Ning. In the text box, paste the URL of your Application XML file. The following ports for supported for hosting Network Apps: 80 (HTTP), 443 (HTTPS), 81, 8080, 8081, 8443. By default, all OpenSocial Applications will have caching enabled to ensure that all social networks on Ning are running at its speediest. That said, if you are actively developing an OpenSocial Application and would like to temporarily turn caching off, you can bypass the caching mechanism by adding "ningapp_nocache=1" to the URL of the social network profile or canvas page that you're viewing. Removing an Application You can remove a Ning App by going to the Manage Page, under Features:Document generated by Confluence on May 07, 2009 05:17 Page 32 Your Ning App will be listed as a component that can be moved to other parts of the main page of a social network, or can be removed entirely. Canvas View Click the 'View Application' link to navigate to your Application's Canvas View. About View When viewing the Canvas View of an application you do not have installed, you can click the 'About this Application' link to navigate to the About View for that application. From a developer standpoint, the About View page of an OpenSocial Application is generated by taking the title, description and screenshot image attributes of the OpenSocial XML file, located in the tag. Submitting your Application to the Ning App Directory To submit your OpenSocial Application to the Ning OpenSocial Application Directory, log in to the Ning Developer Network (http://developer.ning.com) and click on "Create an Application" on the main page, or choose "Submissions" from the navigation menu. From there, enter the XML file of your OpenSocial Application. http://remote/ss.png http://remote/tab.png http://remote/mainview.png Document generated by Confluence on May 07, 2009 05:17 Page 33 ... The tag of your XML file MUST have the following attributes filled out for an OpenSocial Application to be considered for the Directory: Attribute Description title The title of your OpenSocial Application description The string that describes the OpenSocial Application. This description appears in About View of an Application page. thumbnail URL of the Application thumbnail. This must be an 120x60 image of a piece of logo or branding of your application or your company. The image should also be on a public web site that is not blocked by robots.txt. PNG is the preferred format, though GIF and JPG are also acceptable. screenshot URL of the Application screenshot. This must be an image on a public web site that is not blocked by robots.txt. PNG is the preferred format, though GIF and JPG are also acceptable. Screenshots should be 280 pixels wide, with a maximum width of 502 pixels wide. The height of the screenshot should be the "natural" height of the gadget when it's in use, with a maximum height of 1000px. The tag is a series of Ning-only tags that are used when Network Apps are submitted to the Ning App Directory, and are used for screenshots within the directory. ning:screenshot view attribute Description Example ning.main Includes a screenshot of the main view of your Ning App. This field is required. http://remote/mainview.png profile Includes a screenshot of the profile view of your Ning App, if your Ning App includes a profile view. This field is optional. http://remote/ss.png tab Includes a screenshot of the tab view of your Ning App. This field is optional. http://remote/tab.png Once you have added the URL, your Application will be in one of the following states, listed below. Status Description Saved An Application receives this state once you successfully add the URL of your XML File. Select a Category that best matches your application,Document generated by Confluence on May 07, 2009 05:17 Page 34 and click 'Submit for Review'. Categories are chosen from a select box of the following values: Dating, Events, Food & Drink, Fun, Games, Messaging, Music, Movies & TV, News, Photos, Politics, Professional, School, Sports, Travel, Video. (This category is required.) Upon succesful submission, your application will be in a "Pending" state. Pending Once the Application is submitted and all required fields have been completed, the Application is in a "Pending" state awaiting approval from a member of the Ning Team. From there, the Application will be either "Active" or "Rejected," and an e-mail will be sent to the email address you used to log in to the Ning Developer Network. Active An "Active" Application indicates that the Application is in the Directory. Once in this state, Application Developers have the ability to delete or take their Applications offline. Rejected A "Rejected" Application indicates that the Application was rejected. Any additional notes will also be included with the status message. Removed A "Removed" Application indicates that an Application that was previously in the Directory has since been removed. Any additional notes will also be included with the status message. Best Practices Because of our committment to Ning's Network Creators, we have a thorough list of qualifications for a social network to be included into the Ning App Directory. Here are a list of best practices that we recommend: What You MUST Do • Your application must add value to networks. • Your application must be suitable for every social network on Ning. Currently, any social network on Ning has the ability to add an application from the Ning App Directory. The Ning OpenSocial team is currently looking into building functionality for Network Creators to only allow certain applications to their networks. Until then, submitted OpenSocial applications should suitable for every network on Ning; the application should not be offensive or contain adult content. • Make sure the attributes of your Application are properly filled out and images are the proper sizes. The attributes in the tag of your Application stores important meta-data about your OpenSocial Application. Some of these attributes are required, such as the title, description, thumbnail, and screenshot attributes, but if you wish you can include other pieces of meta-data such as the author and author_email fields, and the respective values will be displayed in your Application's "About View" page. The following attributes MUST BE INCLUDED for admission into the Ning App Directory: ° Title: This will be the name of your application in the Directory, Profile Page, About Page and Canvas Page. Try to keep it under 40 characters. ° Thumbnail: This should be 120x60. It is a logo that you want to associate with your application, and will be displayed in the Application Directory. The thumbnail must accurately represent the application. ° Description: The description is displayed in the Directory, and also on the About Page above the screenshot. The description should accurately describe the application, make sense, and be free of spelling and grammatical errors.Document generated by Confluence on May 07, 2009 05:17 Page 35 ° Screenshot: This can be a maximum of 502 px wide (and 1000 px high). It will be displayed on the About page below the description. The screenshot must be a clear image and should accurately represent the application. • The profile and canvas view of your application must look and work as expected. • Members that aren't logged in may be able to view your OpenSocial Application. Give them a good experience. Don't forget that both the Profile View and Canvas View of an OpenSocial Application can be viewed in a signed-out state for profile pages in public social networks. The user ID for these users are given the id of _anonymous. If your OpenSocial Application depends on member-specific information, make sure the application can fail gracefully in this condition. • If your Application allows users to download, view, listen to or otherwise access or distribute third party content dealing with copyright, follow the instructions of Section 6 of the Application Developer Terms of Service. What You SHOULD Do • Make sure your application is free of spelling and grammatical errors. • Test your OpenSocial Application in a variety of browsers. For a good variety of appropriate browsers and platforms, we recommend Yahoo's A-Grade browser chart. This means testing for IE6, IE7, the latest versions of FireFox and Safari. • Be cognizant of the different social networks that run on Ning. Ning is different from other social network containers that run OpenSocial; while most social network containers only allow members to access and edit information from their profile pages, Ning allows its members to create social networks that other members can join. With over half a million networks, there is great diversity: Some social networks pay a premium service to remove promotional links to Ning. Other social networks are geared towards education and are sensitive to content geared towards mature audiences. • Optimize your OpenSocial Application so it runs as speedy as possible. Many optimization tips used in general web development will also apply to developing your OpenSocial Applications. You may want to take a look at the OpenSocial Latency Combat Field Manual for tips on optimizing HTTP Requests, Caching and other optimization tricks. • Ensure that your OpenSocial Application is caching properly. By default, all OpenSocial Applications will have caching enabled to ensure that all social networks on Ning are running at its speediest. That said, if you are actively developing an OpenSocial Application and would like to temporarily turn caching off, you can bypass the caching mechanism by adding "ningapp_nocache=1" to the URL of the profile or canvas page that you're viewing. • Give people using your OpenSocial Application a fun and meaningful social experience. With the ability for Developers to use information such as a member's profile information and friends lists, the possibilities of creating an awesome OpenSocial Application are endless. The Social Design Best Practices document on Google has some great resources. • If appropriate, have your OpenSocial Application blend in as much as possible to a member's Profile Page. You can use gadgets.skins.getProperty to get the CSS values of the default foreground, background and link colors -use this to your advantage for the best user experience. To see an example of this in action, take a look at the Weather Sharer application, or view the page on Google Code: http://code.google.com/apis/opensocial/docs/0.8/reference/gadgets/#gadgets.skins.Property. What NOT to do • If your OpenSocial Application shares user generated content between all social networks, profile thumbnail images can NOT be displayed. • Don't require your users to download an browser/platform-specific external application. We want to be sure that all people, regardless of the browser they use, have a great experience when using an OpenSocial application. For this reason, any OpenSocial applications that have severe limitations on particular platforms or require users to download external files to install on operating systems will not be admitted into the Ning OpenSocial Application Directory. • Don't violate our Terms of Service. The Terms of Service we currently use for social networks on Ning carry over to our OpenSocial Applications, and violators will be handled appropriately. • Don't do anything that will overly annoy the people using your OpenSocial Application.Document generated by Confluence on May 07, 2009 05:17 Page 36 If you have an OpenSocial Application that runs slow scripts, requires an external download, immediately navigates away from the page or blocks the execution of the Profile Page, you'll upset the people using your Application which will make your OpenSocial application less popular. Feature Roadmap -What's coming next? We're planning to add additional features and functionality to make your experience of developing and spreading your applications even better: • About View improvements: We'll include a one-click 'Add to My Page' option, as well as member reviews and statistics about the application. • Sharing: Members will have even more ways to recommend a favorite OpenSocial Application with people on and off the Ning network. • Statistics Tracking: We plan on offering application-specific statistics for your OpenSocial Application in a future release. In the meantime, we recommend using other analytic tools to track and measure success of your application. Because we offer a subset of legacy Google Gadget APIs, one solution is to use the _IG_Analytics methods to integrate Google Analytics --you can find more information on Google Gadget's Development Tools page. Support Resources and References • OpenSocial APIs Supported by Ning • OpenSocial Tutorials v0.7_ • Gadgets XML Reference Page • OpenSocial API Blog • Social Design Best Practices • Frequently asked Questions about OpenSocial • OpenSocial Developer Forum • Orkut's Guide to Localizing OpenSocial Applications • Gadgets and Internationalization • CodeRunner -"CodeRunner is an OpenSocial gadget that allows you to execute JavaScript calls against the container that it is installed in, without having to install or update a gadget XML file. CodeRunner is great for testing code snippets and mocking out test applications." • Ning Certificate for Signed Requests -Read more about Validating Signed Requests Ning API Specific Resources • Ning Developer Network • REST API JSON Operations for Ning • XML Operations Policy Based Links • Ning Terms of Service • 3rd Party Application Policy • General Guidelines for Developing on the Ning Platform