baja/nav/NavNodeContainer.js

/**
 * @copyright 2015 Tridium, Inc. All Rights Reserved.
 * @author Gareth Johnson
 */

/**
 * Defines {@link baja.NavNodeContainer}.
 * @module baja/nav/NavNodeContainer
 */
define([
  "bajaScript/sys",
  "bajaScript/baja/obj/Icon",
  "bajaScript/baja/comm/Callback",
  "bajaScript/baja/nav/NavContainer",
  "bajaScript/baja/nav/NavNode" ], function (
    baja,
    Icon,
    Callback,
    NavContainer,
    NavNode) {
  
  "use strict";
  
  var subclass = baja.subclass,
      callSuper = baja.callSuper,
      cx = {};
  
  /**
   * A Nav Node Container.
   *
   * @class
   * @alias baja.NavNodeContainer
   * @extends baja.NavContainer
   * @implements baja.comm.ServerHandlerProxy
   */
  var NavNodeContainer = function NavNodeContainer(obj) {
    callSuper(NavNodeContainer, this, arguments); 
  };
  
  subclass(NavNodeContainer, NavContainer);

  function findNavNode(navNode, navOrd) {
    var i;

    if (navNode.getNavOrd().equals(navOrd)) {
      return navNode;
    }

    for (i = 0; i < navNode.$navKids.length; ++i) {
      if (findNavNode(navNode.$navKids[i], navOrd)) {
        return navNode.$navKids[i];
      }
    }

    return null;
  }

  function eventHandler(space, events, callback) {
    var i,
        ev,
        parentOrd,
        parent,
        node;

    try {

      for (i = 0; i < events.length; ++i) {
        ev = events[i];
        parentOrd = baja.Ord.make(ev.ord);
        parent = findNavNode(space, parentOrd);

        if (parent) {
          try {
            if (ev.id === "added") {
              node = new NavNode(ev.newNode);
              parent.$addChildNode(node);

              baja.nav.fireHandlers(
                ev.id, 
                baja.error,
                baja.nav, 
                parentOrd, 
                node, 
                cx);            
            } else if (ev.id === "removed") {
              node = parent.$removeChildNode(ev.oldName);

              if (node) {
                baja.nav.fireHandlers(
                  ev.id, 
                  baja.error, 
                  baja.nav, 
                  parentOrd, 
                  ev.oldName, 
                  node,
                  cx);    
              }        
            } else if (ev.id === "renamed") {
              node = parent.$updateChildNode(ev.oldName, ev.newNode);

              if (node) {
                baja.nav.fireHandlers(
                  ev.id, 
                  baja.error, 
                  baja.nav, 
                  parentOrd, 
                  node, 
                  ev.oldName, 
                  cx);      
              }      
            } else if (ev.id === "reordered") {
              baja.nav.fireHandlers(
                ev.id, 
                baja.error, 
                baja.nav, 
                parentOrd,
                cx);          
            }
          } catch (err) {
            baja.error(err);
          }
        }
      }
      
    } finally {
      callback();
    }
  }


  /**
   * Initialize the Space Session Handler.
   *
   * @private
   * 
   * @returns {Promise} Resolved once everything is initialized.
   */
  NavNodeContainer.prototype.init = function () {
    var that = this,
        cb = new Callback(),
        id = that.getServerHandlerId();

    cb.addOk(function (ok/*, fail*/) {
      ok(that);
    });

    if (!baja.comm.hasServerHandler(id)) {
      baja.comm.makeServerHandler(
        id, // The id of the Server Session Handler to be created
        "box:NavNodeSessionHandler", // Type Spec of the Server Session Handler
        id, // Initial argument for the Server Session Handler
        function (events, callback) {
          eventHandler(that, events, callback);
        },
        cb,
        /*makeInBatch*/false);  
    } else {
      cb.ok();
    }

    return cb.promise();
  };

  /**
   * @private
   * @override
   * @returns {String} the server handler ID to use when making server calls.
   */
  NavNodeContainer.prototype.getServerHandlerId = function () {
    return this.getAbsoluteOrd().relativizeToSession().toString();
  };


  /**
   * Make a remote call to the Session Server Handler.
   *
   * @private
   * 
   * @param  {String} key The key of the Server Handler to invoke.
   * @param  arg The argument that will be encoded.
   * @param  {baja.comm.Callback} cb The callback used to send the message.
   * @returns {Promise} A promise that will be resolved once the response
   * has been received.
   */
  NavNodeContainer.prototype.$send = function (key, arg, cb) {
    baja.comm.serverHandlerCall(this, key, arg, cb);

    return cb.promise();
  };
        
  /**
   * Access the Nav Children.
   *
   * @method
   *
   * @param {Object} obj the Object Literal for the method's arguments.
   * @param {Function} [obj.ok] (Deprecated: use Promise) called when we have
   * the Nav Children. An array of Nav Children is passed as an argument into
   * this function.
   * @param {Function} [obj.fail] (Deprecated: use Promise) called if the
   * function fails to complete.
   * @returns {Promise.<Array.<baja.NavNode>>} a promise that will be resolved
   * once the nav children have been retrieved.
   * 
   * @example
   *   container.getNavChildren()
   *     .then(function (kids) {
   *       baja.outln('retrieved nav children: ' + kids.join());
   *     })
   *     .catch(function (err) {
   *       baja.error('failed to retrieve nav children: ' + err);
   *     });
   */
  NavNodeContainer.prototype.getNavChildren = NavNode.prototype.getNavChildren;

  /**
   * Return the Space's absolute ORD.
   * 
   * @returns {baja.Ord} The absolute ORD.
   */
  NavNodeContainer.prototype.getAbsoluteOrd = function () {
    return this.getNavOrd();
  };
    
  return NavNodeContainer;
});