Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 13 Next »

Background

Dojo (pre 1.7) has issues working correctly in an open social gadget because of the way code is loaded.

There are 2 ways to load code in an open social gadget:

  1. Script tag injection
  2. XHR requests

In order to make XHR requests in an open social gadget, you must first have a fully built url, and then pass that url to a makeRequest or osapi.http api which will fetch the url through a proxy. Script tag injection does not suffer from the same origin limitations as xhr requests do, and thus do not need to make use of a proxy.

Dojo 1.7+ uses the script injection method of code loading, so it is recommended that gadgets use this version.

Prior versions(before 1.7) of dojo can be made to load code in the same way. Dojo will need to be built to use the cross domain (xdomain) loader. The xdomain loader is not the normal loader, so existing code could potentially have unexpected issues.

In either case, it should be noted that dojo's xhr module will not work well in a gadget environment and some tweaking is required to get it to work transparently. An example of piping dojo's xhr requests through osapi is shown below.

Examples

License for examples
Copyright 2012 OpenSocial Foundation

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.
Simple dojo 1.4.3 gadget
<Module>
  <ModulePrefs title="Simple dojo 1.4.3 gadget" height="300">
  </ModulePrefs>

  <Content type="html"><![CDATA[
    <body class="tundra">
      <link rel="stylesheet" href="http://archive.dojotoolkit.org/cdn/1.4.3-cdn/google/1.4.3/dijit/themes/tundra/tundra.css" />
      <script src="http://archive.dojotoolkit.org/cdn/1.4.3-cdn/google/1.4.3/dojo/dojo.xd.js"
        djConfig="baseUrl: 'http://archive.dojotoolkit.org/cdn/1.4.3-cdn/google/1.4.3/dojo', parseOnLoad: true">
      </script>
      <script>
        dojo.require("dijit.dijit");
        dojo.require("dijit.Calendar");
      </script>
      <div dojoType="dijit.Calendar" 
        data-dojo-props="onChange:function(){dojo.byId('formatted').innerHTML=dojo.date.locale.format(arguments[0], {formatLength: 'full', selector:'date'})}">
      </div>
      <p id="formatted"></p>
    </body>
  ]]></Content>
</Module>
Simple dojo 1.7 gadget
<Module>
  <ModulePrefs title="Simple dojo 1.7 gadget" height="300">
  </ModulePrefs>

  <Content type="html"><![CDATA[
    <body class="tundra">
      <link rel="stylesheet" href="http://downloads.dojotoolkit.org/release-1.7.1/dojo-release-1.7.1/dijit/themes/tundra/tundra.css" />
      <script src="http://downloads.dojotoolkit.org/release-1.7.1/dojo-release-1.7.1/dojo/dojo.js"
        data-dojo-config="async: true, baseUrl: 'http://downloads.dojotoolkit.org/release-1.7.1/dojo-release-1.7.1/dojo', parseOnLoad: true, deps: ['dojo/parser','dijit/Calendar']">
      </script>
      <div data-dojo-type="dijit.Calendar" 
        data-dojo-props="onChange:function(){dojo.byId('formatted').innerHTML=dojo.date.locale.format(arguments[0], {formatLength: 'full', selector:'date'})}">
      </div>
      <p id="formatted"></p>
    </body>
  ]]></Content>
</Module>
Simple dojo 1.8 gadget
<Module>
  <ModulePrefs title="Simple dojo 1.8 gadget" height="300">
    <!-- 
      Dojo 1.8 appears to have some cdn detection and it really wants to find
      the dojo script tag, so we need to tell the gadget not to rewrite it
    -->
    <Optional feature="content-rewrite">
      <Param name="exclude-url">//ajax.googleapis.com/ajax/libs/dojo/1.8.0/dojo/dojo.js</Param>
      <Param name="exclude-url">//ajax.googleapis.com/ajax/libs/dojo/1.8.0/dijit/themes/tundra/tundra.css</Param>
    </Optional>
  </ModulePrefs>

  <Content type="html"><![CDATA[
    <body class="tundra">
      <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/dojo/1.8.0/dijit/themes/tundra/tundra.css" />
      <script>
        dojoConfig = {
          async: true, 
          deps: ['dojo/parser', 'dijit/Calendar'],
          parseOnLoad: true
        };
      </script>
      <script src="//ajax.googleapis.com/ajax/libs/dojo/1.8.0/dojo/dojo.js"
        data-dojo-config="async: true, parseOnLoad: true, deps: ['dojo/parser','dijit/Calendar']"></script>
      <div data-dojo-type="dijit.Calendar" 
        data-dojo-props="onChange:function(){dojo.byId('formatted').innerHTML=dojo.date.locale.format(arguments[0], {formatLength: 'full', selector:'date'})}">
      </div>
      <p id="formatted"></p>
    </body>
  ]]></Content>
</Module>
Dojo 1.8 xhr demo
<Module>
  <ModulePrefs title="Dojo 1.8 xhr demo" height="300">
    <Require feature="osapi" />
    <!-- 
      Dojo 1.8 appears to have some cdn detection and it really wants to find
      the dojo script tag, so we need to tell the gadget not to rewrite it
    -->
    <Optional feature="content-rewrite">
      <Param name="exclude-url">//ajax.googleapis.com/ajax/libs/dojo/1.8.0/dojo/dojo.js</Param>
      <Param name="exclude-url">//ajax.googleapis.com/ajax/libs/dojo/1.8.0/dijit/themes/tundra/tundra.css</Param>
    </Optional>
  </ModulePrefs>

  <Content type="html"><![CDATA[
    <body class="tundra">
      <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/dojo/1.8.0/dijit/themes/tundra/tundra.css" />
      <script>
        dojoConfig = {
          has: {
            'native-xhr2': false // Because our xhr wrapper doesn't have these methods.
          },
          async: true,
          deps: ['dojo/request/xhr', 'dojo/aspect', 'dojo/_base/lang', 'dojo/parser', 'dijit/form/Button'],
          callback: function(xhr, aspect, lang) {
            // Use dojo/aspect to override the dojo/request/xhr xhr factory.
            aspect.around(xhr, '_create', function(orig) {
              // Our osapi.http wrapper masquarading as an xhr object.
              // This wrapper could be stubbed out into an AMD module, but is shown here for self-containedness.
              // This implementation has not been fully tested and very well may require some modifications.
              // For demo purposes only.

              
              function wrapper(args) {
                this.readyState = this.status = 0;
                this.responseText = this.statusText = '';
              }              
              wrapper.prototype.open = function(method, url, async, user, pass) {
                if(!osapi.http) {
                  throw new Error('osapi.http not found.  Did you request the osapi feature in your gadget?');
                }
                if(user || pass) {
                  throw new Error('User and password arguments not supported in osapi.http requests.');
                } else if(!async) {
                  throw new Error('Synchronous mode not supported in osapi.http requests.');
                } else if(!method || !url) {
                  throw new Error('Invalid arguments.');
                }
                this.method = method.toLowerCase();
                this.href = url.replace(/([?&])dojo\.preventCache=[0-9]+(.)?/, function(match, g1, g2) {
                  return g1 == '?' && g2 ? g1 : '';
                });
              };              
              wrapper.prototype.send = function(data){
                if(this.method == 'post') {
                  this.data_ = data;
                }
                osapi.http[this.method]({format: 'text', href: this.href, headers: this.headers}).execute(lang.hitch(this, function(response) {
                  if(this.aborted) {
                    return;
                  }
                  
                  if(response.error) {
                    this.status = response.error.code;
                    this.statusText = response.error.message;
                  } else {
                    this.status = response.status;
                    var content = this.responseText = response.content;
                    try {
                      // dojo handles the ie use case if this is missing.
                      this.xmlDoc = new DOMParser().parseFromString(content, "text/xml");
                    } catch (error){}
                  }
                  
                  // handle response headers
                  for(var header in (response.headers || {})) {
                    var lc = header.toLowerCase();
                    if(lc != 'set-cookie' && lc != 'set-cookie2') {
                      this.respHeaders[header] = response.headers[header];
                    }
                  }
                  this.readyState = 4;
                  this.onreadystatechange();
                }));
               
                this.readyState = 1;
                this.onreadystatechange();
              };
              wrapper.prototype.setRequestHeader = function(name, value) {
                if(name && value) {
                  var headers = this.headers || (this.headers = {}),
                      values = headers[name] || (headers[name] = []);
                  values.push(value);
                }
              };
              wrapper.prototype.getResponseHeader = function(header) {
                return this.respHeaders[header];
              };
              wrapper.prototype.getAllResponseHeaders = function() {
                var buffer = [], i = 0, headers = this.respHeaders || {};
                for(var header in headers) {
                  if (headers.hasOwnProperty(header)) {
                    buffer[i++] = header + ': ' + headers[header];  
                  }
                }
                return buffer.join('\r\n');
              };
              wrapper.prototype.abort = function() {
                this.aborted = 1;
              };
              wrapper.prototype.onreadystatechange = function(){};
            
              // Return our xhr wrapper factory            
              return function() {
                return new wrapper(); // Overriding dojo/request/xhr._create()
              };
            });
          },
          parseOnLoad: true
        };
      </script>
      <script src="//ajax.googleapis.com/ajax/libs/dojo/1.8.0/dojo/dojo.js"></script>
      <button data-dojo-type="dijit/form/Button" type="button">Click me!
        <script type="dojo/on" data-dojo-event="click" data-dojo-args="evt">
          require(['dojo/request/xhr', 'dojo/dom'], function(xhr, dom){
            dom.byId("result2").innerHTML = '';
            xhr("http://www.google.com").then(function(data){
              dom.byId("result2").innerHTML = data;
            }, function(err){
              console.error(err);
            });
          });
        </script>
      </button>
      <div id="result2"></div>
    </body>
  ]]></Content>
</Module>
  • No labels