text: /*!
   * CanJS - 2.3.23
   * http://canjs.com/
   * Copyright (c) 2016 Bitovi
   * Fri, 08 Apr 2016 17:58:15 GMT
   * Licensed MIT
   */
  
  /*can@2.3.23#list/sort/sort*/
  var can = require('../../util/util.js');
  require('../list.js');
  var oldBubbleRule = can.List._bubbleRule;
  can.List._bubbleRule = function (eventName, list) {
      var oldBubble = oldBubbleRule.apply(this, arguments);
      if (list.comparator && can.inArray('change', oldBubble) === -1) {
          oldBubble.push('change');
      }
      return oldBubble;
  };
  var proto = can.List.prototype, _changes = proto._changes || function () {
      }, setup = proto.setup, unbind = proto.unbind;
  can.extend(proto, {
      setup: function (instances, options) {
          setup.apply(this, arguments);
          this.bind('change', can.proxy(this._changes, this));
          this._comparatorBound = false;
          this.bind('comparator', can.proxy(this._comparatorUpdated, this));
          delete this._init;
          if (this.comparator) {
              this.sort();
          }
      },
      _comparatorUpdated: function (ev, newValue) {
          if (newValue || newValue === 0) {
              this.sort();
              if (this._bindings > 0 && !this._comparatorBound) {
                  this.bind('change', this._comparatorBound = function () {
                  });
              }
          } else if (this._comparatorBound) {
              unbind.call(this, 'change', this._comparatorBound);
              this._comparatorBound = false;
          }
      },
      unbind: function (ev, handler) {
          var res = unbind.apply(this, arguments);
          if (this._comparatorBound && this._bindings === 1) {
              unbind.call(this, 'change', this._comparatorBound);
              this._comparatorBound = false;
          }
          return res;
      },
      _comparator: function (a, b) {
          var comparator = this.comparator;
          if (comparator && typeof comparator === 'function') {
              return comparator(a, b);
          }
          if (typeof a === 'string' && typeof b === 'string' && ''.localeCompare) {
              return a.localeCompare(b);
          }
          return a === b ? 0 : a < b ? -1 : 1;
      },
      _changes: function (ev, attr, how, newVal, oldVal) {
          var dotIndex = ('' + attr).indexOf('.');
          if (this.comparator && dotIndex !== -1) {
              if (ev.batchNum) {
                  if (ev.batchNum === this._lastProcessedBatchNum) {
                      return;
                  } else {
                      this.sort();
                      this._lastProcessedBatchNum = ev.batchNum;
                      return;
                  }
              }
              var currentIndex = +attr.substr(0, dotIndex);
              var item = this[currentIndex];
              var changedAttr = attr.substr(dotIndex + 1);
              if (typeof item !== 'undefined' && (typeof this.comparator !== 'string' || this.comparator.indexOf(changedAttr) === 0)) {
                  var newIndex = this._getRelativeInsertIndex(item, currentIndex);
                  if (newIndex !== currentIndex) {
                      this._swapItems(currentIndex, newIndex);
                      can.batch.trigger(this, 'length', [this.length]);
                  }
              }
          }
          _changes.apply(this, arguments);
      },
      _getInsertIndex: function (item, lowerBound, upperBound) {
          var insertIndex = 0;
          var a = this._getComparatorValue(item);
          var b, dir, comparedItem, testIndex;
          lowerBound = typeof lowerBound === 'number' ? lowerBound : 0;
          upperBound = typeof upperBound === 'number' ? upperBound : this.length - 1;
          while (lowerBound <= upperBound) {
              testIndex = (lowerBound + upperBound) / 2 | 0;
              comparedItem = this[testIndex];
              b = this._getComparatorValue(comparedItem);
              dir = this._comparator(a, b);
              if (dir < 0) {
                  upperBound = testIndex - 1;
              } else if (dir >= 0) {
                  lowerBound = testIndex + 1;
                  insertIndex = lowerBound;
              }
          }
          return insertIndex;
      },
      _getRelativeInsertIndex: function (item, currentIndex) {
          var naiveInsertIndex = this._getInsertIndex(item);
          var nextItemIndex = currentIndex + 1;
          var a = this._getComparatorValue(item);
          var b;
          if (naiveInsertIndex >= currentIndex) {
              naiveInsertIndex -= 1;
          }
          if (currentIndex < naiveInsertIndex && nextItemIndex < this.length) {
              b = this._getComparatorValue(this[nextItemIndex]);
              if (this._comparator(a, b) === 0) {
                  return currentIndex;
              }
          }
          return naiveInsertIndex;
      },
      _getComparatorValue: function (item) {
          var comparator = this.comparator;
          if (item && comparator && typeof comparator === 'string') {
              item = typeof item[comparator] === 'function' ? item[comparator]() : item.attr(comparator);
          }
          return item;
      },
      _getComparatorValues: function () {
          var self = this;
          var a = [];
          this.each(function (item, index) {
              a.push(self._getComparatorValue(item));
          });
          return a;
      },
      sort: function (comparator) {
          if (arguments.length) {
              this.attr('comparator', comparator);
          } else {
              this._sort();
          }
          return this;
      },
      _sort: function () {
          var a, b, c, isSorted;
          for (var i, iMin, j = 0, n = this.length; j < n - 1; j++) {
              iMin = j;
              isSorted = true;
              c = undefined;
              for (i = j + 1; i < n; i++) {
                  a = this._getComparatorValue(this.attr(i));
                  b = this._getComparatorValue(this.attr(iMin));
                  if (this._comparator.call(this, a, b) < 0) {
                      isSorted = false;
                      iMin = i;
                  }
                  if (c && this._comparator.call(this, a, c) < 0) {
                      isSorted = false;
                  }
                  c = a;
              }
              if (isSorted) {
                  break;
              }
              if (iMin !== j) {
                  this._swapItems(iMin, j);
              }
          }
          can.batch.trigger(this, 'length', [this.length]);
          return this;
      },
      _swapItems: function (oldIndex, newIndex) {
          var temporaryItemReference = this[oldIndex];
          [].splice.call(this, oldIndex, 1);
          [].splice.call(this, newIndex, 0, temporaryItemReference);
          can.batch.trigger(this, 'move', [
              temporaryItemReference,
              newIndex,
              oldIndex
          ]);
      }
  });
  can.each({
      push: 'length',
      unshift: 0
  }, function (where, name) {
      var proto = can.List.prototype, old = proto[name];
      proto[name] = function () {
          if (this.comparator && arguments.length) {
              var args = can.makeArray(arguments);
              var length = args.length;
              var i = 0;
              var newIndex, val;
              while (i < length) {
                  val = can.bubble.set(this, i, this.__type(args[i], i));
                  newIndex = this._getInsertIndex(val);
                  Array.prototype.splice.apply(this, [
                      newIndex,
                      0,
                      val
                  ]);
                  this._triggerChange('' + newIndex, 'add', [val], undefined);
                  i++;
              }
              can.batch.trigger(this, 'reset', [args]);
              return this;
          } else {
              return old.apply(this, arguments);
          }
      };
  });
  (function () {
      var proto = can.List.prototype;
      var oldSplice = proto.splice;
      proto.splice = function (index, howMany) {
          var args = can.makeArray(arguments);
          if (!this.comparator) {
              return oldSplice.apply(this, args);
          }
          oldSplice.call(this, index, howMany);
          args.splice(0, 2);
          proto.push.apply(this, args);
      };
  }());
  module.exports = can.Map;