| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 | 
/** 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.*//** 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.*/function defaultKeyGetter(item) {  return item;}/** * @param {Array} oldArr * @param {Array} newArr * @param {Function} oldKeyGetter * @param {Function} newKeyGetter * @param {Object} [context] Can be visited by this.context in callback. */function DataDiffer(oldArr, newArr, oldKeyGetter, newKeyGetter, context) {  this._old = oldArr;  this._new = newArr;  this._oldKeyGetter = oldKeyGetter || defaultKeyGetter;  this._newKeyGetter = newKeyGetter || defaultKeyGetter;  this.context = context;}DataDiffer.prototype = {  constructor: DataDiffer,  /**   * Callback function when add a data   */  add: function (func) {    this._add = func;    return this;  },  /**   * Callback function when update a data   */  update: function (func) {    this._update = func;    return this;  },  /**   * Callback function when remove a data   */  remove: function (func) {    this._remove = func;    return this;  },  execute: function () {    var oldArr = this._old;    var newArr = this._new;    var oldDataIndexMap = {};    var newDataIndexMap = {};    var oldDataKeyArr = [];    var newDataKeyArr = [];    var i;    initIndexMap(oldArr, oldDataIndexMap, oldDataKeyArr, '_oldKeyGetter', this);    initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter', this);    for (i = 0; i < oldArr.length; i++) {      var key = oldDataKeyArr[i];      var idx = newDataIndexMap[key]; // idx can never be empty array here. see 'set null' logic below.      if (idx != null) {        // Consider there is duplicate key (for example, use dataItem.name as key).        // We should make sure every item in newArr and oldArr can be visited.        var len = idx.length;        if (len) {          len === 1 && (newDataIndexMap[key] = null);          idx = idx.shift();        } else {          newDataIndexMap[key] = null;        }        this._update && this._update(idx, i);      } else {        this._remove && this._remove(i);      }    }    for (var i = 0; i < newDataKeyArr.length; i++) {      var key = newDataKeyArr[i];      if (newDataIndexMap.hasOwnProperty(key)) {        var idx = newDataIndexMap[key];        if (idx == null) {          continue;        } // idx can never be empty array here. see 'set null' logic above.        if (!idx.length) {          this._add && this._add(idx);        } else {          for (var j = 0, len = idx.length; j < len; j++) {            this._add && this._add(idx[j]);          }        }      }    }  }};function initIndexMap(arr, map, keyArr, keyGetterName, dataDiffer) {  for (var i = 0; i < arr.length; i++) {    // Add prefix to avoid conflict with Object.prototype.    var key = '_ec_' + dataDiffer[keyGetterName](arr[i], i);    var existence = map[key];    if (existence == null) {      keyArr.push(key);      map[key] = i;    } else {      if (!existence.length) {        map[key] = existence = [existence];      }      existence.push(i);    }  }}var _default = DataDiffer;module.exports = _default;
 |