<commit_before>/*!
 * Lectric v0.2.3
 * http://github.com/mckinney/lectric
 *
 * Copyright 2010, McKinney
 * Licensed under the MIT license.
 * http://github.com/mckinney/lectric/blob/master/LICENSE
 *
 * Author: Brett C. Buddin
 */

(function(window) {
  var Lectric = {};
  var Browser = {};

  var ua = navigator.userAgent.toLowerCase();
  Browser.isWebkit = !!ua.match(/applewebkit/i);
  Browser.isChrome = !!ua.match(/chrome/i);
  Browser.isIE = !!ua.match(/msie/i);
  Browser.isFirefox = ua.match(/firefox/);
  try {
    document.createEvent("TouchEvent");
    Browser.supportsTouch = true;
  } catch (e) {
    Browser.supportsTouch = false;
  }

  var Slider = function() {
    if (Browser.supportsTouch && Browser.isWebkit) {
      return new TouchSlider();
    } else {
      return new BaseSlider();
    }
  };

  var BaseSlider = function() {};

  BaseSlider.prototype.init = function(element, opts) {
    this.opts = jQuery.extend({
      next: undefined,
      previous: undefined,
      item : ".item",
      limitLeft: false,
      limitRight: false,
      init: undefined
    }, opts);

    this.currentX = 0;
    this.currentY = 0;

    var $element = $(element);
    $element.find(this.opts.item).wrapAll('
');
    $element.css('overflow', 'hidden');
    this.element = $element.find('.items');
    this.element.itemSelector = this.opts.item;
    this.element.css('width', '1000000px');
    this.element.find(this.element.itemSelector).css('float', 'left');

    this.structure = this.structure(this.element);

    var self = this;
    if (this.opts.next) {
      $(this.opts.next).bind('click', function() {
        var previous = self.currentX;
        self.currentX = self.limitXBounds(self.nextPageX(self.currentX));
        if (self.currentX !== previous) {
          self.update();
        }

        return false;
      });
    }

    if (this.opts.previous) {
      $(this.opts.previous).bind('click', function() {
        var previous = self.currentX;
        self.currentX = self.limitXBounds(self.previousPageX(self.currentX));
        if (self.currentX !== previous) {
          self.update();
        }

        return false;
      });
    }

    if (this.opts.init !== undefined) {
      this.opts.init(this);
    }
  };

  BaseSlider.prototype.update = function(opts) {
    var options = jQuery.extend({animate: true, triggerMove: true}, opts);

    var self = this;
    var after = function() {
      self.element.trigger('animationEnd.lectric');
      $(this).dequeue();
    };

    if (options.animate) {
      this.element.animate({'margin-left': this.currentX + 'px'}).queue(after);
    } else {
      this.element.css({'margin-left': this.currentX + 'px'}).queue(after);
    }

    if (options.triggerMove) { this.element.trigger('move.lectric'); }
  };

  BaseSlider.prototype.subscribe = function(name, fn) {
    var self = this;
    return this.element.bind(name + '.lectric', function(e) {
      if (e.target == self.element[0]) {
        fn(self);
      }
    });
  };

  BaseSlider.prototype.structure = function(element) {
    var structure = {};
    var first = function() { return element.find(element.itemSelector).eq(0); };

    structure.itemCount = function() { return element.find(element.itemSelector).size(); };
    structure.itemHeight = function() { return parseInt(first().height(), 10); };

    structure.itemSpacing = function() {
      var marginRight = first().css('marginRight');
      return (marginRight !== undefined) ? parseInt(marginRight.replace('px', ''), 10) : 0;
    };
    structure.itemWidth = function() {
      return (structure.itemSpacing() + parseInt(first().width(), 10));
    };

    return structure;
  };

  BaseSlider.prototype.page = function(currentX) {
    return Math.abs(Math.round(currentX / this.structure.itemWidth()));
  };

  BaseSlider.prototype.nearestPageX = function(currentX) {
    return Math.round(currentX / this.structure.itemWidth()) * this.structure.itemWidth();
  };

  BaseSlider.prototype.pageX = function(index) {
    var flip = (this.opts.reverse) ? 1 : -1;
    return flip * index * this.structure.itemWidth();
  };

  BaseSlider.prototype.to = function(index) {
    var previous = this.currentX;
    this.currentX = this.limitXBounds(this.pageX(index));
    if (this.currentX !== previous) {
      this.update();
    }
    return this.currentX;
  };

  BaseSlider.prototype.toElement = function(e) {
    var previous = this.currentX;
    var index = this.getItemIndex(e);
	return this.to(index);
  };

  BaseSlider.prototype.getItemIndex = function(e) {
	var all = this.element.find(this.element.itemSelector);

    var i;
    var length = all.length;
	for (i = 0; i < length; i++) {
      if ($(all[i])[0] == e[0]) { return i; }
	}
  };

  BaseSlider.prototype.nextPageX = function(currentX) {
    if (this.page(currentX) + 1 <= this.structure.itemCount() - 1) {
      currentX = currentX -this.structure.itemWidth();
    }
    return currentX;
  };

  BaseSlider.prototype.previousPageX = function(currentX) {
    if (this.page(currentX) >= 0) {
      currentX = currentX + this.structure.itemWidth();
    }
    return currentX;
  };

  BaseSlider.prototype.limitXBounds = function(currentX) {
    var total_width = this.structure.itemWidth() * this.structure.itemCount();
    if (this.opts.reverse) {
      currentX = (currentX > total_width - this.structure.itemWidth()) ?
                   total_width - this.structure.itemWidth() :
                   currentX;

      currentX = (currentX < 0) ? 0 : currentX;
    } else {
    currentX = (currentX < -total_width + this.structure.itemWidth()) ?
                 -total_width + this.structure.itemWidth() :
                 currentX;
      currentX = (currentX > 0) ? 0 : currentX;
    }

    if ((this.currentX - currentX > 0 && this.opts.limitRight) ||
        (this.currentX - currentX < 0 && this.opts.limitLeft)) {
      currentX = this.currentX;
    }
    return currentX;
  };

  var TouchSlider = function() {};
  TouchSlider.prototype = new BaseSlider();
  TouchSlider.superobject = BaseSlider.prototype;

  TouchSlider.prototype.init = function(element, structure, opts) {
    TouchSlider.superobject.init.call(this, element, structure, opts);
    this.element.parent().addClass('lectric-slider-touch');

    this.gesturing = false;
    var $element = $(element);
    $element[0].addEventListener('touchstart', this, false);
    $element[0].addEventListener('webkitTransitionEnd', this, false);
  };

  TouchSlider.prototype.update = function(opts) {
    var options = jQuery.extend({animate: true, triggerMove: true}, opts);
    if (options.animate) { this.decayOn(); }
    this.element.css({'-webkit-transform': 'translate3d(' + this.currentX + 'px, 0, 0)'});

    if (options.triggerMove) { this.element.trigger('move.lectric'); }
  };

  TouchSlider.prototype.handleEvent = function(e) { this[e.type](e); };

  TouchSlider.prototype.click = function(e) {
    if (this.moved) { e.preventDefault(); }
    this.element[0].removeEventListener('click', this, false);
    return false;
  };

  TouchSlider.prototype.touchstart = function(e) {
    this.currentTarget = e.currentTarget;
    this.startX = e.touches[0].pageX - this.currentX;
    this.startY = e.touches[0].pageY - this.currentY;
    this.moved = false;

    window.addEventListener('gesturestart', this, false);
    window.addEventListener('gestureend', this, false);
    window.addEventListener('touchmove', this, false);
    window.addEventListener('touchend', this, false);
    this.element[0].addEventListener('click', this, false);

    this.decayOff();

    this.element.trigger('start.lectric');
  };

  TouchSlider.prototype.touchmove = function(e) {
    if (this.gesturing) { return false; }

    if (!this.moved) {
      var deltaY = e.touches[0].pageY - this.startY;
      var deltaX = e.touches[0].pageX - this.startX;
      if (Math.abs(deltaY) < 15) {
        e.preventDefault();
      }

      this.element.trigger('firstMove.lectric');
    }

    this.moved = true;
    this.lastX = this.currentX;
    this.lastMoveTime = new Date();

    this.currentX = this.limitXBounds(e.touches[0].pageX - this.startX);

    this.update({animate: false});
  };

  TouchSlider.prototype.touchend = function(e) {
    window.removeEventListener('gesturestart', this, false);
    window.removeEventListener('gestureend', this, false);
    window.removeEventListener('touchmove', this, false);
    window.removeEventListener('touchend', this, false);

    if (this.moved) {
      var dx = this.currentX - this.lastX;
      var dt = (new Date()) - this.lastMoveTime + 1;

      var tossedX = this.limitXBounds(this.currentX + dx * 100 / dt);
      this.currentX = this.nearestPageX(tossedX);

      this.update();
      this.element.trigger('end.lectric');
    } else {
      this.element.trigger('endNoMove.lectric');
    }

    this.currentTarget = undefined;
  };

  TouchSlider.prototype.webkitTransitionEnd = function(e) {
    this.element.trigger('animationEnd.lectric');
  };

  TouchSlider.prototype.gesturestart = function(e) { this.gesturing = true; };
  TouchSlider.prototype.gestureend = function(e) { this.gesturing = false; };

  TouchSlider.prototype.decayOff = function() {
    this.element.css({'-webkit-transition-duration': '0s'});
    this.element.css({'-webkit-transition-property': 'none'});
  };

  TouchSlider.prototype.decayOn = function() {
    this.element.css({'-webkit-transition-duration': '0.4s'});
    this.element.css({'-webkit-transition-property': '-webkit-transform'});
  };

  Lectric.Slider = Slider;
  Lectric.BaseSlider = BaseSlider;
  Lectric.TouchSlider = TouchSlider;

  window.Lectric = Lectric;
})(window);<commit_msg>Eliminating the Browser object<commit_after>/*!
 * Lectric v0.2.3
 * http://github.com/mckinney/lectric
 *
 * Copyright 2010, McKinney
 * Licensed under the MIT license.
 * http://github.com/mckinney/lectric/blob/master/LICENSE
 *
 * Author: Brett C. Buddin
 */

(function(window) {
  var ua = navigator.userAgent.toLowerCase();
  isWebkit = !!ua.match(/applewebkit/i);
  var supportsTouch = false;
  try {
    document.createEvent("TouchEvent");
    supportsTouch = true;
  } catch (e) {}

  var Slider = function() {
    if (supportsTouch && isWebkit) {
      return new TouchSlider();
    } else {
      return new BaseSlider();
    }
  };

  var BaseSlider = function() {};

  BaseSlider.prototype.init = function(element, opts) {
    this.opts = jQuery.extend({
      next: undefined,
      previous: undefined,
      item : ".item",
      limitLeft: false,
      limitRight: false,
      init: undefined
    }, opts);

    this.currentX = 0;
    this.currentY = 0;

    var $element = $(element);
    $element.find(this.opts.item).wrapAll('
');
    $element.css('overflow', 'hidden');
    this.element = $element.find('.items');
    this.element.itemSelector = this.opts.item;
    this.element.css('width', '1000000px');
    this.element.find(this.element.itemSelector).css('float', 'left');

    this.structure = this.structure(this.element);

    var self = this;
    if (this.opts.next) {
      $(this.opts.next).bind('click', function() {
        var previous = self.currentX;
        self.currentX = self.limitXBounds(self.nextPageX(self.currentX));
        if (self.currentX !== previous) {
          self.update();
        }

        return false;
      });
    }

    if (this.opts.previous) {
      $(this.opts.previous).bind('click', function() {
        var previous = self.currentX;
        self.currentX = self.limitXBounds(self.previousPageX(self.currentX));
        if (self.currentX !== previous) {
          self.update();
        }

        return false;
      });
    }

    if (this.opts.init !== undefined) {
      this.opts.init(this);
    }
  };

  BaseSlider.prototype.update = function(opts) {
    var options = jQuery.extend({animate: true, triggerMove: true}, opts);

    var self = this;
    var after = function() {
      self.element.trigger('animationEnd.lectric');
      $(this).dequeue();
    };

    if (options.animate) {
      this.element.animate({'margin-left': this.currentX + 'px'}).queue(after);
    } else {
      this.element.css({'margin-left': this.currentX + 'px'}).queue(after);
    }

    if (options.triggerMove) { this.element.trigger('move.lectric'); }
  };

  BaseSlider.prototype.subscribe = function(name, fn) {
    var self = this;
    return this.element.bind(name + '.lectric', function(e) {
      if (e.target == self.element[0]) {
        fn(self);
      }
    });
  };

  BaseSlider.prototype.structure = function(element) {
    var structure = {};
    var first = function() { return element.find(element.itemSelector).eq(0); };

    structure.itemCount = function() { return element.find(element.itemSelector).size(); };
    structure.itemHeight = function() { return parseInt(first().height(), 10); };

    structure.itemSpacing = function() {
      var marginRight = first().css('marginRight');
      return (marginRight !== undefined) ? parseInt(marginRight.replace('px', ''), 10) : 0;
    };
    structure.itemWidth = function() {
      return (structure.itemSpacing() + parseInt(first().width(), 10));
    };

    return structure;
  };

  BaseSlider.prototype.page = function(currentX) {
    return Math.abs(Math.round(currentX / this.structure.itemWidth()));
  };

  BaseSlider.prototype.nearestPageX = function(currentX) {
    return Math.round(currentX / this.structure.itemWidth()) * this.structure.itemWidth();
  };

  BaseSlider.prototype.pageX = function(index) {
    var flip = (this.opts.reverse) ? 1 : -1;
    return flip * index * this.structure.itemWidth();
  };

  BaseSlider.prototype.to = function(index) {
    var previous = this.currentX;
    this.currentX = this.limitXBounds(this.pageX(index));
    if (this.currentX !== previous) {
      this.update();
    }
    return this.currentX;
  };

  BaseSlider.prototype.toElement = function(e) {
    var previous = this.currentX;
    var index = this.getItemIndex(e);
	return this.to(index);
  };

  BaseSlider.prototype.getItemIndex = function(e) {
	var all = this.element.find(this.element.itemSelector);

    var i;
    var length = all.length;
	for (i = 0; i < length; i++) {
      if ($(all[i])[0] == e[0]) { return i; }
	}
  };

  BaseSlider.prototype.nextPageX = function(currentX) {
    if (this.page(currentX) + 1 <= this.structure.itemCount() - 1) {
      currentX = currentX -this.structure.itemWidth();
    }
    return currentX;
  };

  BaseSlider.prototype.previousPageX = function(currentX) {
    if (this.page(currentX) >= 0) {
      currentX = currentX + this.structure.itemWidth();
    }
    return currentX;
  };

  BaseSlider.prototype.limitXBounds = function(currentX) {
    var total_width = this.structure.itemWidth() * this.structure.itemCount();
    if (this.opts.reverse) {
      currentX = (currentX > total_width - this.structure.itemWidth()) ?
                   total_width - this.structure.itemWidth() :
                   currentX;

      currentX = (currentX < 0) ? 0 : currentX;
    } else {
    currentX = (currentX < -total_width + this.structure.itemWidth()) ?
                 -total_width + this.structure.itemWidth() :
                 currentX;
      currentX = (currentX > 0) ? 0 : currentX;
    }

    if ((this.currentX - currentX > 0 && this.opts.limitRight) ||
        (this.currentX - currentX < 0 && this.opts.limitLeft)) {
      currentX = this.currentX;
    }
    return currentX;
  };

  var TouchSlider = function() {};
  TouchSlider.prototype = new BaseSlider();
  TouchSlider.superobject = BaseSlider.prototype;

  TouchSlider.prototype.init = function(element, structure, opts) {
    TouchSlider.superobject.init.call(this, element, structure, opts);
    this.element.parent().addClass('lectric-slider-touch');

    this.gesturing = false;
    var $element = $(element);
    $element[0].addEventListener('touchstart', this, false);
    $element[0].addEventListener('webkitTransitionEnd', this, false);
  };

  TouchSlider.prototype.update = function(opts) {
    var options = jQuery.extend({animate: true, triggerMove: true}, opts);
    if (options.animate) { this.decayOn(); }
    this.element.css({'-webkit-transform': 'translate3d(' + this.currentX + 'px, 0, 0)'});

    if (options.triggerMove) { this.element.trigger('move.lectric'); }
  };

  TouchSlider.prototype.handleEvent = function(e) { this[e.type](e); };

  TouchSlider.prototype.click = function(e) {
    if (this.moved) { e.preventDefault(); }
    this.element[0].removeEventListener('click', this, false);
    return false;
  };

  TouchSlider.prototype.touchstart = function(e) {
    this.currentTarget = e.currentTarget;
    this.startX = e.touches[0].pageX - this.currentX;
    this.startY = e.touches[0].pageY - this.currentY;
    this.moved = false;

    window.addEventListener('gesturestart', this, false);
    window.addEventListener('gestureend', this, false);
    window.addEventListener('touchmove', this, false);
    window.addEventListener('touchend', this, false);
    this.element[0].addEventListener('click', this, false);

    this.decayOff();

    this.element.trigger('start.lectric');
  };

  TouchSlider.prototype.touchmove = function(e) {
    if (this.gesturing) { return false; }

    if (!this.moved) {
      var deltaY = e.touches[0].pageY - this.startY;
      var deltaX = e.touches[0].pageX - this.startX;
      if (Math.abs(deltaY) < 15) {
        e.preventDefault();
      }

      this.element.trigger('firstMove.lectric');
    }

    this.moved = true;
    this.lastX = this.currentX;
    this.lastMoveTime = new Date();

    this.currentX = this.limitXBounds(e.touches[0].pageX - this.startX);

    this.update({animate: false});
  };

  TouchSlider.prototype.touchend = function(e) {
    window.removeEventListener('gesturestart', this, false);
    window.removeEventListener('gestureend', this, false);
    window.removeEventListener('touchmove', this, false);
    window.removeEventListener('touchend', this, false);

    if (this.moved) {
      var dx = this.currentX - this.lastX;
      var dt = (new Date()) - this.lastMoveTime + 1;

      var tossedX = this.limitXBounds(this.currentX + dx * 100 / dt);
      this.currentX = this.nearestPageX(tossedX);

      this.update();
      this.element.trigger('end.lectric');
    } else {
      this.element.trigger('endNoMove.lectric');
    }

    this.currentTarget = undefined;
  };

  TouchSlider.prototype.webkitTransitionEnd = function(e) {
    this.element.trigger('animationEnd.lectric');
  };

  TouchSlider.prototype.gesturestart = function(e) { this.gesturing = true; };
  TouchSlider.prototype.gestureend = function(e) { this.gesturing = false; };

  TouchSlider.prototype.decayOff = function() {
    this.element.css({'-webkit-transition-duration': '0s'});
    this.element.css({'-webkit-transition-property': 'none'});
  };

  TouchSlider.prototype.decayOn = function() {
    this.element.css({'-webkit-transition-duration': '0.4s'});
    this.element.css({'-webkit-transition-property': '-webkit-transform'});
  };

  Lectric.Slider = Slider;
  Lectric.BaseSlider = BaseSlider;
  Lectric.TouchSlider = TouchSlider;

  window.Lectric = Lectric;
})(window);
<|endoftext|>


<commit_before>'use strict';

import $ from 'jquery';

const Nest = {
  Feather(menu, type = 'zf') {
    menu.attr('role', 'menubar');

    var items = menu.find('li').attr({'role': 'menuitem'}),
        subMenuClass = `is-${type}-submenu`,
        subItemClass = `${subMenuClass}-item`,
        hasSubClass = `is-${type}-submenu-parent`,
        applyAria = (type !== 'accordion'); // Accordions handle their own ARIA attriutes.

    items.each(function() {
      var $item = $(this),
          $sub = $item.children('ul');

      if ($sub.length) {
        $item.addClass(hasSubClass);
        $sub.addClass(`submenu ${subMenuClass}`).attr({'data-submenu': ''});
        if(applyAria) {
          $item.attr({
            'aria-haspopup': true,
            'aria-label': $item.children('a:first').text()
          });
          // Note:  Drilldowns behave differently in how they hide, and so need
          // additional attributes.  We should look if this possibly over-generalized
          // utility (Nest) is appropriate when we rework menus in 6.4
          if(type === 'drilldown') {
            $item.attr({'aria-expanded': false});
          }
        }
        $sub
          .addClass(`submenu ${subMenuClass}`)
          .attr({
            'data-submenu': '',
            'role': 'menubar'
          });
        if(type === 'drilldown') {
          $sub.attr({'aria-hidden': true});
        }
      }

      if ($item.parent('[data-submenu]').length) {
        $item.addClass(`is-submenu-item ${subItemClass}`);
      }
    });

    return;
  },

  Burn(menu, type) {
    var //items = menu.find('li'),
        subMenuClass = `is-${type}-submenu`,
        subItemClass = `${subMenuClass}-item`,
        hasSubClass = `is-${type}-submenu-parent`;

    menu
      .find('>li, > li > ul, .menu, .menu > li')
      .removeClass(`${subMenuClass} ${subItemClass} ${hasSubClass} is-submenu-item submenu is-active`)
      .removeAttr('data-submenu').css('display', '');

  }
}

export {Nest};
<commit_msg>fix: clear submenu item classe in Nest #11467<commit_after>'use strict';

import $ from 'jquery';

const Nest = {
  Feather(menu, type = 'zf') {
    menu.attr('role', 'menubar');

    var items = menu.find('li').attr({'role': 'menuitem'}),
        subMenuClass = `is-${type}-submenu`,
        subItemClass = `${subMenuClass}-item`,
        hasSubClass = `is-${type}-submenu-parent`,
        applyAria = (type !== 'accordion'); // Accordions handle their own ARIA attriutes.

    items.each(function() {
      var $item = $(this),
          $sub = $item.children('ul');

      if ($sub.length) {
        $item.addClass(hasSubClass);
        $sub.addClass(`submenu ${subMenuClass}`).attr({'data-submenu': ''});
        if(applyAria) {
          $item.attr({
            'aria-haspopup': true,
            'aria-label': $item.children('a:first').text()
          });
          // Note:  Drilldowns behave differently in how they hide, and so need
          // additional attributes.  We should look if this possibly over-generalized
          // utility (Nest) is appropriate when we rework menus in 6.4
          if(type === 'drilldown') {
            $item.attr({'aria-expanded': false});
          }
        }
        $sub
          .addClass(`submenu ${subMenuClass}`)
          .attr({
            'data-submenu': '',
            'role': 'menubar'
          });
        if(type === 'drilldown') {
          $sub.attr({'aria-hidden': true});
        }
      }

      if ($item.parent('[data-submenu]').length) {
        $item.addClass(`is-submenu-item ${subItemClass}`);
      }
    });

    return;
  },

  Burn(menu, type) {
    var //items = menu.find('li'),
        subMenuClass = `is-${type}-submenu`,
        subItemClass = `${subMenuClass}-item`,
        hasSubClass = `is-${type}-submenu-parent`;

    menu
      .find('>li, > li > ul, .menu, .menu > li, [data-submenu] > li')
      .removeClass(`${subMenuClass} ${subItemClass} ${hasSubClass} is-submenu-item submenu is-active`)
      .removeAttr('data-submenu').css('display', '');

  }
}

export {Nest};
<|endoftext|>


<commit_before>// Portland, Oregon
var home  = [45.5230622, -122.67648150000002];

/* Places in lat long
----------------------
Orange County, California
San Diego, California
Seattle, Washington
Tacoma, Washington
Vancouver, Washington
Vancouver, BC
Chicago, Illinois
Las Vegas, Nevada
Boise, Idaho
Phoenix, Arizona
South Bend, Indiana
Louisville, Kentucky
Pittsburgh, Pennsylvania
Sandusky, Ohio
Columbus, Ohio
Youngstown, Ohio
Nashville, Tennessee
Rome, Italy
Brussels, Belgium
Montreal, Quebec
Punta Cana, Dominican Republic
Austin, Texas
Houston, Texas
Saigon, Vietnam
Changi, Singapore
Denver, Colorado
*/
var placesBeen = [[33.7174708, -117.83114280000001],
                  [32.715738, -117.16108380000003],
                  [47.6062095, -122.3320708],
                  [47.2528768, -122.44429059999999],
                  [45.6318397, -122.67160630000001],
                  [49.2827291, -123.12073750000002],
                  [41.8781136, -87.62979819999998],
                  [36.1699412, -115.13982959999998],
                  [43.6187102, -116.21460680000001],
                  [41.4489396, -82.70796050000001],
                  [39.9611755, -82.99879420000002],
                  [38.2526647, -85.75845570000001],
                  [41.6763545, -86.25198979999999],
                  [40.44062479999999, -79.99588640000002],
                  [41.0997803, -80.64951940000003],
                  [33.4483771, -112.07403729999999],
                  [41.9027835, 12.496365500000024],
                  [50.8503463, 4.351721099999963],
                  [36.1626638, -86.78160159999999],
                  [10.8230989, 106.6296638],
                  [30.267153, -97.74306079999997],
                  [1.3450101, 103.98320890000002],
                  [45.5016889, -73.56725599999999],
                  [18.5820101, -68.4054729],
                  [29.7604267, -95.3698028],
                  [39.739236, -104.990251],
                  [38.6270, 90.1994];

/* Places in lat long
----------------------
New York City, New York
Orlando, Florida
Madrid, Spain
London, UK
Dublin, Ireland
Tokyo, Japan
Berlin, Germany
*/
var placesWant  = [[40.712775, -74.005973],
                   [28.538335, -81.379236],
                   [41.385064, 2.173403],
                   [51.507351, -0.127758],
                   [53.349805, -6.260310],
                   [35.689487, 139.691706],
                   [52.520007, 13.404954]];

// Initialize markerMap
function initMarkerMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    center: new google.maps.LatLng(0, 0),
    zoom: 2,
  });

  // Set markers
  setMarkers(map);

  // Set legend
  legend = document.getElementById('legend');
  map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(legend);
}

// Sets the places markers on the map
function setMarkers(map) {
  // Set home
  var marker = new google.maps.Marker({
    position:  new google.maps.LatLng(home[0], home[1]),
    map: map,
    icon: 'http://maps.google.com/mapfiles/kml/pal2/icon10.png'
  });

  // Places I have been
  for(place in placesBeen) {
    var marker = new google.maps.Marker({
      position:  new google.maps.LatLng(placesBeen[place][0], placesBeen[place][1]),
      map: map,
      icon: 'http://maps.google.com/mapfiles/ms/icons/green-dot.png'
    });
  }

  // Places I want to go
  for(place in placesWant) {
    var marker = new google.maps.Marker({
      position:  new google.maps.LatLng(placesWant[place][0], placesWant[place][1]),
      map: map,
      icon: 'http://maps.google.com/mapfiles/ms/icons/red-dot.png'
    });
  }
}

// On document ready
$(function() {
  initMarkerMap();
});<commit_msg>Update lifemap.js<commit_after>// Portland, Oregon
var home  = [45.5230622, -122.67648150000002];

/* Places in lat long
----------------------
Orange County, California
San Diego, California
Seattle, Washington
Tacoma, Washington
Vancouver, Washington
Vancouver, BC
Chicago, Illinois
Las Vegas, Nevada
Boise, Idaho
Phoenix, Arizona
South Bend, Indiana
Louisville, Kentucky
Pittsburgh, Pennsylvania
Sandusky, Ohio
Columbus, Ohio
Youngstown, Ohio
Nashville, Tennessee
Rome, Italy
Brussels, Belgium
Montreal, Quebec
Punta Cana, Dominican Republic
Austin, Texas
Houston, Texas
Saigon, Vietnam
Changi, Singapore
Denver, Colorado
*/
var placesBeen = [[33.7174708, -117.83114280000001],
                  [32.715738, -117.16108380000003],
                  [47.6062095, -122.3320708],
                  [47.2528768, -122.44429059999999],
                  [45.6318397, -122.67160630000001],
                  [49.2827291, -123.12073750000002],
                  [41.8781136, -87.62979819999998],
                  [36.1699412, -115.13982959999998],
                  [43.6187102, -116.21460680000001],
                  [41.4489396, -82.70796050000001],
                  [39.9611755, -82.99879420000002],
                  [38.2526647, -85.75845570000001],
                  [41.6763545, -86.25198979999999],
                  [40.44062479999999, -79.99588640000002],
                  [41.0997803, -80.64951940000003],
                  [33.4483771, -112.07403729999999],
                  [41.9027835, 12.496365500000024],
                  [50.8503463, 4.351721099999963],
                  [36.1626638, -86.78160159999999],
                  [10.8230989, 106.6296638],
                  [30.267153, -97.74306079999997],
                  [1.3450101, 103.98320890000002],
                  [45.5016889, -73.56725599999999],
                  [18.5820101, -68.4054729],
                  [29.7604267, -95.3698028],
                  [39.739236, -104.990251],
                  [38.6270, 90.1994]];

/* Places in lat long
----------------------
New York City, New York
Orlando, Florida
Madrid, Spain
London, UK
Dublin, Ireland
Tokyo, Japan
Berlin, Germany
*/
var placesWant  = [[40.712775, -74.005973],
                   [28.538335, -81.379236],
                   [41.385064, 2.173403],
                   [51.507351, -0.127758],
                   [53.349805, -6.260310],
                   [35.689487, 139.691706],
                   [52.520007, 13.404954]];

// Initialize markerMap
function initMarkerMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    center: new google.maps.LatLng(0, 0),
    zoom: 2,
  });

  // Set markers
  setMarkers(map);

  // Set legend
  legend = document.getElementById('legend');
  map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(legend);
}

// Sets the places markers on the map
function setMarkers(map) {
  // Set home
  var marker = new google.maps.Marker({
    position:  new google.maps.LatLng(home[0], home[1]),
    map: map,
    icon: 'http://maps.google.com/mapfiles/kml/pal2/icon10.png'
  });

  // Places I have been
  for(place in placesBeen) {
    var marker = new google.maps.Marker({
      position:  new google.maps.LatLng(placesBeen[place][0], placesBeen[place][1]),
      map: map,
      icon: 'http://maps.google.com/mapfiles/ms/icons/green-dot.png'
    });
  }

  // Places I want to go
  for(place in placesWant) {
    var marker = new google.maps.Marker({
      position:  new google.maps.LatLng(placesWant[place][0], placesWant[place][1]),
      map: map,
      icon: 'http://maps.google.com/mapfiles/ms/icons/red-dot.png'
    });
  }
}

// On document ready
$(function() {
  initMarkerMap();
});
<|endoftext|>


<commit_before>/* jshint expr:true */
require("./support/titanium");
var check          = require("./support/asyncCheck");
var sinon          = require("sinon");
var chai           = require("chai");
var expect         = chai.expect;
var AssertionError = chai.AssertionError;
var FileLoader     = require("file_loader");
var Q              = require("q");
var fakeTimeout    = 10;

function fakeOnError(url, response) {
  Q.delay(fakeTimeout).then(function() {
    Ti.Network._requestURLs[url].onerror({error: response});
  });
}

function fakeOnLoad(url, response) {
  Q.delay(fakeTimeout).then(function() {
    Ti.Network._requestURLs[url].onload.call(response);
  });
}

function fakeOnDataStream(url, response) {
  Q.delay(fakeTimeout).then(function() {
    Ti.Network._requestURLs[url].ondatastream({progress: response});
  });
}

describe("FileLoader#download", function() {
  var sandbox = sinon.sandbox.create();
  this.timeout(200);

  before(function() {
    // Use the silly mocking system provided by mockti
    Ti.Network.fakeRequests = true;
    Ti.Network.online = true;
  });

  after(function() {
    Ti.Network.fakeRequests = false;
  });

  beforeEach(function() {
    this.test_data = "test data";
    this.response = {
      status:       200,
      responseData: this.test_data
    };
    this.url = "http://example.com/test_file.png";

    this.fileWriteStub   = sandbox.stub(FileLoader.File.prototype, "write").returns(true);
    this.fileExistsStub  = sandbox.stub(FileLoader.File.prototype, "exists");
    this.fileExpiredStub = sandbox.stub(FileLoader.File.prototype, "expired");
    this.createClientSpy = sandbox.spy(Ti.Network, "createHTTPClient");

    FileLoader.setupTaskStack(); // Force a fresh queue for testing
  });

  afterEach(function() {
    sandbox.restore();
    Ti.Network.online = true;
    Ti.Network._clear();
  });

  it("rejects the promise when network unavailable", function(done) {
    var test = this;
    Ti.Network.online = false;
    FileLoader.download("http://test.example.com/image.png")
      .fail(function(reason) {
        check(done, function() {
          sinon.assert.notCalled(test.createClientSpy);
          expect( reason ).to.match(/offline/i);
        });
      }).done();
  });

  it("rejects the promise when there is a network error", function(done) {
    FileLoader.download(this.url)
      .then(function(val) {
        done(new AssertionError("expected promise to be rejected (" + val + ")"));
      }, function(reason) {
        check(done, function() {
          expect( reason ).to.have.property("error", "test_error");
        });
      }).done();
    fakeOnError(this.url, "test_error");
  });

  it("resolves the promise when file data has been written", function(done) {
    FileLoader.download(this.url)
      .then(function(value) {
        check(done, function() {
          expect( value ).to.be.an.instanceof(FileLoader.File);
        });
      }).done();
    fakeOnLoad(this.url, this.response);
  });

  describe("with cached files", function() {
    beforeEach(function() {
      var test_file = FileLoader.File.fromURL(this.url);
      test_file.md5 = Ti.Utils.md5HexDigest(this.test_data);
      test_file.save();

      this.fileExistsStub.returns(true);
    });

    it("resolves when file is cached and not expired", function(done) {
      var test = this;
      this.fileExpiredStub.returns(false);

      FileLoader.download(this.url).then(function(value) {
        check(done, function() {
          sinon.assert.notCalled(test.createClientSpy);
          sinon.assert.notCalled(test.fileWriteStub);
        });
      }).done();
    });

    it("requests new file when cache is expired", function(done) {
      var test = this;
      this.fileExpiredStub.returns(true);
      this.response.responseData = "changed_data";

      FileLoader.download(this.url).then(function(value) {
        check(done, function() {
          sinon.assert.called(test.createClientSpy);
          sinon.assert.called(test.fileWriteStub);
        });
      }).done();

      fakeOnLoad(this.url, this.response);
    });

    it("does not write file when data has not changed", function(done) {
      var test = this;
      this.fileExpiredStub.returns(true);

      FileLoader.download(this.url).then(function(value) {
        check(done, function() {
          sinon.assert.called(test.createClientSpy);
          sinon.assert.notCalled(test.fileWriteStub);
        });
      }).done();

      fakeOnLoad(this.url, this.response);
    });
  });

  it("queues requests with a throttle limit", function(done) {
    var test = this;

    FileLoader.download("a");
    FileLoader.download("b");
    FileLoader.download("c");
    FileLoader.download("d");
    FileLoader.download("e");

    Q.delay(fakeTimeout).then(function() {
      check(done, function() {
        sinon.assert.callCount(test.createClientSpy, Ti.App.cache_requests);
      });
    });
  });

  // FIXME: This feature has been removed and needs to be reinvented.
  it.skip("notifies promise while recieving network data", function(done) {
    var test = this;
    FileLoader.download(this.url).progress(function(value) {
      check(done, function() {
        expect( value ).to.have.property("progress", 0.9);
      });
    }).done();
    fakeOnDataStream(this.url, 0.9);
  });

  it("handles HTTPClient options", function(done) {
    var test = this;
    FileLoader.download(this.url, { username: "bob" }).then(function() {
      check(done, function() {
        sinon.assert.calledWith(test.createClientSpy, sinon.match.has("username", "bob"));
      });
    }).done();

    fakeOnLoad(this.url, this.response);
  });

  describe("Redirects", function() {
    beforeEach(function() {
      this.response = {
        status:       200,
        responseData: "test_data",
        location:     "test_location",
      };
    });

    it("does not use the built-in autoRedirect", function(done) {
      var test = this;
      FileLoader.download("a").done();
      Q.delay(fakeTimeout).then(function() {
        check(done, function() {
          sinon.assert.calledWith(test.createClientSpy, sinon.match.has("autoRedirect", false));
        });
      });
    });

    function fakeRedirectedOnLoad(index, response) {
      Q.delay(fakeTimeout).then(function() {
        Ti.Network._requests[index].onload.call(response);
      });
    }

    function testRedirect(done, redirectCode, asserts) {
      var test = this;
      this.response._redirectStatus = redirectCode;
      FileLoader.download(this.url).then(function() {
        check(done, asserts);
      }, function(err) {
        done(new AssertionError("expected promise to be fulfilled: " + err));
      }).done();
      Q.delay(fakeTimeout).then(function() {
        test.response.status = redirectCode;
        Ti.Network._requests[0].onload.call(test.response);
      }).delay(fakeTimeout).then(function() {
        test.response.status = 200;
        Ti.Network._requests[1].onload.call(test.response);
      });
    }

    [301, 302].forEach(function(redirectCode) {
      it("handles a " + redirectCode + " redirect", function(done) {
        var test = this;
        testRedirect.call(this, done, redirectCode, function() {
          sinon.assert.calledTwice(test.createClientSpy);
          expect( Ti.Network._requestURLs ).to.have.property("test_location");
        });
      });
    });
  });
});
<commit_msg>Refactor redirect tests for better hop managment<commit_after>/* jshint expr:true */
require("./support/titanium");
var check          = require("./support/asyncCheck");
var sinon          = require("sinon");
var chai           = require("chai");
var expect         = chai.expect;
var AssertionError = chai.AssertionError;
var FileLoader     = require("file_loader");
var Q              = require("q");
var fakeTimeout    = 10;

function fakeOnError(url, response) {
  Q.delay(fakeTimeout).then(function() {
    Ti.Network._requestURLs[url].onerror({error: response});
  });
}

function fakeOnLoad(url, response) {
  Q.delay(fakeTimeout).then(function() {
    Ti.Network._requestURLs[url].onload.call(response);
  });
}

function fakeOnDataStream(url, response) {
  Q.delay(fakeTimeout).then(function() {
    Ti.Network._requestURLs[url].ondatastream({progress: response});
  });
}

describe("FileLoader#download", function() {
  var sandbox = sinon.sandbox.create();
  this.timeout(200);

  before(function() {
    // Use the silly mocking system provided by mockti
    Ti.Network.fakeRequests = true;
    Ti.Network.online = true;
  });

  after(function() {
    Ti.Network.fakeRequests = false;
  });

  beforeEach(function() {
    this.test_data = "test data";
    this.response = {
      status:       200,
      responseData: this.test_data
    };
    this.url = "http://example.com/test_file.png";

    this.fileWriteStub   = sandbox.stub(FileLoader.File.prototype, "write").returns(true);
    this.fileExistsStub  = sandbox.stub(FileLoader.File.prototype, "exists");
    this.fileExpiredStub = sandbox.stub(FileLoader.File.prototype, "expired");
    this.createClientSpy = sandbox.spy(Ti.Network, "createHTTPClient");

    FileLoader.setupTaskStack(); // Force a fresh queue for testing
  });

  afterEach(function() {
    sandbox.restore();
    Ti.Network.online = true;
    Ti.Network._clear();
  });

  it("rejects the promise when network unavailable", function(done) {
    var test = this;
    Ti.Network.online = false;
    FileLoader.download("http://test.example.com/image.png")
      .fail(function(reason) {
        check(done, function() {
          sinon.assert.notCalled(test.createClientSpy);
          expect( reason ).to.match(/offline/i);
        });
      }).done();
  });

  it("rejects the promise when there is a network error", function(done) {
    FileLoader.download(this.url)
      .then(function(val) {
        done(new AssertionError("expected promise to be rejected (" + val + ")"));
      }, function(reason) {
        check(done, function() {
          expect( reason ).to.have.property("error", "test_error");
        });
      }).done();
    fakeOnError(this.url, "test_error");
  });

  it("resolves the promise when file data has been written", function(done) {
    FileLoader.download(this.url)
      .then(function(value) {
        check(done, function() {
          expect( value ).to.be.an.instanceof(FileLoader.File);
        });
      }).done();
    fakeOnLoad(this.url, this.response);
  });

  describe("with cached files", function() {
    beforeEach(function() {
      var test_file = FileLoader.File.fromURL(this.url);
      test_file.md5 = Ti.Utils.md5HexDigest(this.test_data);
      test_file.save();

      this.fileExistsStub.returns(true);
    });

    it("resolves when file is cached and not expired", function(done) {
      var test = this;
      this.fileExpiredStub.returns(false);

      FileLoader.download(this.url).then(function(value) {
        check(done, function() {
          sinon.assert.notCalled(test.createClientSpy);
          sinon.assert.notCalled(test.fileWriteStub);
        });
      }).done();
    });

    it("requests new file when cache is expired", function(done) {
      var test = this;
      this.fileExpiredStub.returns(true);
      this.response.responseData = "changed_data";

      FileLoader.download(this.url).then(function(value) {
        check(done, function() {
          sinon.assert.called(test.createClientSpy);
          sinon.assert.called(test.fileWriteStub);
        });
      }).done();

      fakeOnLoad(this.url, this.response);
    });

    it("does not write file when data has not changed", function(done) {
      var test = this;
      this.fileExpiredStub.returns(true);

      FileLoader.download(this.url).then(function(value) {
        check(done, function() {
          sinon.assert.called(test.createClientSpy);
          sinon.assert.notCalled(test.fileWriteStub);
        });
      }).done();

      fakeOnLoad(this.url, this.response);
    });
  });

  it("queues requests with a throttle limit", function(done) {
    var test = this;

    FileLoader.download("a");
    FileLoader.download("b");
    FileLoader.download("c");
    FileLoader.download("d");
    FileLoader.download("e");

    Q.delay(fakeTimeout).then(function() {
      check(done, function() {
        sinon.assert.callCount(test.createClientSpy, Ti.App.cache_requests);
      });
    });
  });

  // FIXME: This feature has been removed and needs to be reinvented.
  it.skip("notifies promise while recieving network data", function(done) {
    var test = this;
    FileLoader.download(this.url).progress(function(value) {
      check(done, function() {
        expect( value ).to.have.property("progress", 0.9);
      });
    }).done();
    fakeOnDataStream(this.url, 0.9);
  });

  it("handles HTTPClient options", function(done) {
    var test = this;
    FileLoader.download(this.url, { username: "bob" }).then(function() {
      check(done, function() {
        sinon.assert.calledWith(test.createClientSpy, sinon.match.has("username", "bob"));
      });
    }).done();

    fakeOnLoad(this.url, this.response);
  });

  describe("Redirects", function() {
    beforeEach(function() {
      this.response = {
        status:       200,
        responseData: "test_data",
        location:     "test_location",
      };
    });

    it("does not use the built-in autoRedirect", function(done) {
      var test = this;
      FileLoader.download("a").done();
      Q.delay(fakeTimeout).then(function() {
        check(done, function() {
          sinon.assert.calledWith(test.createClientSpy, sinon.match.has("autoRedirect", false));
        });
      });
    });

    function fakeRedirectedOnLoad(index, response) {
      Q.delay(fakeTimeout).then(function() {
        Ti.Network._requests[index].onload.call(response);
      });
    }

    function testRedirect(done, redirectCode, redirectHops, asserts) {
      var hops, worker = Q(), test = this;

      function chainNextStatus(index, status) {
        worker
          .delay(fakeTimeout)
          .then(function() {
            test.response.status = status;
            Ti.Network._requests[index].onload.call(test.response);
          });
      }

      FileLoader.download(this.url)
        .then(function() {
          check(done, asserts);
        }, function(err) {
          done(new AssertionError("expected promise to be fulfilled: " + err));
        }).done();

      for (hops = 0; hops < redirectHops; hops++) {
        chainNextStatus(hops, redirectCode);
      }

      chainNextStatus(hops, 200);
    }

    [301, 302].forEach(function(redirectCode) {
      it("handles a " + redirectCode + " redirect", function(done) {
        var test = this;
        testRedirect.call(this, done, redirectCode, 1, function() {
          sinon.assert.calledTwice(test.createClientSpy);
          expect( Ti.Network._requestURLs ).to.have.property("test_location");
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>//Set/enable the loading
jviz.modules.ideogram.prototype.loading = function(value)
{
  //Check the value
  if(typeof value !== 'boolean'){ return this._loading; }

  //Check the value
  (value === true) ? this._panel.showLoading() : this._panel.hideLoading();

  //Save the value
  this._loading = value;

  //Return this
  return this;
};

//Show loading
jviz.modules.ideogram.prototype.showLoading = function(){ return this.loading(true); };

//Hide loading
jviz.modules.ideogram.prototype.hideLoading = function(){ return this.loading(false); };

//Check if is loading
jviz.modules.ideogram.prototype.isLoading = function(){ return this._loading; };
<commit_msg>js/loading.js: fixed bug<commit_after>//Set/enable the loading
jviz.modules.ideogram.prototype.loading = function(value)
{
  //Check the value
  if(typeof value !== 'boolean'){ return this._loading; }

  //Check the value
  (value === true) ? this._panel.el.showLoading() : this._panel.el.hideLoading();

  //Save the value
  this._loading = value;

  //Return this
  return this;
};

//Show loading
jviz.modules.ideogram.prototype.showLoading = function(){ return this.loading(true); };

//Hide loading
jviz.modules.ideogram.prototype.hideLoading = function(){ return this.loading(false); };

//Check if is loading
jviz.modules.ideogram.prototype.isLoading = function(){ return this._loading; };
<|endoftext|>


<commit_before>/* jshint expr:true */
require("./support/titanium");
var check          = require("./support/asyncCheck");
var sinon          = require("sinon");
var chai           = require("chai");
var expect         = chai.expect;
var AssertionError = chai.AssertionError;
var FileLoader     = require("file_loader");
var Q              = require("q");
var fakeTimeout    = 10;

function fakeOnError(url, response) {
  Q.delay(fakeTimeout).then(function() {
    Ti.Network._requestURLs[url].onerror({error: response});
  });
}

function fakeOnLoad(url, response) {
  Q.delay(fakeTimeout).then(function() {
    Ti.Network._requestURLs[url].onload.call(response);
  });
}

function fakeOnDataStream(url, response) {
  Q.delay(fakeTimeout).then(function() {
    Ti.Network._requestURLs[url].ondatastream({progress: response});
  });
}

describe("FileLoader#download", function() {
  var sandbox = sinon.sandbox.create();
  this.timeout(200);

  before(function() {
    // Use the silly mocking system provided by mockti
    Ti.Network.fakeRequests = true;
    Ti.Network.online = true;
  });

  after(function() {
    Ti.Network.fakeRequests = false;
  });

  beforeEach(function() {
    this.test_data = "test data";
    this.response = {
      status:       200,
      responseData: this.test_data
    };
    this.url = "http://example.com/test_file.png";

    this.fileWriteStub   = sandbox.stub(FileLoader.File.prototype, "write").returns(true);
    this.fileExistsStub  = sandbox.stub(FileLoader.File.prototype, "exists");
    this.fileExpiredStub = sandbox.stub(FileLoader.File.prototype, "expired");
    this.createClientSpy = sandbox.spy(Ti.Network, "createHTTPClient");

    FileLoader.setupTaskStack(); // Force a fresh queue for testing
  });

  afterEach(function() {
    sandbox.restore();
    Ti.Network.online = true;
    Ti.Network._clear();
  });

  it("rejects the promise when network unavailable", function(done) {
    var test = this;
    Ti.Network.online = false;
    FileLoader.download("http://test.example.com/image.png")
      .fail(function(reason) {
        check(done, function() {
          sinon.assert.notCalled(test.createClientSpy);
          expect( reason ).to.match(/offline/i);
        });
      }).done();
  });

  it("rejects the promise when there is a network error", function(done) {
    FileLoader.download(this.url)
      .then(function(val) {
        done(new AssertionError("expected promise to be rejected (" + val + ")"));
      }, function(reason) {
        check(done, function() {
          expect( reason ).to.have.property("error", "test_error");
        });
      }).done();
    fakeOnError(this.url, "test_error");
  });

  it("resolves the promise when file data has been written", function(done) {
    FileLoader.download(this.url)
      .then(function(value) {
        check(done, function() {
          expect( value ).to.be.an.instanceof(FileLoader.File);
        });
      }).done();
    fakeOnLoad(this.url, this.response);
  });

  describe("with cached files", function() {
    beforeEach(function() {
      var test_file = FileLoader.File.fromURL(this.url);
      test_file.md5 = Ti.Utils.md5HexDigest(this.test_data);
      test_file.save();

      this.fileExistsStub.returns(true);
    });

    it("resolves when file is cached and not expired", function(done) {
      var test = this;
      this.fileExpiredStub.returns(false);

      FileLoader.download(this.url).then(function(value) {
        check(done, function() {
          sinon.assert.notCalled(test.createClientSpy);
          sinon.assert.notCalled(test.fileWriteStub);
        });
      }).done();
    });

    it("requests new file when cache is expired", function(done) {
      var test = this;
      this.fileExpiredStub.returns(true);
      this.response.responseData = "changed_data";

      FileLoader.download(this.url).then(function(value) {
        check(done, function() {
          sinon.assert.called(test.createClientSpy);
          sinon.assert.called(test.fileWriteStub);
        });
      }).done();

      fakeOnLoad(this.url, this.response);
    });

    it("does not write file when data has not changed", function(done) {
      var test = this;
      this.fileExpiredStub.returns(true);

      FileLoader.download(this.url).then(function(value) {
        check(done, function() {
          sinon.assert.called(test.createClientSpy);
          sinon.assert.notCalled(test.fileWriteStub);
        });
      }).done();

      fakeOnLoad(this.url, this.response);
    });
  });

  it("queues requests with a throttle limit", function(done) {
    var test = this;

    FileLoader.download("a");
    FileLoader.download("b");
    FileLoader.download("c");
    FileLoader.download("d");
    FileLoader.download("e");

    Q.delay(fakeTimeout).then(function() {
      check(done, function() {
        sinon.assert.callCount(test.createClientSpy, Ti.App.cache_requests);
      });
    });
  });

  // FIXME: This feature has been removed and needs to be reinvented.
  it.skip("notifies promise while recieving network data", function(done) {
    var test = this;
    FileLoader.download(this.url).progress(function(value) {
      check(done, function() {
        expect( value ).to.have.property("progress", 0.9);
      });
    }).done();
    fakeOnDataStream(this.url, 0.9);
  });

  it("handles HTTPClient options", function(done) {
    var test = this;
    FileLoader.download(this.url, { username: "bob" }).then(function() {
      check(done, function() {
        sinon.assert.calledWith(test.createClientSpy, sinon.match.has("username", "bob"));
      });
    }).done();

    fakeOnLoad(this.url, this.response);
  });

  describe("Redirects", function() {
    beforeEach(function() {
      this.response.getResponseHeader = sinon.stub()
        .withArgs("Location").returns("test_location");
    });

    it("does not use the built-in autoRedirect option", function(done) {
      var test = this;
      FileLoader.download("a").done();
      Q.delay(fakeTimeout).then(function() {
        check(done, function() {
          sinon.assert.calledWith(test.createClientSpy, sinon.match.has("autoRedirect", false));
        });
      });
    });

    it("uses the built-in cache option", function(done) {
      var test = this;
      FileLoader.download("a").done();
      Q.delay(fakeTimeout).then(function() {
        check(done, function() {
          sinon.assert.calledWith(test.createClientSpy, sinon.match.has("cache", true));
        });
      });
    });

    function fakeRedirectedOnLoad(index, response) {
      Q.delay(fakeTimeout).then(function() {
        Ti.Network._requests[index].onload.call(response);
      });
    }

    function testRedirect(done, redirectCode, redirectHops, asserts) {
      var hops, worker = Q(), test = this;

      function chainNextStatus(index, status) {
        worker
          .delay(fakeTimeout)
          .then(function() {
            test.response.status = status;
            Ti.Network._requests[index].onload.call(test.response);
          });
      }

      var downloadPromise = FileLoader.download(this.url)
        .then(function() {
          check(done, asserts);
        });

      for (hops = 0; hops < redirectHops; hops++) {
        chainNextStatus(hops, redirectCode);
      }

      chainNextStatus(hops, 200);

      return downloadPromise;
    }

    [300, 301, 302, 305, 306, 307].forEach(function(redirectCode) {
      describe(redirectCode + " redirect", function() {
        it("uses the location header and trys again", function(done) {
          var test = this;
          testRedirect.call(this, done, redirectCode, 1, function() {
            sinon.assert.calledTwice(test.createClientSpy);
            expect( Ti.Network._requestURLs ).to.have.property("test_location");
          }).fail(function(err) {
            done(new AssertionError("expected promise to be fulfilled: " + err));
          }).done();
        });
      });
    });

    it("handles more then one redirect", function(done) {
      var test = this;
      testRedirect.call(this, done, 302, 3, function() {
        // Three 302 hops + One 200 response = 4
        sinon.assert.callCount(test.createClientSpy, 4);
        expect( Ti.Network._requestURLs ).to.have.property("test_location");
      }).fail(function(err) {
        done(new AssertionError("expected promise to be fulfilled: " + err));
      }).done();
    });

    it("will not allow more then max redirects", function(done) {
      var test = this;
      testRedirect.call(this, done, 302, 6, function() {
        throw new AssertionError("expected promise to be rejected");
      }).fail(function(reason) {
        check(done, function() {
          expect( reason ).to.match(/max/i);
        });
      }).done();
    });
  });
});
<commit_msg>Fix typos/spelling in spec definitions<commit_after>/* jshint expr:true */
require("./support/titanium");
var check          = require("./support/asyncCheck");
var sinon          = require("sinon");
var chai           = require("chai");
var expect         = chai.expect;
var AssertionError = chai.AssertionError;
var FileLoader     = require("file_loader");
var Q              = require("q");
var fakeTimeout    = 10;

function fakeOnError(url, response) {
  Q.delay(fakeTimeout).then(function() {
    Ti.Network._requestURLs[url].onerror({error: response});
  });
}

function fakeOnLoad(url, response) {
  Q.delay(fakeTimeout).then(function() {
    Ti.Network._requestURLs[url].onload.call(response);
  });
}

function fakeOnDataStream(url, response) {
  Q.delay(fakeTimeout).then(function() {
    Ti.Network._requestURLs[url].ondatastream({progress: response});
  });
}

describe("FileLoader#download", function() {
  var sandbox = sinon.sandbox.create();
  this.timeout(200);

  before(function() {
    // Use the silly mocking system provided by mockti
    Ti.Network.fakeRequests = true;
    Ti.Network.online = true;
  });

  after(function() {
    Ti.Network.fakeRequests = false;
  });

  beforeEach(function() {
    this.test_data = "test data";
    this.response = {
      status:       200,
      responseData: this.test_data
    };
    this.url = "http://example.com/test_file.png";

    this.fileWriteStub   = sandbox.stub(FileLoader.File.prototype, "write").returns(true);
    this.fileExistsStub  = sandbox.stub(FileLoader.File.prototype, "exists");
    this.fileExpiredStub = sandbox.stub(FileLoader.File.prototype, "expired");
    this.createClientSpy = sandbox.spy(Ti.Network, "createHTTPClient");

    FileLoader.setupTaskStack(); // Force a fresh queue for testing
  });

  afterEach(function() {
    sandbox.restore();
    Ti.Network.online = true;
    Ti.Network._clear();
  });

  it("rejects the promise when network unavailable", function(done) {
    var test = this;
    Ti.Network.online = false;
    FileLoader.download("http://test.example.com/image.png")
      .fail(function(reason) {
        check(done, function() {
          sinon.assert.notCalled(test.createClientSpy);
          expect( reason ).to.match(/offline/i);
        });
      }).done();
  });

  it("rejects the promise when there is a network error", function(done) {
    FileLoader.download(this.url)
      .then(function(val) {
        done(new AssertionError("expected promise to be rejected (" + val + ")"));
      }, function(reason) {
        check(done, function() {
          expect( reason ).to.have.property("error", "test_error");
        });
      }).done();
    fakeOnError(this.url, "test_error");
  });

  it("resolves the promise when file data has been written", function(done) {
    FileLoader.download(this.url)
      .then(function(value) {
        check(done, function() {
          expect( value ).to.be.an.instanceof(FileLoader.File);
        });
      }).done();
    fakeOnLoad(this.url, this.response);
  });

  describe("with cached files", function() {
    beforeEach(function() {
      var test_file = FileLoader.File.fromURL(this.url);
      test_file.md5 = Ti.Utils.md5HexDigest(this.test_data);
      test_file.save();

      this.fileExistsStub.returns(true);
    });

    it("resolves when file is cached and not expired", function(done) {
      var test = this;
      this.fileExpiredStub.returns(false);

      FileLoader.download(this.url).then(function(value) {
        check(done, function() {
          sinon.assert.notCalled(test.createClientSpy);
          sinon.assert.notCalled(test.fileWriteStub);
        });
      }).done();
    });

    it("requests new file when cache is expired", function(done) {
      var test = this;
      this.fileExpiredStub.returns(true);
      this.response.responseData = "changed_data";

      FileLoader.download(this.url).then(function(value) {
        check(done, function() {
          sinon.assert.called(test.createClientSpy);
          sinon.assert.called(test.fileWriteStub);
        });
      }).done();

      fakeOnLoad(this.url, this.response);
    });

    it("does not write file when data has not changed", function(done) {
      var test = this;
      this.fileExpiredStub.returns(true);

      FileLoader.download(this.url).then(function(value) {
        check(done, function() {
          sinon.assert.called(test.createClientSpy);
          sinon.assert.notCalled(test.fileWriteStub);
        });
      }).done();

      fakeOnLoad(this.url, this.response);
    });
  });

  it("queues requests with a throttle limit", function(done) {
    var test = this;

    FileLoader.download("a");
    FileLoader.download("b");
    FileLoader.download("c");
    FileLoader.download("d");
    FileLoader.download("e");

    Q.delay(fakeTimeout).then(function() {
      check(done, function() {
        sinon.assert.callCount(test.createClientSpy, Ti.App.cache_requests);
      });
    });
  });

  // FIXME: This feature has been removed and needs to be reinvented.
  it.skip("notifies promise while receiving network data", function(done) {
    var test = this;
    FileLoader.download(this.url).progress(function(value) {
      check(done, function() {
        expect( value ).to.have.property("progress", 0.9);
      });
    }).done();
    fakeOnDataStream(this.url, 0.9);
  });

  it("handles HTTPClient options", function(done) {
    var test = this;
    FileLoader.download(this.url, { username: "bob" }).then(function() {
      check(done, function() {
        sinon.assert.calledWith(test.createClientSpy, sinon.match.has("username", "bob"));
      });
    }).done();

    fakeOnLoad(this.url, this.response);
  });

  describe("Redirects", function() {
    beforeEach(function() {
      this.response.getResponseHeader = sinon.stub()
        .withArgs("Location").returns("test_location");
    });

    it("does not use the built-in autoRedirect option", function(done) {
      var test = this;
      FileLoader.download("a").done();
      Q.delay(fakeTimeout).then(function() {
        check(done, function() {
          sinon.assert.calledWith(test.createClientSpy, sinon.match.has("autoRedirect", false));
        });
      });
    });

    it("uses the built-in cache option (304 redirect support)", function(done) {
      var test = this;
      FileLoader.download("a").done();
      Q.delay(fakeTimeout).then(function() {
        check(done, function() {
          sinon.assert.calledWith(test.createClientSpy, sinon.match.has("cache", true));
        });
      });
    });

    function fakeRedirectedOnLoad(index, response) {
      Q.delay(fakeTimeout).then(function() {
        Ti.Network._requests[index].onload.call(response);
      });
    }

    function testRedirect(done, redirectCode, redirectHops, asserts) {
      var hops, worker = Q(), test = this;

      function chainNextStatus(index, status) {
        worker
          .delay(fakeTimeout)
          .then(function() {
            test.response.status = status;
            Ti.Network._requests[index].onload.call(test.response);
          });
      }

      var downloadPromise = FileLoader.download(this.url)
        .then(function() {
          check(done, asserts);
        });

      for (hops = 0; hops < redirectHops; hops++) {
        chainNextStatus(hops, redirectCode);
      }

      chainNextStatus(hops, 200);

      return downloadPromise;
    }

    [300, 301, 302, 305, 306, 307].forEach(function(redirectCode) {
      describe(redirectCode + " redirect", function() {
        it("uses the location header and trys again", function(done) {
          var test = this;
          testRedirect.call(this, done, redirectCode, 1, function() {
            sinon.assert.calledTwice(test.createClientSpy);
            expect( Ti.Network._requestURLs ).to.have.property("test_location");
          }).fail(function(err) {
            done(new AssertionError("expected promise to be fulfilled: " + err));
          }).done();
        });
      });
    });

    it("handles more then one redirect", function(done) {
      var test = this;
      testRedirect.call(this, done, 302, 3, function() {
        // Three 302 hops + One 200 response = 4
        sinon.assert.callCount(test.createClientSpy, 4);
        expect( Ti.Network._requestURLs ).to.have.property("test_location");
      }).fail(function(err) {
        done(new AssertionError("expected promise to be fulfilled: " + err));
      }).done();
    });

    it("will not allow more then max redirects", function(done) {
      var test = this;
      testRedirect.call(this, done, 302, 6, function() {
        throw new AssertionError("expected promise to be rejected");
      }).fail(function(reason) {
        check(done, function() {
          expect( reason ).to.match(/max/i);
        });
      }).done();
    });
  });
});
<|endoftext|>


<commit_before>/*
    Copyright (C) 2008 Tobias S. Josefowitz

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

		    GNU GENERAL PUBLIC LICENSE
		       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

		    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
*/

// =======================================================================
// =======================================================================
// __                                          .
// | \   _   __     ._ _   __  ._  _|_  _  _|_    _  ._
// |  ) / \ /   | | | | | /__) | \  |  / |  |  | / \ | \
// |_/  \_/ \__ |_|_| | | \___ | (_ |_ \_|_ |_ |_\_/ | (_
//
// =======================================================================
// everybody complains when there is none, so now better read it!!
// =======================================================================
//
// this mapping class uses typeof(x) + ";" + x; as hashing method.
// this means that strings, booleans and numbers can safely be used as indices.
// additionally, any other types where this gives sufficient distinction can
// be used totally or at least partially, e.g. arrays: arrays of numbers and
// booleans and strings which do NOT have "," in them or are "true" or "false"
// can be used safely.
//
// an example of indices that do not work well (together):
// var mapping = new Mapping();
// mapping.set([2,3], "hey");
// mapping.get(["2,3"]); // returns "hey" which might not be desired.
//
// you get the picture.
//
// =======================================================================
// =======================================================================

/**
 * Flexible mapping/dictionary class that allows for arbitrary key types.
 * @constructor
 */
function Mapping() {
	if (arguments.length & 1) throw("odd number of mapping members.");
	this.n = new Object();
	this.m = new Object();
	this.length = 0;
	for (var i = 0; i < arguments.length; i += 2) {
		this.set(arguments[i], arguments[i+1]);
	}
}
Mapping.prototype = {
	constructor : Mapping,
	id_cache : new Object(), // shared cached for all implementations
	get_new_id : function(o) {
		var a = new Array();
		// put some logic here to tune length of id and amount of items
		for (var i = 0; i < 10; i++) {
			a.push(Math.floor(Math.random() * 255));
		}

		var id = String.fromCharCode.apply(window, a);

		if (this.id_cache.hasOwnProperty(id)) {
			return this.get_new_id();
		}

		return id;
	},
    sfy : function(key) { // sfy ==> stringify
		// better use if (key.__proto__ == String.prototype) { ??
		// also there is somewhere something like isPrototypeOf(proto, instance). what about that?
		// for sure subclasses of String shouldn't be matched here.
		// on the other hand, subclasses of strings are strings. i made up
		// my mind and now think it's the right thing to adhere to that.
		if (typeof(key) == "object") {
			// not sure if we need this
			if (key instanceof String) {
				return "string;" + key;
			}
			if (key.hasOwnProperty("__id")) {
				return key["__id"];
			}

			var id = this.get_new_id();
			key["__id"] = id;
			return id;
		} else {
			return typeof(key) + ";" + key;
		}
    },

	/**
	 * Set an entry.
	 */
    set : function(key, val) {
		var key2 = this.sfy(key);

		if (!this.m.hasOwnProperty(key2)) {
			this.length++;
		}

		this.m[key2] = val;
		this.n[key2] = key;
    },

	/**
	 * Get an entry.
	 */
    get : function(key) {
		return this.m[this.sfy(key)];
    },

    // IE doesn't like this being called "delete", so, beware!
	/**
	 * Remove an entry.
	 */
    remove : function(key) {
		var key2 = this.sfy(key);

		if (this.hasIndex(key)) {
			this.length--;
		}

		delete this.m[key2];
		delete this.n[key2];
    },

	/**
	 * Indices of the mapping.
	 * @returns An array of indices.
	 */
    indices : function() {
		var ret = new Array();

		for (var i in this.n) {
			ret.push(this.n[i]);
		}

		return ret;
    },

	/**
	 * Values of the mapping.
	 * @returns An array of values.
	 */
    values : function() {
		var ret = new Array();

		for (var i in this.m) {
			ret.push(this.m[i]);
		}

		return ret;
    },

	/**
	 * Loops over all entries in the mapping and calls cb for each pair of (key, value).
	 */
    forEach : function(cb, context) {
		for (var i in this.n) {
			if (context) {
				cb.call(context, this.n[i], this.m[i]);
			} else {
				cb(this.n[i], this.m[i]);
			}
		}
    },

    toString : function() {
		return "Mapping(:" + this.length + ")";
    },

	/**
	 * Returns true if an entry with the given key exists.
	 */
    hasIndex : function(key) {
		return this.m.hasOwnProperty(this.sfy(key));
    },

    reset : function() {
		this.m = new Object();
		this.n = new Object();
		this.length = 0;
    }
};

// =======================================================================
// if your head hurts now, you should've just read the documentation.
// =======================================================================
<commit_msg>no weird chars. safari does not like it<commit_after>/*
    Copyright (C) 2008 Tobias S. Josefowitz

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

		    GNU GENERAL PUBLIC LICENSE
		       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

		    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
*/

// =======================================================================
// =======================================================================
// __                                          .
// | \   _   __     ._ _   __  ._  _|_  _  _|_    _  ._
// |  ) / \ /   | | | | | /__) | \  |  / |  |  | / \ | \
// |_/  \_/ \__ |_|_| | | \___ | (_ |_ \_|_ |_ |_\_/ | (_
//
// =======================================================================
// everybody complains when there is none, so now better read it!!
// =======================================================================
//
// this mapping class uses typeof(x) + ";" + x; as hashing method.
// this means that strings, booleans and numbers can safely be used as indices.
// additionally, any other types where this gives sufficient distinction can
// be used totally or at least partially, e.g. arrays: arrays of numbers and
// booleans and strings which do NOT have "," in them or are "true" or "false"
// can be used safely.
//
// an example of indices that do not work well (together):
// var mapping = new Mapping();
// mapping.set([2,3], "hey");
// mapping.get(["2,3"]); // returns "hey" which might not be desired.
//
// you get the picture.
//
// =======================================================================
// =======================================================================

/**
 * Flexible mapping/dictionary class that allows for arbitrary key types.
 * @constructor
 */
function Mapping() {
	if (arguments.length & 1) throw("odd number of mapping members.");
	this.n = new Object();
	this.m = new Object();
	this.length = 0;
	for (var i = 0; i < arguments.length; i += 2) {
		this.set(arguments[i], arguments[i+1]);
	}
}
Mapping.prototype = {
	constructor : Mapping,
	id_cache : new Object(), // shared cached for all implementations
	get_new_id : function(o) {
		var a = new Array();
		// put some logic here to tune length of id and amount of items
		for (var i = 0; i < 10; i++) {
			a.push('A' + Math.floor(Math.random() * ('A'-'Z')));
		}

		var id = String.fromCharCode.apply(window, a);

		if (this.id_cache.hasOwnProperty(id)) {
			return this.get_new_id();
		}

		return id;
	},
    sfy : function(key) { // sfy ==> stringify
		// better use if (key.__proto__ == String.prototype) { ??
		// also there is somewhere something like isPrototypeOf(proto, instance). what about that?
		// for sure subclasses of String shouldn't be matched here.
		// on the other hand, subclasses of strings are strings. i made up
		// my mind and now think it's the right thing to adhere to that.
		if (typeof(key) == "object") {
			// not sure if we need this
			if (key instanceof String) {
				return "string;" + key;
			}
			if (key.hasOwnProperty("__id")) {
				return key["__id"];
			}

			var id = this.get_new_id();
			key["__id"] = id;
			return id;
		} else {
			return typeof(key) + ";" + key;
		}
    },

	/**
	 * Set an entry.
	 */
    set : function(key, val) {
		var key2 = this.sfy(key);

		if (!this.m.hasOwnProperty(key2)) {
			this.length++;
		}

		this.m[key2] = val;
		this.n[key2] = key;
    },

	/**
	 * Get an entry.
	 */
    get : function(key) {
		return this.m[this.sfy(key)];
    },

    // IE doesn't like this being called "delete", so, beware!
	/**
	 * Remove an entry.
	 */
    remove : function(key) {
		var key2 = this.sfy(key);

		if (this.hasIndex(key)) {
			this.length--;
		}

		delete this.m[key2];
		delete this.n[key2];
    },

	/**
	 * Indices of the mapping.
	 * @returns An array of indices.
	 */
    indices : function() {
		var ret = new Array();

		for (var i in this.n) {
			ret.push(this.n[i]);
		}

		return ret;
    },

	/**
	 * Values of the mapping.
	 * @returns An array of values.
	 */
    values : function() {
		var ret = new Array();

		for (var i in this.m) {
			ret.push(this.m[i]);
		}

		return ret;
    },

	/**
	 * Loops over all entries in the mapping and calls cb for each pair of (key, value).
	 */
    forEach : function(cb, context) {
		for (var i in this.n) {
			if (context) {
				cb.call(context, this.n[i], this.m[i]);
			} else {
				cb(this.n[i], this.m[i]);
			}
		}
    },

    toString : function() {
		return "Mapping(:" + this.length + ")";
    },

	/**
	 * Returns true if an entry with the given key exists.
	 */
    hasIndex : function(key) {
		return this.m.hasOwnProperty(this.sfy(key));
    },

    reset : function() {
		this.m = new Object();
		this.n = new Object();
		this.length = 0;
    }
};

// =======================================================================
// if your head hurts now, you should've just read the documentation.
// =======================================================================
<|endoftext|>


<commit_before>//console.log("INFO\t: loading Measure");
var child_process = require('child_process');
var path = require("path");
var fs = require("fs");
var DVSFactory = require("./lib/DVSFactory.js");
var LPPCurve = require("./lib/LPPCurve.js");

module.exports.Measure = (function() {
    ///////////////////////// private instance variables

    ////////////////// constructor
    function Measure(images, firesight, options) {
        var that = this;
        options = options || {};
        options.model = options.model || {};

        that.model = options.model;
        that.model.available = true;
        if ((that.images = images) == null) throw new Error("images is required");
        if ((that.firesight = firesight) == null) throw new Error("firesight is required");
        if ((that.firestep = images.firestep) == null) throw new Error("firestep is required");
        if ((that.camera = images.camera) == null) throw new Error("camera is required");;

        return that;
    }

    Measure.prototype.isAvailable = function() {
        var that = this;
        return that.model.available === true;
    }
    Measure.prototype.jogPrecision = function(camName, options, onSuccess, onFail) {
        var that = this;
        options = options || {};
        var jog = options.jog || 10;
        var n = options.n || 2;
        var testPrecision = function() {
            var urlPath = that.images.savedImage(camName);
            var x = that.firestep.model.mpo.x;
            var y = that.firestep.model.mpo.y;
            var z = that.firestep.model.mpo.z;
            var cmd = [];
            var dx = Math.random() < 0.5 ? -jog : jog;
            var dy = Math.random() < 0.5 ? -jog : jog;
            for (var i = 0; i < n; i++) {
                cmd.push({
                    movxr: dx
                });
            }
            for (var i = 0; i < n; i++) {
                cmd.push({
                    movyr: dy
                });
            }
            cmd.push({
                mov: {
                    x: x,
                    y: y,
                    z: z
                }
            });
            cmd.push({
                mpo: "",
                dpyds: 12,
                idl: 200
            }); // idl allows camera auto-exposure to settle
            that.firestep.send(cmd, function() {
                that.firesight.calcOffset(camName, function(offset) {
                    var result = {
                        xErr: offset.dx == null ? "unknown" : offset.dx,
                        yErr: offset.dy == null ? "unknown" : offset.dy,
                        dx: dx,
                        dy: dy,
                        n: n,
                    };
                    console.log("INFO\t: jogPrecision() => " + JSON.stringify(result));
                    onSuccess(result);
                }, function(error) {
                    onFail(error);
                });
            });
        }
        if (that.images.hasSavedImage(camName)) {
            testPrecision();
        } else {
            that.images.save(camName, testPrecision, function(error) {
                onFail(error);
            });
        }
    }
    Measure.prototype.lppPrecision = function(camName, options, onSuccess, onFail) {
        var that = this;
        options = options || {};
        var jog = options.jog || 10;
        var n = options.n || 2;
        var z1 = options.z1 || 30;
        var z2 = options.z2 || 0;
        var x = that.firestep.model.mpo.x;
        var y = that.firestep.model.mpo.y;
        var z = that.firestep.model.mpo.z;
        var testLPP = function() {
            var urlPath = that.images.savedImage(camName);
            var cmd = [];
            var dx = Math.random() < 0.5 ? -jog : jog;
            var dy = Math.random() < 0.5 ? -jog : jog;
            for (var i = 0; i < n; i++) {
                cmd.push({
                    movxr: dx
                });
            }
            for (var i = 0; i < n; i++) {
                cmd.push({
                    movyr: dy
                });
            }
            cmd.push({
                mov: {
                    xr: -dx,
                    yr: -dy,
                }
            });
            that.firestep.send(cmd, function() {
                that.firestep.moveLPP(x, y, z, function() {
                    that.firesight.calcOffset(camName, function(offset) {
                        var result = {
                            xErr: offset.dx == null ? "unknown" : offset.dx,
                            yErr: offset.dy == null ? "unknown" : offset.dy,
                            dx: dx,
                            dy: dy,
                            n: n,
                        };
                        console.log("INFO\t: lppPrecision() => " + JSON.stringify(result));
                        onSuccess(result);
                    }, function(error) {
                        onFail(error);
                    });
                });
            });
        }
        that.firestep.moveLPP(x, y, z, function() {
            if (that.images.hasSavedImage(camName)) {
                testLPP();
            } else {
                that.images.save(camName, testLPP, function(error) {
                    onFail(error);
                });
            }
        }, function(error) {
            onFail(error);
        });
    }

    return Measure;
})();
<commit_msg>moveLPP<commit_after>//console.log("INFO\t: loading Measure");
var child_process = require('child_process');
var path = require("path");
var fs = require("fs");
var DVSFactory = require("./lib/DVSFactory.js");
var LPPCurve = require("./lib/LPPCurve.js");

module.exports.Measure = (function() {
    ///////////////////////// private instance variables

    ////////////////// constructor
    function Measure(images, firesight, options) {
        var that = this;
        options = options || {};
        options.model = options.model || {};

        that.model = options.model;
        that.model.available = true;
        if ((that.images = images) == null) throw new Error("images is required");
        if ((that.firesight = firesight) == null) throw new Error("firesight is required");
        if ((that.firestep = images.firestep) == null) throw new Error("firestep is required");
        if ((that.camera = images.camera) == null) throw new Error("camera is required");;

        return that;
    }

    Measure.prototype.isAvailable = function() {
        var that = this;
        return that.model.available === true;
    }
    Measure.prototype.jogPrecision = function(camName, options, onSuccess, onFail) {
        var that = this;
        options = options || {};
        var jog = options.jog || 10;
        var n = options.n || 2;
        var testPrecision = function() {
            var urlPath = that.images.savedImage(camName);
            var x = that.firestep.model.mpo.x;
            var y = that.firestep.model.mpo.y;
            var z = that.firestep.model.mpo.z;
            var cmd = [];
            var dx = Math.random() < 0.5 ? -jog : jog;
            var dy = Math.random() < 0.5 ? -jog : jog;
            for (var i = 0; i < n; i++) {
                cmd.push({
                    movxr: dx
                });
            }
            for (var i = 0; i < n; i++) {
                cmd.push({
                    movyr: dy
                });
            }
            cmd.push({
                mov: {
                    x: x,
                    y: y,
                    z: z
                }
            });
            cmd.push({
                mpo: "",
                dpyds: 12,
                idl: 200
            }); // idl allows camera auto-exposure to settle
            that.firestep.send(cmd, function() {
                that.firesight.calcOffset(camName, function(offset) {
                    var result = {
                        xErr: offset.dx == null ? "unknown" : offset.dx,
                        yErr: offset.dy == null ? "unknown" : offset.dy,
                        dx: dx,
                        dy: dy,
                        n: n,
                    };
                    console.log("INFO\t: jogPrecision() => " + JSON.stringify(result));
                    onSuccess(result);
                }, function(error) {
                    onFail(error);
                });
            });
        }
        if (that.images.hasSavedImage(camName)) {
            testPrecision();
        } else {
            that.images.save(camName, testPrecision, function(error) {
                onFail(error);
            });
        }
    }
    Measure.prototype.lppPrecision = function(camName, options, onSuccess, onFail) {
        var that = this;
        options = options || {};
        var jog = options.jog || 10;
        var n = options.n || 2;
        var z1 = options.z1 || 30;
        var z2 = options.z2 || 0;
        var x = that.firestep.model.mpo.x;
        var y = that.firestep.model.mpo.y;
        var z = that.firestep.model.mpo.z;
        var testLPP = function() {
            var urlPath = that.images.savedImage(camName);
            var cmd = [];
            var dx = Math.random() < 0.5 ? -jog : jog;
            var dy = Math.random() < 0.5 ? -jog : jog;
            for (var i = 0; i < n; i++) {
                that.firestep.send({
                    movxr: dx
                });
            }
            for (var i = 0; i < n; i++) {
                that.firestep.send({
                    movyr: dy
                });
            }
            var movxyz = {mov:{x:x,y:y,z:z}};
            that.firestep.send(movxyz, function() {
                console.log("DEBUG\t: Measure.lppPrecison() calcOffset");
                that.firesight.calcOffset(camName, function(offset) {
                    var result = {
                        xErr: offset.dx == null ? "unknown" : offset.dx,
                        yErr: offset.dy == null ? "unknown" : offset.dy,
                        dx: dx,
                        dy: dy,
                        n: n,
                    };
                    console.log("INFO\t: Measure.lppPrecision() => " + JSON.stringify(result));
                    onSuccess(result);
                }, function(error) {
                    onFail(error);
                });
            });
        }
        that.firestep.send(movxyz, function() {
            if (that.images.hasSavedImage(camName)) {
                testLPP();
            } else {
                console.log("INFO\t: Measure.lppPrecision() saving image");
                that.images.save(camName, testLPP, function(error) {
                    onFail(error);
                });
            }
        }, function(error) {
            onFail(error);
        });
    }

    return Measure;
})();
<|endoftext|>