baja/coll/QueryCursor.js

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

/**
 * Defines `QueryCursor` (not exposed on `baja` namespace).
 * @module baja/coll/QueryCursor
 */
define([ "bajaScript/sys",
        "bajaScript/baja/coll/collUtil" ], 
        function (baja, collUtil) {
  
  "use strict";
  
  var subclass = baja.subclass,
      callSuper = baja.callSuper,
      strictArg = baja.strictArg,
      
      colGet = collUtil.colGet;
  
  /**
   * Cursor for a Query.
   * 
   * @class
   * @alias module:baja/coll/QueryCursor
   * @extends baja.AsyncCursor
   * @inner
   * @public
   * @param {baja.coll.QueryResult} source
   * @param {Object} curData
   */
  var QueryCursor = function QueryCursor(source, curData) {
    var that = this;
    callSuper(QueryCursor, that, arguments);
    that.$source = source;
    that.$curData = curData;
    that.$index = -1;
    that.$before = baja.noop;
    that.$after = baja.noop;
  };
  
  subclass(QueryCursor, baja.AsyncCursor);
  
  /**
   * Return the underlying Cursor's data source.
   * 
   * @returns {baja.coll.QueryResult}
   */
  QueryCursor.prototype.getSource = function () {
    return this.$source;
  }; 
  
  /**
   * Return the current row.
   * 
   * @returns the cursor value (null if none available)
   */
  QueryCursor.prototype.get = function () {
    return colGet(this);
  }; 

  /**
   * When the cursor is iterated, the before function will be called
   * just before iteration starts.
   * 
   * When the function is called, `this` refers to the Cursor. The Cursor is also
   * passed in as a argument to this function.
   * 
   * @param {Function} func the before function.
   */
  QueryCursor.prototype.before = function (func) {
    strictArg(func, Function);
    this.$before = func;
  };
  
  /**
   * When the cursor is iterated, the before function will be called
   * just after iteration has finished.
   * 
   * When the function is called, `this` refers to the Cursor. The Cursor is also
   * passed in as a argument to this function.
   * 
   * @param {Function} func the after function.
   */
  QueryCursor.prototype.after = function (func) {
    strictArg(func, Function);
    this.$after = func;
  };
  
  /**
   * Iterate through the Cursor and call a function for every item.
   * 
   * When the function is called, `this` refers to the Cursor.
   * 
   * @param {Function} func function called on every iteration with 
   *                        the current row used as the first argument and row
   *                        index as the second argument.
   */
  QueryCursor.prototype.each = function (func) {
    strictArg(func, Function);
        
    var that = this,
        size = that.$curData.length,
        i,
        result;
    
    that.$index = -1;

    // Called just before iteration
    that.$before(that);  
        
    for (i = 0; i < size; ++i) {
      // Called for every item in the Cursor
      ++that.$index;
      result = func.call(that, that.get(), that.$index);
      
      // Break if a truthy result is returned
      if (result) {
        break;
      } 
    }
          
    // Called just after iteration
    that.$after(that);
  };
  
  return QueryCursor;
});