All Downloads are FREE. Search and download functionalities are using the official Maven repository.

features.opensocial-templates.loader.js Maven / Gradle / Ivy

Go to download

Packages all the features that shindig provides into a single jar file to allow loading from the classpath

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
/**
 * @fileoverview OpenSocial Template loader. Can be used to load template
 * libraries via URL. Supports Javascript and CSS injection.
 *
 * Usage:
 *   os.Loader.loadUrl("/path/templatelib.xml", function() { doSomething(); });
 *
 * or
 *   os.Loader.loadContent(
 *       "");
 *
 * The Template Library should have the following structure:
 *
 *   
 *     
 *     
 *     
 *     
 *       function usedByAllTemplates() { ... };
 *     
 *     
 *       
 *       
 *       
 *         function usedByFooBaz() { ... };
 *       
 *     
 *   
 *
 * TODO(levik): Implement dependency support - inject JS and CSS lazily.
 * TODO(levik): More error handling and reporting of ill-formed XML files.
 */

os.Loader = {};

/**
 * A map of URLs which were already loaded.
 * @private
 */
os.Loader.loadedUrls_ = {};

/**
 * Load a remote URL via XMLHttpRequest or gadgets.io.makeRequest API
 *     when in context of a gadget.
 * @param {string} url The URL that is to be fetched.
 * @param {Function} callback Function to call once loaded.
 */
os.Loader.loadUrl = function(url, callback) {
  if (typeof(window['gadgets']) != 'undefined') {
    os.Loader.requestUrlGadgets_(url, callback);
  } else {
    os.Loader.requestUrlXHR_(url, callback);
  }
};

/**
 * Loads a Template Library from a URL via XMLHttpRequest. Once the library is
 * loaded, the callback function is called. A map is kept to prevent loading
 * the same URL twice.
 * @param {string} url The URL of the Template Library.
 * @param {Function} callback Function to call once loaded.
 * @private
 */
os.Loader.requestUrlXHR_ = function(url, callback) {
  if (os.Loader.loadedUrls_[url]) {
    window.setTimeout(callback, 0);
    return;
  }
  var req = null;
  if (typeof shindig != 'undefined' &&
      shindig.xhrwrapper &&
      shindig.xhrwrapper.createXHR) {
    req = shindig.xhrwrapper.createXHR();
  } else if (typeof XMLHttpRequest != 'undefined') {
    req = new XMLHttpRequest();
  } else {
    req = new ActiveXObject('MSXML2.XMLHTTP');
  }
  req.open('GET', url, true);
  req.onreadystatechange = function() {
    if (req.readyState == 4) {
      os.Loader.loadContent(req.responseText, url);
      callback();
    }
  };
  req.send(null);
};

/**
 * Fetch content remotely using the gadgets.io.makeRequest API.
 * @param {string} url The URL where the content is located.
 * @param {Function} callback Function to call with the data from the URL
 *     once it is fetched.
 * @private
 */
os.Loader.requestUrlGadgets_ = function(url, callback) {
  var params = {};
  var gadgets = window['gadgets'];

  if (os.Loader.loadedUrls_[url]) {
    window.setTimeout(callback, 0);
    return;
  }
  params[gadgets.io.RequestParameters.CONTENT_TYPE] =
      gadgets.io.ContentType.TEXT;
  gadgets.io.makeRequest(url, function(obj) {
    os.Loader.loadContent(obj.data, url);
    callback();
  }, params);
};

/**
 * Loads a number of Template libraries, specified by an array of URLs. Once
 * all the libraries have been loaded, the callback is called.
 * @param {Array.} urls An array of URLs of Template Libraries to load.
 * @param {Function} callback Function to call once all libraries are loaded.
 */
os.Loader.loadUrls = function(urls, callback) {
  var loadOne = function() {
    if (urls.length == 0) {
      callback();
    } else {
      os.Loader.loadUrl(urls.pop(), loadOne);
    }
  };
  loadOne();
};

/**
 * Processes the XML markup of a Template Library.
 */
os.Loader.loadContent = function(xmlString, url) {
  var doc = gadgets.jsondom.parse(xmlString, url);
  var templatesNode = doc.firstChild;
  os.Loader.processTemplatesNode(templatesNode);
  os.Loader.loadedUrls_[url] = true;
};

/**
 * Gets the function that should be used for processing a tag.
 * @param {string} tagName Name of the tag.
 * @return {?Function} The function for processing such tags.
 * @private
 */
os.Loader.getProcessorFunction_ = function(tagName) {
  // TODO(levik): This won't work once compiler does name mangling.
  return os.Loader['process' + tagName + 'Node'] || null;
};

/**
 * Processes the  node.
 */
os.Loader.processTemplatesNode = function(node) {
  // since the ie domparse does not return a general parent element
  // we check here if firstChild is really present
  if (node.firstChild) {
    node = node.firstChild;
  }
  for (var child = node; child; child = child.nextSibling) {
    if (child.nodeType == DOM_ELEMENT_NODE) {
      var handler = os.Loader.getProcessorFunction_(child.tagName);
      if (handler) {
        handler(child);
      }
    }
  }
};

/**
 * Processes the  node.
 */
os.Loader.processNamespaceNode = function(node) {
  var prefix = node.getAttribute('prefix');
  var url = node.getAttribute('url');
  os.createNamespace(prefix, url);
};

/**
 * Processes the  node
 */
os.Loader.processTemplateDefNode = function(node) {
  var tag = node.getAttribute('tag');
  var name = node.getAttribute('name');
  for (var child = node.firstChild; child; child = child.nextSibling) {
    if (child.nodeType == DOM_ELEMENT_NODE) {
      // TODO(levik): This won't work once compiler does name mangling.
      var handler = os.Loader.getProcessorFunction_(child.tagName);
      if (handler) {
        handler(child, tag, name);
      }
    }
  }
};

/**
 * Processes the