...
All embedded experiences must include either a gadget or URL in order to be valid embedded experience. The data model MAY choose to include both if the service wants to provide both types of embedded experiences. Services may include any combination of the other properties based on their use cases. Here are some example data models.
URL Embedded Experience
...
XML
...
Code Block | ||||
---|---|---|---|---|
| ||||
<embed>
<url>http://example.com/ee.html</url>
</embed>
|
...
JSON
...
Code Block | ||||
---|---|---|---|---|
| ||||
{
"url": "http://example.com/ee.html"
}
|
Gadget Embedded Experience
...
XML
...
Code Block | ||||
---|---|---|---|---|
| ||||
<embed>
<gadget>http://example.com/EE_Gadget.xml</gadget>
</embed>
|
...
JSON
...
Code Block | ||||
---|---|---|---|---|
| ||||
{
"gadget": "http://example.com/EE_Gadget.xml"
}
|
Gadget And URL Embedded Experience
...
XML
...
Code Block | ||||
---|---|---|---|---|
| ||||
<embed>
<url>http://example.com/ee.html</url>
<gadget>http://example.com/EE_Gadget.xml</gadget>
</embed>
|
...
JSON
...
Code Block | ||||
---|---|---|---|---|
| ||||
{
"url": "http://example.com/ee.html",
"gadget": "http://example.com/EE_Gadget.xml"
}
|
Gadget Embedded Experience With Context
...
XML
...
Code Block | ||||
---|---|---|---|---|
| ||||
<embed>
<gadget>http://example.com/EE_Gadget.xml</gadget>
<context>
<title>Foo</title>
<id>1234</id>
</context>
</embed>
|
...
JSON
...
Code Block | ||||
---|---|---|---|---|
| ||||
{
"gadget": "http://example.com/EE_Gadget.xml",
"context": {
"title": "Foo",
"id": "1234"
}
}
|
Gadget And URL Embedded Experience With Context And Preview Image
...
XML
...
Code Block | ||||
---|---|---|---|---|
| ||||
<embed>
<url>http://example.com/ee.html</url>
<gadget>http://example.com/EE_Gadget.xml</gadget>
<context>
<title>Foo</title>
<id>1234</id>
</context>
<previewImage>http://example.com/EE_Preview.png</previewImage>
</embed>
|
...
JSON
...
Code Block | ||||
---|---|---|---|---|
| ||||
{
"url": "http://example.com/ee.html",
"gadget": "http://example.com/EE_Gadget.xml",
"context": {
"title": "Foo",
"id": "1234"
}
"previewImage": "http://example.com/EE_Preview.png"
}
|
How Do I Get Started With Developing My Embedded Experience?
Now that you know what an embedded experience is and we know what makes up an embedded experience, we are ready to get started building an embedded experience. In this tutorial we will build a gadget based embedded experience since that is the more complex and interesting type of embedded experience. If your interested in building a URL embedded experience its a simple as building a web page and placing the URL to that page in the data model you want to use. See below on how to embed the data model in different types of mediums.
For this tutorial we will build an embedded experience gadget which will embed a YouTube video in both emails and activity streams. The first thing we need to do is decide on the what our data model is going to look like. For this tutorial we will keep it fairly simple. Lets say we want to embed the URL to this OpenSocial tutorial video, http://www.youtube.com/watch?v=9gW2YVBrNVA. As most people know, you can already embed YouTube videos into any HTML page using this HTML.
Code Block | ||||
---|---|---|---|---|
| ||||
<object width=480" height="285">
<param name="movie" value="http://www.youtube.com/v/9gW2YVBrNVA"></param>
<param name="allowFullScreen" value="true"></param>
<param name="allowscriptaccess" value="always"></param>
<embed src="http://www.youtube.com/v/9gW2YVBrNVA" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="285">
</embed>
</object>
|
We could just place this HTML in the gadget use that gadget. Lets take a look at what an embedded experience gadget and data model would look like using this HTML.
...
Data Model
...
Code Block | ||||
---|---|---|---|---|
| ||||
{
"gadget": "http://example.com/YouTube_EE.xml"
}
|
...
Gadget XML
...
Code Block | ||||
---|---|---|---|---|
| ||||
<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="YouTube Player" description="YouTube Player Using Embedded Experiences" height="400" width="700"/>
<Content type="html">
<![CDATA[
<object width=480" height="285">
<param name="movie" value="http://www.youtube.com/v/9gW2YVBrNVA"></param>
<param name="allowFullScreen" value="true"></param>
<param name="allowscriptaccess" value="always"></param>
<embed src="http://www.youtube.com/v/9gW2YVBrNVA" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="285">
</embed>
</object>
]]>
</Content>
</Module>
|
However the problem with this embedded experience is that it is very static. What if we wanted to create an embedded experience for a different YouTube video. With our current embedded experience we would have to build a new gadget. The embedded experiences data model can solve this problem.
Using The Embedded Experiences Context
The context property in the embedded experiences data model can be used to make a more abstract embedded experiences gadget. Really the only thing we would need to change in the gadget above is the video id in the URLs in the param and embed tags. We can also build that HTML dynamically in the gadget itself once we know the YouTube video id. To do this we can change our data model so the context property includes the video id. Here is what our new data model will look like.
Code Block | ||||
---|---|---|---|---|
| ||||
{
"gadget": "http://example.com/YouTube_EE.xml",
"context": "9gW2YVBrNVA"
}
|
Our gadget however needs to be able to get the context information from the data model. This is where we can take advantage of the embedded experiences feature in the OpenSocial specification. Here is the new gadget XML.
Code Block | ||||
---|---|---|---|---|
| ||||
<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="YouTube Player" description="YouTube Player Using Embedded Experiences" height="400" width="700">
<Require feature="embedded-experiences"></Require>
<Require feature="dynamic-height"></Require>
</ModulePrefs>
<Content type="html">
<![CDATA[
<script type="text/javascript">
function showPlayer(context){
document.getElementById("player").innerHTML = '<object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/' + context + '?fs=1&hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/' + context + '?fs=1&hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object>';
gadgets.window.adjustHeight();
}
function initData() {
opensocial.data.getDataContext().registerListener('org.opensocial.ee.context', function(key){
showPlayer(opensocial.data.getDataContext().getDataSet(key));
});
}
gadgets.util.registerOnLoadHandler(initData);
</script>
<div id="player">
</div>
]]>
</Content>
</Module>
|
The first difference you will notice is that we have included two features in the ModulePrefs section of the gadget XML. The dynamic-height feature is used to adjust the height of the gadget once the video has been placed in the gadget. The more important feature is the embedded-experiences feature. This is the feature which will get the context information and make it available to the gadget. The context information from the data model is placed in the data context object, under the key org.opensocial.ee.context. You can access information from the data context object by using the data context APIs to get the data set for the embedded experiences key.
Notice in the content section of the gadget we have also removed all the HTML from our previous embedded experience gadget and now just have a script tag and a div tag. If we take a look at the contents of the script tag you will see two functions and a call to register an on load handler to kick everything off. The on load handler we register, initData, will be called once the gadget has been loaded. When initData is called we register a listener for the key org.opensocial.ee.context on the data context object. When the data set attached to org.opensocial.ee.context is changed our listener function, will be called, and can retreive the data set for that key. In the embedded experiences case the data set is the context information from the data model. The data set, or context information, can be retrieved by calling opensocial.data.getDataContext().getDataSet('org.opensocial.ee.context'). In our example embedded experience gadget we call showPlayer with the context information, which in our data model is the YouTube video id. The showPlayer function sets the inner HTML of the div element with the id player to the HTML to show the YouTube video.
The above embedded experience gadget can now be used to provide an embedded experience for any YouTube video. All we have to do as the service is change the context informaiton in our data model. This is much simpler than having to have a separate gadget for every YouTube video.
Embedding Our Gadget In An Email
Now that we know what our data model is going to look like and we have written our gadget we are ready to start providing embedded experiences. One of the most interesting use cases is to provide a richer experience in email. The majority of services today send static HTML emails based on a standard called MIME. This is a step above plain text emails but, the HTML has its own limitations as well. Embedded experiences has taken advantage of the MIME email spec to allow applications to send embedded experiences in MIME emails as well. If the application aleady is sending MIME emails the changes will be minimal and it will not effect users who are using mail clients which don't support embedded experiences.
You can add an embedded experience to a MIME email by simply adding an additional MIME part to the MIME email. Lets say our application sends this MIME email today.
Code Block |
---|
From: notifications@example.com
To: johndoe@example.com
Subject: Check Out This YouTube Video
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="XXXXboundary text"
Check out this YouTube video.
http://www.youtube.com/watch?v=9gW2YVBrNVA
--XXXXboundary text
Content-Type: text/plain
Check out this YouTube video.
http://www.youtube.com/watch?v=9gW2YVBrNVA
--XXXXboundary text
Content-Type: text/html
Check out this <a href="http://www.youtube.com/watch?v=9gW2YVBrNVA">YouTube video</a>.
|
This is a pretty standard multipart/alternative MIME email. It has two parts, a text/plain and a text/html part. This is pretty similar to most MIME emails which applications send today. Like I said above, to make this an embedded experience email we just have to add another part.
Code Block |
---|
From: notifications@example.com
To: johndoe@example.com
Subject: Check Out This YouTube Video
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="XXXXboundary text"
Check out this YouTube video.
http://www.youtube.com/watch?v=9gW2YVBrNVA
--XXXXboundary text
Content-Type: text/plain
Check out this YouTube video.
http://www.youtube.com/watch?v=9gW2YVBrNVA
--XXXXboundary text
Content-Type: text/html
Check out this <a href="http://www.youtube.com/watch?v=9gW2YVBrNVA">YouTube video</a>.
--XXXXboundary text
Content-Type: application/embed+json
{
"gadget" : "http://example.com/YouTube_EE.xml",
"context" : 123
}
|
In this example you can see we have added another part with the content type of application/embed+json. This is a MIME type the OpenSocial foundation has registered with IANA to represent embedded experiences. In addition to the JSON MIME type the OpenSocial foundation has also registered applicaiton/embed+xml for the XML data model. The content of the MIME part is just our embedded experiences data model. When email clients which support embedded experiences, receive this email they will be looking for a MIME part with the type application/embed+json or application/embed+xml, and if they find it they can choose to render the embedded experience. If a client which does not support embedded experiences receives this email they will choose to render whatever other part they support, most likely the text/html part.
Embedding Our Gadget In An Activity In An Activity Stream
OpenSocial 2.0 supports the ActivityStreams 1.0 specification. OpenSocial also has defined a namespace extension to the ActivityStreams spec which contains OpenSocial specific concepts.