Pre-release
AdventureJS Docs Downloads
Score: 0 Moves: 0
//diff.js
/*global adventurejs A*/

/**
 * diff function for comparing objects.
 * Specifically intended to support UNDO and SAVE / RESTORE.
 * It recurses objects, stringifies arrays, copies others.
 * @method adventurejs.Game#diff
 * @memberOf adventurejs.Game
 * @param {Object} baseline_object Old object
 * @param {Object} updated_object New object
 * @returns {Object}
 */
adventurejs.diff = function Adventurejs_diff(baseline_object, updated_object) {
  var starttime = new Date().getTime();
  var diff_object = {};

  for (var prop in updated_object) {
    if (false === Object.prototype.hasOwnProperty.call(updated_object, prop)) {
      continue;
    }
    // if prop is of different type, include in diff
    else if (typeof updated_object[prop] !== typeof baseline_object[prop]) {
      diff_object[prop] = A.clone(updated_object[prop]);
      continue;
    }

    // if updated_object prop doesn't exist in baseline_object, include in diff
    else if (
      "undefined" === typeof baseline_object[prop] &&
      "undefined" !== typeof updated_object[prop]
    ) {
      diff_object[prop] = A.clone(updated_object[prop]);
      continue;
    }

    // Handle the 3 simple types, and null or undefined
    else if (
      (null == updated_object[prop] ||
        "object" != typeof updated_object[prop]) &&
      updated_object[prop] !== baseline_object[prop]
    ) {
      diff_object[prop] = A.clone(updated_object[prop]);
      continue;
    }

    // else if (Array.isArray(updated_object[prop])) {
    //   var baseline_object_prop = JSON.stringify(baseline_object[prop]);
    //   var updated_object_prop = JSON.stringify(updated_object[prop]);
    //   if (updated_object_prop !== baseline_object_prop) {
    //       console.warn("BAZINGA!!!");
    //       console.log("prop", prop);
    //       console.log("baseline_object_prop", baseline_object_prop);
    //       console.log("updated_object_prop", updated_object_prop);
    //     diff_object[prop] = JSON.parse(updated_object_prop);
    //   }
    //   continue;
    // }

    // Handle Array - just stringify, it's not worth worrying about
    // the complexity of splicing or reordering
    else if (Array.isArray(updated_object[prop])) {
      var baseline_object_prop = JSON.stringify(baseline_object[prop]);
      var updated_object_prop = JSON.stringify(updated_object[prop]);
      if (updated_object_prop !== baseline_object_prop) {
        diff_object[prop] = JSON.parse(updated_object_prop);
      }
      continue;
    }

    // Handle Object - recursive
    else if (typeof updated_object[prop] === "function") {
      // this version does stringify then parse - unsure its necessary
      // var baseline_object_prop = JSON.stringify( baseline_object[ prop ],
      //   function(key, val) {
      //     return val.toString()
      //   });
      // var updated_object_prop = JSON.stringify( updated_object[ prop ],
      //   function(key, val) {
      //     return val.toString()
      //   });

      // this version converts to string without stringify
      var baseline_object_prop = baseline_object[prop].toString();
      var updated_object_prop = updated_object[prop].toString();

      if (updated_object_prop !== baseline_object_prop) {
        diff_object[prop] = eval("(" + updated_object_prop + ")");
      }
      continue;
    }

    // Handle Object - recursive
    else if (typeof updated_object[prop] === "object") {
      var diff_object_prop = A.diff(
        baseline_object[prop],
        updated_object[prop]
      );
      var diff_object_prop_keys = Object.keys(diff_object_prop);
      if (0 < diff_object_prop_keys.length) {
        diff_object[prop] = diff_object_prop;
      }
      continue;
    }
  }

  return diff_object;
};