<commit_before>
// LinkRegExp -- Regular

// var LinkRegExp = RegExp(''
//   + '\b'                      // words
//   + '('                       // Capture 1: entire matched URL
//   +   '(?:'
//   +     'https?://'                   // http or https protocol
//   +     '|'                           // or
//   +     'www\d{0,3}[.]'               // "www.", "www1.", "www2." … "www999."
//   +     '|'                           // or
//   +     '[a-z0-9.\-]+[.][a-z]{2,4}/'  // domain name followed by a slash
//   +   ')'
//   +   '(?:'                       // One or more:
//   +     '[^\s()<>]+'                  // Run of non-space, non-()<>
//   +     '|'                           // or
//   +     '\(([^\s()<>]+|(\([^\s()<>]+\)))*\)' // balanced parens, up to 2 levels
//   +   ')+'
//   +   '(?:'                       // End with:
//   +     '\(([^\s()<>]+|(\([^\s()<>]+\)))*\)'  // balanced parens, up to 2 levels
//   +     '|'                               //   or
//   +     '[^\s`!()\[\]{};:\'".,<>?«»“”‘’]'  // not these punct chars
//   +   ')'
//   + ')',
//   'i'
// );
//

var LinkRegExp =
  RegExp('http://[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|]', 'i');

// LinkValidationInterface -- for determining whether links match.
// ---------------------------------------------------------------

var LinkValidationInterface = {

  // **validRegexes** list of valid LinkRegexes
  validRegexes: [
    LinkRegExp
  ],

  // urlMatches: returns whether a given url matches this Shell.
  // determined by the validRegexes above.
  urlMatches: function(url) {
    return _(this.validRegexes).find(function(re) {
      return re.test(url);
    });
  },

  isValidLink: function(link) {
    return !!this.urlMatches(link);
  },

};

acorn.util.isValidLink =
  _.bind(LinkValidationInterface.isValidLink, LinkValidationInterface);

// **acorn.shellForLink** returns a shell to match given link
// ----------------------------------------------------------

acorn.shellForLink = function(link, options) {

  var location = parseUrl(link);

  // filter out shells that don't derive from LinkShell.
  var linkShells = _(acorn.shells).filter(function (shell) {
    return derives(shell, acorn.shells.LinkShell);
  });

  // filter out shells that don't match this link.
  var matchingShells = _(linkShells).filter(function (linkShell) {
    return linkShell.prototype.isValidLink(location);
  });

  // reduce to the most specific shell (in terms of inheritance).
  var bestShell = _(matchingShells).reduce(function(bestShell, shell) {
    return derives(bestShell, shell) ? bestShell : shell;
  }, acorn.shells.LinkShell);

  // if all else fails, use LinkShell.
  bestShell = bestShell || acorn.shells.LinkShell;

  // setup options
  options = _.extend({}, options);
  options.data = {'link': link};
  options.location = location;

  return new bestShell(options);
};

// LinkShellAPI -- interface for determining whether links match.
// -------------------------------------------------------------------

var LinkShellAPI = {

  shellid: 'acorn.LinkShell',

  // The cannonical type of this media. One of `acorn.types`.
  type: 'link',

  // **link** is the main data kept by LinkShells
  link: function(link) {
    if (link !== undefined)
      this.data.link = link;
    return this.data.link;
  },

  // **title** returns a simple title of the shell
  title: function() { return this.link(); },

  // **description** returns a simple description of the shell
  description: function() { return ''; },

  // **thumbnailLink** returns the link to the thumbnail image
  thumbnailLink: function(link) {
    if (link !== undefined)
      this.data.thumbnailLink = link;
    return this.data.thumbnailLink;
  },

  extraInfoLink: function() { return ''; },

  // Retrieve extra information. Nothing by default.
  retrieveExtraInfo: function(callback) {
    callback = callback || function() {};

    var extraInfoLink = this.extraInfoLink();
    if (!extraInfoLink || this.extraInfo) {
      return callback();
    }

    var self = this;
    $.getJSON(extraInfoLink, function(data) {
      self.extraInfo = data;
      callback();
    });
  },

};

_.extend(LinkShellAPI, LinkValidationInterface);

// acorn.shells.LinkShell -- a shell that links to media and embeds it.
// --------------------------------------------------------------------

var LinkShell = acorn.shells.LinkShell = Shell.extend(LinkShellAPI);

// ContentView -- Simply displays the link text for now.
// TODO: thumbnail the website? embed the webpage in iframe?
// ---------------------------------------------------------

LinkShell.ContentView = Shell.ContentView.extend({

  initialize: function() {
    Shell.ContentView.prototype.initialize.call(this);

    assert(this.shell.link, 'No link provided to LinkShell.');

    this.location = this.options.location || parseUrl(this.shell.link());

    assert(this.shell.isValidLink(this.location),
      'Link provided does not match ' + this.shell.type);

  },

  render: function() {
    var link = this.shell.link();
    this.$el.append(iframe(link, 'link-iframe'));
  },

});

// LinkShell.EditView -- a text field for the link.
// --------------------------------------------------

LinkShell.EditView = Shell.EditView.extend({

  events: {
    'click button#add': 'onClickAdd',
  },

  template: _.template('\

\
      \

\

\

\

\
    <button class="btn btn-large" id="add">Add Link</button>\
  '),

  initialize: function() {
    Shell.EditView.prototype.initialize.call(this);

    this.linkView = new Backbone.components.EditableTextCmp.View({
      textFn: this.link,
      placeholder: 'Enter Link',
      validate: _.bind(this.validateLink, this),
      addToggle: true,
      onSave: _.bind(this.generateThumbnailLink, this),
    });

  },

  validateLink: function(link) {
    link = parseUrl(link).toString();
    if (acorn.util.isValidLink(link))
      return false;

    return "invalid link."
  },

  link: function(link) {
    if (link) {
      link = parseUrl(link).toString();
      this.shell.link(link);
      var s = acorn.shellForLink(link, {shell: this.shell});

      // if the shellid has changed, we need to swap shells entirely.
      if (s.shellid != this.shell.data.shell)
        this.trigger('swap:shell', s.data);

      // else, announce that the shell has changed.
      else
        this.trigger('change:shell', this.shell);
    }
    return this.shell.link();
  },

  render: function() {
    Shell.EditView.prototype.render.call(this);

    // set thumbnail src
    var tlink = this.shell.thumbnailLink();
    this.$el.find('#thumbnail').attr('src', tlink);

    this.linkView.setElement(this.$el.find('#link'));
    this.linkView.render();

    if (!this.link())
      this.linkView.edit();

    if (this.isSubShellView())
      this.$el.find('button#add').hide();
  },

  generateThumbnailLink: function(callback) {
    callback = callback || function() {};

    var self = this;
    var bounds = '600x600';
    var req_url = '/url2png/' + bounds + '/' + this.shell.link();
    $.ajax(req_url, {
      success: function(data) {
        callback(data);
      },
      error: function() {
        acorn.alert('Error: failed to generate thumbnail for link.',
                    'alert-error');
      }
    });
  },

  // **finalizeEdit** finish all edits.
  finalizeEdit: function() {
    if (this.linkView.isEditing)
      this.linkView.save();
  },

  // **onClickAdd** add another link
  onClickAdd: function() {

    var multiShell = new acorn.shells.MultiShell();
    multiShell.addShell(this.shell);
    multiShell.addShell(new acorn.shellForLink(''));
    this.trigger('swap:shell', multiShell.data);
  },

});

// Register the shell with the acorn object.
acorn.registerShell(LinkShell);
<commit_msg>f/LinkShell: fixed link regexp to match https.<commit_after>
// LinkRegExp -- Regular

// var LinkRegExp = RegExp(''
//   + '\b'                      // words
//   + '('                       // Capture 1: entire matched URL
//   +   '(?:'
//   +     'https?://'                   // http or https protocol
//   +     '|'                           // or
//   +     'www\d{0,3}[.]'               // "www.", "www1.", "www2." … "www999."
//   +     '|'                           // or
//   +     '[a-z0-9.\-]+[.][a-z]{2,4}/'  // domain name followed by a slash
//   +   ')'
//   +   '(?:'                       // One or more:
//   +     '[^\s()<>]+'                  // Run of non-space, non-()<>
//   +     '|'                           // or
//   +     '\(([^\s()<>]+|(\([^\s()<>]+\)))*\)' // balanced parens, up to 2 levels
//   +   ')+'
//   +   '(?:'                       // End with:
//   +     '\(([^\s()<>]+|(\([^\s()<>]+\)))*\)'  // balanced parens, up to 2 levels
//   +     '|'                               //   or
//   +     '[^\s`!()\[\]{};:\'".,<>?«»“”‘’]'  // not these punct chars
//   +   ')'
//   + ')',
//   'i'
// );
//

var LinkRegExp =
  RegExp('https?://[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|]',
   'i');

// LinkValidationInterface -- for determining whether links match.
// ---------------------------------------------------------------

var LinkValidationInterface = {

  // **validRegexes** list of valid LinkRegexes
  validRegexes: [
    LinkRegExp
  ],

  // urlMatches: returns whether a given url matches this Shell.
  // determined by the validRegexes above.
  urlMatches: function(url) {
    return _(this.validRegexes).find(function(re) {
      return re.test(url);
    });
  },

  isValidLink: function(link) {
    return !!this.urlMatches(link);
  },

};

acorn.util.isValidLink =
  _.bind(LinkValidationInterface.isValidLink, LinkValidationInterface);

// **acorn.shellForLink** returns a shell to match given link
// ----------------------------------------------------------

acorn.shellForLink = function(link, options) {

  var location = parseUrl(link);

  // filter out shells that don't derive from LinkShell.
  var linkShells = _(acorn.shells).filter(function (shell) {
    return derives(shell, acorn.shells.LinkShell);
  });

  // filter out shells that don't match this link.
  var matchingShells = _(linkShells).filter(function (linkShell) {
    return linkShell.prototype.isValidLink(location);
  });

  // reduce to the most specific shell (in terms of inheritance).
  var bestShell = _(matchingShells).reduce(function(bestShell, shell) {
    return derives(bestShell, shell) ? bestShell : shell;
  }, acorn.shells.LinkShell);

  // if all else fails, use LinkShell.
  bestShell = bestShell || acorn.shells.LinkShell;

  // setup options
  options = _.extend({}, options);
  options.data = {'link': link};
  options.location = location;

  return new bestShell(options);
};

// LinkShellAPI -- interface for determining whether links match.
// -------------------------------------------------------------------

var LinkShellAPI = {

  shellid: 'acorn.LinkShell',

  // The cannonical type of this media. One of `acorn.types`.
  type: 'link',

  // **link** is the main data kept by LinkShells
  link: function(link) {
    if (link !== undefined)
      this.data.link = link;
    return this.data.link;
  },

  // **title** returns a simple title of the shell
  title: function() { return this.link(); },

  // **description** returns a simple description of the shell
  description: function() { return ''; },

  // **thumbnailLink** returns the link to the thumbnail image
  thumbnailLink: function(link) {
    if (link !== undefined)
      this.data.thumbnailLink = link;
    return this.data.thumbnailLink;
  },

  extraInfoLink: function() { return ''; },

  // Retrieve extra information. Nothing by default.
  retrieveExtraInfo: function(callback) {
    callback = callback || function() {};

    var extraInfoLink = this.extraInfoLink();
    if (!extraInfoLink || this.extraInfo) {
      return callback();
    }

    var self = this;
    $.getJSON(extraInfoLink, function(data) {
      self.extraInfo = data;
      callback();
    });
  },

};

_.extend(LinkShellAPI, LinkValidationInterface);

// acorn.shells.LinkShell -- a shell that links to media and embeds it.
// --------------------------------------------------------------------

var LinkShell = acorn.shells.LinkShell = Shell.extend(LinkShellAPI);

// ContentView -- Simply displays the link text for now.
// TODO: thumbnail the website? embed the webpage in iframe?
// ---------------------------------------------------------

LinkShell.ContentView = Shell.ContentView.extend({

  initialize: function() {
    Shell.ContentView.prototype.initialize.call(this);

    assert(this.shell.link, 'No link provided to LinkShell.');

    this.location = this.options.location || parseUrl(this.shell.link());

    assert(this.shell.isValidLink(this.location),
      'Link provided does not match ' + this.shell.type);

  },

  render: function() {
    var link = this.shell.link();
    this.$el.append(iframe(link, 'link-iframe'));
  },

});

// LinkShell.EditView -- a text field for the link.
// --------------------------------------------------

LinkShell.EditView = Shell.EditView.extend({

  events: {
    'click button#add': 'onClickAdd',
  },

  template: _.template('\

\
      \

\

\

\

\
    <button class="btn btn-large" id="add">Add Link</button>\
  '),

  initialize: function() {
    Shell.EditView.prototype.initialize.call(this);

    this.linkView = new Backbone.components.EditableTextCmp.View({
      textFn: this.link,
      placeholder: 'Enter Link',
      validate: _.bind(this.validateLink, this),
      addToggle: true,
      onSave: _.bind(this.generateThumbnailLink, this),
    });

  },

  validateLink: function(link) {
    link = parseUrl(link).toString();
    if (acorn.util.isValidLink(link))
      return false;

    return "invalid link."
  },

  link: function(link) {
    if (link) {
      link = parseUrl(link).toString();
      this.shell.link(link);
      var s = acorn.shellForLink(link, {shell: this.shell});

      // if the shellid has changed, we need to swap shells entirely.
      if (s.shellid != this.shell.data.shell)
        this.trigger('swap:shell', s.data);

      // else, announce that the shell has changed.
      else
        this.trigger('change:shell', this.shell);
    }
    return this.shell.link();
  },

  render: function() {
    Shell.EditView.prototype.render.call(this);

    // set thumbnail src
    var tlink = this.shell.thumbnailLink();
    this.$el.find('#thumbnail').attr('src', tlink);

    this.linkView.setElement(this.$el.find('#link'));
    this.linkView.render();

    if (!this.link())
      this.linkView.edit();

    if (this.isSubShellView())
      this.$el.find('button#add').hide();
  },

  generateThumbnailLink: function(callback) {
    callback = callback || function() {};

    var self = this;
    var bounds = '600x600';
    var req_url = '/url2png/' + bounds + '/' + this.shell.link();
    $.ajax(req_url, {
      success: function(data) {
        callback(data);
      },
      error: function() {
        acorn.alert('Error: failed to generate thumbnail for link.',
                    'alert-error');
      }
    });
  },

  // **finalizeEdit** finish all edits.
  finalizeEdit: function() {
    if (this.linkView.isEditing)
      this.linkView.save();
  },

  // **onClickAdd** add another link
  onClickAdd: function() {

    var multiShell = new acorn.shells.MultiShell();
    multiShell.addShell(this.shell);
    multiShell.addShell(new acorn.shellForLink(''));
    this.trigger('swap:shell', multiShell.data);
  },

});

// Register the shell with the acorn object.
acorn.registerShell(LinkShell);
<|endoftext|>


<commit_before>/**
  * config object
  * {
  *   container: <reference element>, the elemnt in which the slider will be rendered
  *   slider_base_class: <css class>, the class which defines the dimesions of the slider
  *   slider_class: <css class>, the class which contains the slider elent
  *   slider_template: <template>, a template for the slider
  *   onx: <callback>, // optional
  *   ony: <callback>, // optional
  *   onxy: <callback>, // optional
  *   min_x: <number>, // optional
  *   max_x: <number>, // optional
  *   min_y: <number>, // optional
  *   max_y: <number> // optional
  * }
  */

var Slider = function(config)
{
  /* interface */
  this.onx = function(x){};
  this.ony = function(y){};
  this.onxy = function(x, y){};
  //read and write
  this.x;
  this.y;

  /* constructor */
  this._init(config);
};

Slider.prototype = new function()
{
  const UPDATE_INTERVAL = 80;
  this._onmousemoveinterval = function(event)
  {
    if (this._is_active)
    {
      if (this._onxy && !(this.x == this._submitted_x && this.y == this._submitted_y))
        this.onxy(this._submitted_x = this.x, this._submitted_y = this.y);
      if (this._onx && this.x != this._submitted_x)
        this.onx(this._submitted_x = this.x);
      if (this._ony && this.y != this._submitted_y)
        this.ony(this._submitted_y = this.y);
    }
    else
    {
      window.clearInterval(this._interval);
      this._interval = 0;
    }
  }

  this._onmousemove = function(event)
  {
    this._focus_catcher.focus();
    var value = 0, box = this._ref_element.getBoundingClientRect();
    if (this._has_x)
    {
      value = (event.clientX - this._delta_x - box.left) /
              this._pixel_range_x * this._range_x + this._min_x;
      value = value > this._max_x ? this._max_x : value < this._min_x ? this._min_x : value;
      this.x = this._is_invers_x ? this._max_x - value + this._min_x : value;
    }
    if (this._has_y)
    {
      value = (event.clientY - this._delta_y - box.top) /
              this._pixel_range_y * this._range_y + this._min_y;
      value = value > this._max_y ? this._max_y : value < this._min_y ? this._min_y : value;
      this.y = this._is_invers_y ? this._max_y - value + this._min_y : value;
    }
  }

  this._update_y = function(value)
  {
    if (this._is_invers_y)
      value = this._max_y - value + this._min_y;
    this._element.style.top = ((value - this._min_y) / this._range_y * this._pixel_range_y) + "px";
  }

  this._update_x = function(value)
  {
    if (this._is_invers_x)
      value = this._max_x - value + this._min_x;
    this._element.style.left = ((value - this._min_x) / this._range_x * this._pixel_range_x) + "px";
  }

  this._onmousedown = function(event)
  {
    if (!this._interval && !this._is_active)
    {
      if (this._element.contains(event.target))
      {
        var target_box = this._element.getBoundingClientRect();
        this._delta_x = event.clientX - target_box.left - (target_box.width / 2 >> 0);
        this._delta_y = event.clientY - target_box.top - (target_box.height / 2 >> 0);
      }
      else
      {
        this._delta_x = 0;
        this._delta_y = 0;
        this._onmousemove(event);
      }
      document.addEventListener('mousemove', this._onmousemove_bound, false);
      document.addEventListener('mouseup', this._onmouseup_bound, false);
      this._interval = window.setInterval(this._onmousemoveinterval_bound, UPDATE_INTERVAL);
      this._is_active = true;
    }
  }

  this._onmouseup = function(event)
  {
    this._is_active = false;
    document.removeEventListener('mousemove', this._onmousemove_bound, false);
    document.removeEventListener('mouseup', this._onmouseup_bound, false);
  }

  this._onremove = function(event)
  {
    if (event.target.nodeType == 1 && event.target.contains(this._ref_element))
    {
      this._ref_element.removeEventListener('mousedown', this._onmousedown_bound, false);
      document.removeEventListener('DOMNoderemoved', this._onremove_bound, false);
      this._focus_catcher.parentNode.removeChild(this._focus_catcher);
      this._focus_catcher = null;
      this._ref_element = null;
      this._element = null;
      this._onmousedown_bound = null;
      this._onmousemove_bound = null;
      this._onmouseup_bound = null;
      this._onremove_bound = null;
      this._onmousemoveinterval_bound = null;
    }
  }

  this._set_axis = function(axis, min, max, pixel_range)
  {
    this['_has_' + axis] = true;
    this['_min_' + axis] = Math.min(min, max);
    this['_max_' + axis] = Math.max(min, max);
    this['_pixel_range_' + axis] = pixel_range;
    this['_range_' + axis] = Math.abs(max - min);
    this['_is_invers_' + axis] = min > max;
    this['_' + axis] = 0;
    this['_submitted_' + axis] = 0;
    this[axis] = this['_is_invers_' + axis] ? max : min;
  }

  this._init = function(config)
  {
    var
    container = config.container,
    slider_base_class = config.slider_base_class,
    slider_class = config.slider_class,
    box = null;

    if (container instanceof Element)
    {
      container.render(window.templates.slider(slider_base_class, slider_class, config.slider_template));
      this._ref_element = container.getElementsByClassName(slider_base_class)[0];
      this._element = container.getElementsByClassName(slider_class)[0];
      this._focus_catcher = document.documentElement.render(window.templates.slider_focus_catcher());
      box = this._ref_element.getBoundingClientRect();

      if (config.onxy)
      {
        this.onxy = config.onxy;
        this._onxy = true;
        this._set_axis('x', config.min_x, config.max_x, box.width);
        this._set_axis('y', config.min_y, config.max_y, box.height);
      }
      else
      {
        if (config.onx)
        {
          this.onx = config.onx;
          this._onx = true;
          this._set_axis('x', config.min_x, config.max_x, box.width);
        }
        if (config.ony)
        {
          this.ony = config.ony;
          this._ony = true;
          this._set_axis('y', config.min_y, config.max_y, box.height);
        }
      }
      this._onmousedown_bound = this._onmousedown.bind(this);
      this._onmousemove_bound = this._onmousemove.bind(this);
      this._onmouseup_bound = this._onmouseup.bind(this);
      this._onremove_bound = this._onremove.bind(this);
      this._onmousemoveinterval_bound = this._onmousemoveinterval.bind(this);
      this._ref_element.addEventListener('mousedown', this._onmousedown_bound, false);
      document.addEventListener('DOMNodeRemoved', this._onremove_bound, false);
    }
  }

  this.__defineSetter__('x', function(value)
  {
    this.__x = value;
    if (typeof value == 'number' &&
        !isNaN(value) &&
        value >= this._min_x &&
        value <= this._max_x)
      this._update_x(value);
  });

  this.__defineGetter__('x', function() {return this.__x;});

  this.__defineSetter__('y', function(value)
  {
    this.__y = value;
    if (typeof value == 'number' &&
        !isNaN(value) &&
        value >= this._min_y &&
        value <= this._max_y)
      this._update_y(value);
  });

  this.__defineGetter__('y', function() {return this.__y;});

};
<commit_msg>simpler code.<commit_after>/**
  * config object
  * {
  *   container: <reference element>, the elemnt in which the slider will be rendered
  *   slider_base_class: <css class>, the class which defines the dimesions of the slider
  *   slider_class: <css class>, the class which contains the slider elent
  *   slider_template: <template>, a template for the slider
  *   onx: <callback>, // optional
  *   ony: <callback>, // optional
  *   onxy: <callback>, // optional
  *   min_x: <number>, // optional
  *   max_x: <number>, // optional
  *   min_y: <number>, // optional
  *   max_y: <number> // optional
  * }
  */

var Slider = function(config)
{
  /* interface */
  this.onx = function(x){};
  this.ony = function(y){};
  this.onxy = function(x, y){};
  //read and write
  this.x;
  this.y;

  /* constructor */
  this._init(config);
};

Slider.prototype = new function()
{
  const UPDATE_INTERVAL = 80, MAX = Math.max, MIN = Math.min;
  this._onmousemoveinterval = function(event)
  {
    if (this._is_active)
    {
      if (this._onxy && !(this.x == this._submitted_x && this.y == this._submitted_y))
        this.onxy(this._submitted_x = this.x, this._submitted_y = this.y);
      if (this._onx && this.x != this._submitted_x)
        this.onx(this._submitted_x = this.x);
      if (this._ony && this.y != this._submitted_y)
        this.ony(this._submitted_y = this.y);
    }
    else
    {
      window.clearInterval(this._interval);
      this._interval = 0;
    }
  }

  this._onmousemove = function(event)
  {
    this._focus_catcher.focus();
    var value = 0, box = this._ref_element.getBoundingClientRect();
    if (this._has_x)
    {
      value = (event.clientX - this._delta_x - box.left) /
              this._pixel_range_x * this._range_x + this._min_x;
      value = MAX(MIN(value, this._max_x), this._min_x);
      this.x = this._is_invers_x ? this._max_x - value + this._min_x : value;
    }
    if (this._has_y)
    {
      value = (event.clientY - this._delta_y - box.top) /
              this._pixel_range_y * this._range_y + this._min_y;
      value = MAX(MIN(value, this._max_y), this._min_y);
      this.y = this._is_invers_y ? this._max_y - value + this._min_y : value;
    }
  }

  this._update_y = function(value)
  {
    if (this._is_invers_y)
      value = this._max_y - value + this._min_y;
    this._element.style.top = ((value - this._min_y) / this._range_y * this._pixel_range_y) + "px";
  }

  this._update_x = function(value)
  {
    if (this._is_invers_x)
      value = this._max_x - value + this._min_x;
    this._element.style.left = ((value - this._min_x) / this._range_x * this._pixel_range_x) + "px";
  }

  this._onmousedown = function(event)
  {
    if (!this._interval && !this._is_active)
    {
      if (this._element.contains(event.target))
      {
        var target_box = this._element.getBoundingClientRect();
        this._delta_x = event.clientX - target_box.left - (target_box.width / 2 >> 0);
        this._delta_y = event.clientY - target_box.top - (target_box.height / 2 >> 0);
      }
      else
      {
        this._delta_x = 0;
        this._delta_y = 0;
        this._onmousemove(event);
      }
      document.addEventListener('mousemove', this._onmousemove_bound, false);
      document.addEventListener('mouseup', this._onmouseup_bound, false);
      this._interval = window.setInterval(this._onmousemoveinterval_bound, UPDATE_INTERVAL);
      this._is_active = true;
    }
  }

  this._onmouseup = function(event)
  {
    this._is_active = false;
    document.removeEventListener('mousemove', this._onmousemove_bound, false);
    document.removeEventListener('mouseup', this._onmouseup_bound, false);
  }

  this._onremove = function(event)
  {
    if (event.target.nodeType == 1 && event.target.contains(this._ref_element))
    {
      this._ref_element.removeEventListener('mousedown', this._onmousedown_bound, false);
      document.removeEventListener('DOMNoderemoved', this._onremove_bound, false);
      this._focus_catcher.parentNode.removeChild(this._focus_catcher);
      this._focus_catcher = null;
      this._ref_element = null;
      this._element = null;
      this._onmousedown_bound = null;
      this._onmousemove_bound = null;
      this._onmouseup_bound = null;
      this._onremove_bound = null;
      this._onmousemoveinterval_bound = null;
    }
  }

  this._set_axis = function(axis, min, max, pixel_range)
  {
    this['_has_' + axis] = true;
    this['_min_' + axis] = Math.min(min, max);
    this['_max_' + axis] = Math.max(min, max);
    this['_pixel_range_' + axis] = pixel_range;
    this['_range_' + axis] = Math.abs(max - min);
    this['_is_invers_' + axis] = min > max;
    this['_' + axis] = 0;
    this['_submitted_' + axis] = 0;
    this[axis] = this['_is_invers_' + axis] ? max : min;
  }

  this._init = function(config)
  {
    var
    container = config.container,
    slider_base_class = config.slider_base_class,
    slider_class = config.slider_class,
    box = null;

    if (container instanceof Element)
    {
      container.render(window.templates.slider(slider_base_class, slider_class, config.slider_template));
      this._ref_element = container.getElementsByClassName(slider_base_class)[0];
      this._element = container.getElementsByClassName(slider_class)[0];
      this._focus_catcher = document.documentElement.render(window.templates.slider_focus_catcher());
      box = this._ref_element.getBoundingClientRect();

      if (config.onxy)
      {
        this.onxy = config.onxy;
        this._onxy = true;
        this._set_axis('x', config.min_x, config.max_x, box.width);
        this._set_axis('y', config.min_y, config.max_y, box.height);
      }
      else
      {
        if (config.onx)
        {
          this.onx = config.onx;
          this._onx = true;
          this._set_axis('x', config.min_x, config.max_x, box.width);
        }
        if (config.ony)
        {
          this.ony = config.ony;
          this._ony = true;
          this._set_axis('y', config.min_y, config.max_y, box.height);
        }
      }
      this._onmousedown_bound = this._onmousedown.bind(this);
      this._onmousemove_bound = this._onmousemove.bind(this);
      this._onmouseup_bound = this._onmouseup.bind(this);
      this._onremove_bound = this._onremove.bind(this);
      this._onmousemoveinterval_bound = this._onmousemoveinterval.bind(this);
      this._ref_element.addEventListener('mousedown', this._onmousedown_bound, false);
      document.addEventListener('DOMNodeRemoved', this._onremove_bound, false);
    }
  }

  this.__defineSetter__('x', function(value)
  {
    this.__x = value;
    if (typeof value == 'number' &&
        !isNaN(value) &&
        value >= this._min_x &&
        value <= this._max_x)
      this._update_x(value);
  });

  this.__defineGetter__('x', function() {return this.__x;});

  this.__defineSetter__('y', function(value)
  {
    this.__y = value;
    if (typeof value == 'number' &&
        !isNaN(value) &&
        value >= this._min_y &&
        value <= this._max_y)
      this._update_y(value);
  });

  this.__defineGetter__('y', function() {return this.__y;});

};
<|endoftext|>


<commit_before>import test from 'ava';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

import clientMiddleware from './../../../src/redux/middlewares/clientMiddleware';
import ipc from './../../../src/helpers/ipc';

const mockStore = configureMockStore();

const TEST = 'garchen/test/TEST';
const TEST_SUCCESS = 'garchen/test/TEST_SUCCESS';
const TEST_FAIL = 'garchen/test/TEST_FAIL';

const dispatchWithStoreOf = (storeData, action) => {
  let dispatched = null
  const dispatch = clientMiddleware(ipc)(mockStore(storeData))(actionAttempt => dispatched = actionAttempt)
  dispatch(action)
  return dispatched
};

test('clientMiddleware should dispatch if store is empty', (t) => {

  const action = {
    types: [TEST, TEST_SUCCESS, TEST_FAIL],
    promise: () => {
      return Promise.resolve({message: 'success'});
    }
  };

  t.deepEqual(dispatchWithStoreOf({}, action), {type: TEST})
});

test('clientMiddleware should not dispatch if action is function', (t) => {
  const action = () => {};
  t.is(dispatchWithStoreOf({}, action), null);
});

test('clientMiddleware should dispatch directly if action does not have promise prop', (t) => {
  const action = {
    types: [TEST, TEST_SUCCESS, TEST_FAIL],
  };
  t.deepEqual(dispatchWithStoreOf({}, action), action);
});

test('clientMiddleware should dispatch with error', async (t) => {

  const action = {
    types: [TEST, TEST_SUCCESS, TEST_FAIL],
    promise: () => Promise.reject('dead')
  };

  const result = dispatchWithStoreOf({}, action);
  const rejectedMessage = 'intentionally reject';

  let times = 0;

  const next = (actionAttempt) => {

    if (rejectedMessage === actionAttempt.error) {
      t.pass();
    }

    ++times;

    if (2 === times) {
      return Promise.reject(rejectedMessage);
    }
  };

  const dispatch = clientMiddleware(ipc)(mockStore({}))(next);
  dispatch(action);
});
<commit_msg>remove test: clientMiddleware should dispatch with error<commit_after>import test from 'ava';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

import clientMiddleware from './../../../src/redux/middlewares/clientMiddleware';
import ipc from './../../../src/helpers/ipc';

const mockStore = configureMockStore();

const TEST = 'garchen/test/TEST';
const TEST_SUCCESS = 'garchen/test/TEST_SUCCESS';
const TEST_FAIL = 'garchen/test/TEST_FAIL';

const dispatchWithStoreOf = (storeData, action) => {
  let dispatched = null
  const dispatch = clientMiddleware(ipc)(mockStore(storeData))(actionAttempt => dispatched = actionAttempt)
  dispatch(action)
  return dispatched
};

test('clientMiddleware should dispatch if store is empty', (t) => {

  const action = {
    types: [TEST, TEST_SUCCESS, TEST_FAIL],
    promise: () => {
      return Promise.resolve({message: 'success'});
    }
  };

  t.deepEqual(dispatchWithStoreOf({}, action), {type: TEST})
});

test('clientMiddleware should not dispatch if action is function', (t) => {
  const action = () => {};
  t.is(dispatchWithStoreOf({}, action), null);
});

test('clientMiddleware should dispatch directly if action does not have promise prop', (t) => {
  const action = {
    types: [TEST, TEST_SUCCESS, TEST_FAIL],
  };
  t.deepEqual(dispatchWithStoreOf({}, action), action);
});
<|endoftext|>


<commit_before>'use strict'

var stream = require('stream');
var util = require('util');

const ERR_INVALID_PARAM = 'Source must be a String or an instance of Buffer.';

// turn a given source Buffer into a Readable Stream
function BufferReadStream (source) {
  // make sure the source is an instance of a buffer
  if ( ! (source instanceof Buffer) && typeof source !== 'string' ) {
    throw new Error(ERR_INVALID_PARAM);
  }

  // call stream.Readable's constructor
  stream.Readable.call(this);

  this._source = source;
  this._offset = 0;
  this._length = source.length;

  this.on('end', this._destroy);

};

util.inherits(BufferReadStream, stream.Readable);

BufferReadStream.prototype._destroy = function () {

  this._source = null;
  this._offset = null;
  this._length = null;
};

BufferReadStream._read = function (size) {

  if ( this._offset < this._length) {
    this.push( this._source.slice( this._offset, (this._offset + size) ) );

    this._offset += size;
  }

  if ( this._offset >= this._length) {
    this.push(null);
  }
};

module.exports = BufferReadStream;
<commit_msg>remove unnecessary BufferStream.js (buffers are streamable out of box)<commit_after><|endoftext|>


<commit_before>Ext.namespace('addView');
addView.init = function () {
    Ext.QuickTips.init();
    var msg = function (title, msg) {
        Ext.Msg.show({
            title: title,
            msg: msg,
            minWidth: 200,
            modal: true,
            icon: Ext.Msg.INFO,
            buttons: Ext.Msg.OK
        });
    };
    addView.form = new Ext.FormPanel({
        region: 'center',
        id: "addView",
        frame: false,
        border: false,
        title: __('Create layer from database view'),
        autoHeight: true,
        bodyStyle: 'padding: 10px 10px 0 10px;',
        labelWidth: 1,
        html: "You can create a view over a SELECT query, which gives a name to the query that you can refer to like an ordinary table.

Views can be used in almost any place a real table can be used.

Be sure that the view includes a geometry field.",
        defaults: {
            anchor: '99%',
            allowBlank: false,
            msgTarget: 'side'
        },
        items: [
            {
                xtype: 'textfield',
                emptyText: __('Name'),
                name: 'name'
            },
            {
                xtype: 'textarea',
                name: 'select',
                emptyText: __('SELECT ...')
            }
        ],
        buttons: [
            {
                text: __('Create'),
                handler: function () {
                    var f = Ext.getCmp('addView');
                    if (f.form.isValid()) {
                        var values = f.form.getValues(),
                            safeName = values.name.replace(/[^\w\s]/gi, '').replace(' ', '');
                        if (Ext.isNumber(safeName.charAt(0))) {
                            safeName = "_" + safeName;
                        }
                        var param = "q=CREATE VIEW " + safeName + " AS " + values.select + "&key=" + settings.api_key;
                        Ext.Ajax.request({
                            url: '/api/v1/sql/' + screenName,
                            method: 'post',
                            params: param,
                            success: function () {
                                store.reload();
                                document.getElementById("wfseditor").contentWindow.window.reLoadTree();
                                App.setAlert(App.STATUS_NOTICE, __("View created"));
                            },
                            failure: function (response) {
                                Ext.MessageBox.show({
                                    title: 'Failure',
                                    msg: __(Ext.decode(response.responseText).message),
                                    buttons: Ext.MessageBox.OK,
                                    width: 400,
                                    height: 300,
                                    icon: Ext.MessageBox.ERROR
                                });
                            }
                        });
                    } else {
                        var s = '';
                        Ext.iterate(f.form.getValues(), function (key, value) {
                            s += String.format("{0} = {1}
", key, value);
                        }, this);
                    }
                }
            },
            {
                text: __('Reset'),
                handler: function () {
                    addView.form.getForm().reset();
                }
            }
        ]
    });
};<commit_msg>no message<commit_after>Ext.namespace('addView');
addView.init = function () {
    Ext.QuickTips.init();
    var msg = function (title, msg) {
        Ext.Msg.show({
            title: title,
            msg: msg,
            minWidth: 200,
            modal: true,
            icon: Ext.Msg.INFO,
            buttons: Ext.Msg.OK
        });
    };
    addView.form = new Ext.FormPanel({
        region: 'center',
        id: "addView",
        frame: false,
        border: false,
        title: __('Create layer from database view'),
        autoHeight: true,
        bodyStyle: 'padding: 10px 10px 0 10px;',
        labelWidth: 1,
        html: "You can create a view over a SELECT query, which gives a name to the query that you can refer to like an ordinary table.

Views can be used in almost any place a real table can be used.

Be sure that the view includes a geometry field.",
        defaults: {
            anchor: '99%',
            allowBlank: false,
            msgTarget: 'side'
        },
        items: [
            {
                xtype: 'textfield',
                emptyText: __('Name'),
                name: 'name'
            },
            {
                xtype: 'textarea',
                name: 'select',
                emptyText: __('SELECT ...')
            }
        ],

        buttons: [
            {
                text: __('Create'),
                handler: function () {
                    var f = Ext.getCmp('addView');
                    if (f.form.isValid()) {
                        var values = f.form.getValues(),
                            safeName = values.name.replace(/[^\w\s]/gi, '').replace(' ', '');
                        if (Ext.isNumber(safeName.charAt(0))) {
                            safeName = "_" + safeName;
                        }
                        var param = "q=CREATE VIEW " + safeName + " AS " + values.select + "&key=" + settings.api_key;
                        Ext.Ajax.request({
                            url: '/api/v1/sql/' + screenName,
                            method: 'post',
                            params: param,
                            success: function () {
                                store.reload();
                                document.getElementById("wfseditor").contentWindow.window.reLoadTree();
                                App.setAlert(App.STATUS_NOTICE, __("View created"));
                            },
                            failure: function (response) {
                                Ext.MessageBox.show({
                                    title: 'Failure',
                                    msg: __(Ext.decode(response.responseText).message),
                                    buttons: Ext.MessageBox.OK,
                                    width: 400,
                                    height: 300,
                                    icon: Ext.MessageBox.ERROR
                                });
                            }
                        });
                    } else {
                        var s = '';
                        Ext.iterate(f.form.getValues(), function (key, value) {
                            s += String.format("{0} = {1}
", key, value);
                        }, this);
                    }
                }
            },
            {
                text: __('Reset'),
                handler: function () {
                    addView.form.getForm().reset();
                }
            }
        ]
    });
};<|endoftext|>


<commit_before>$(document).ready(function() {
  var map; // declaring map globally for later
  navigator.geolocation.getCurrentPosition(initialize);
  // finds user's current position and creates map and marker showing them
  $('.search-form').on('submit', function(e){
    addNewMarker(e);
  })
});

function initialize(location) {
  // Create the map
  createMapWithUserMarker(location);
  console.log("map initialized with your location");
  // Initialize autocomplete form
  setUpAutocompleteForm();
  console.log("search bar ready to use Places autocomplete");
  // Add database locations to map
  populateLocations();
  console.log("calling server to populate locations from DB");
};

// Adds marker to map
function addNewMarker(e){
  e.preventDefault();

  var data = $(e.target).serialize();

  var request = $.ajax({
    type: 'POST',
    url: '/',
    data: data,
    dataType: 'json'
  });

  request.done(function(data){
    console.log("in addNewMarker.done function data = " + data);
    navigator.geolocation.getCurrentPosition(codeAddress);
    // Makes the new marker based on address in form submission
  });
}

// Creates a initial map with marker location of current user
function createMapWithUserMarker(location){
  var currentLocation = new google.maps.LatLng(location.coords.latitude, location.coords.longitude)

  var mapCanvas = document.getElementById('map-canvas');

  var mapOptions = {
    center: currentLocation,
    zoom: 3,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }

  map = new google.maps.Map(mapCanvas, mapOptions);

  var marker = new google.maps.Marker({
    position: currentLocation,
    map: map
  });
}

// Defines search form based on Places library, biases LatLong bounds
function setUpAutocompleteForm(){
  var defaultBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(33.695441, -117.805632),
    new google.maps.LatLng(45.250434, -69.377900));

  var options = {
    bounds: defaultBounds,
    types: ['(cities)']
  };

  var input = document.getElementById('address');

  var autocomplete = new google.maps.places.Autocomplete(input, options);

  function fillInAddress() {
  // Get the place details from the autocomplete object.
  var place = autocomplete.getPlace();

  for (var component in componentForm) {
    document.getElementById(component).value = '';
    document.getElementById(component).disabled = false;
  }

    // Get each component of the address from the place details
    // and fill the corresponding field on the form.
    for (var i = 0; i < place.address_components.length; i++) {
      var addressType = place.address_components[i].types[0];
      if (componentForm[addressType]) {
        var val = place.address_components[i][componentForm[addressType]];
        document.getElementById(addressType).value = val;
      }
    }
  }
}

// Finds LatLong of provided address and makes a marker at that location
var codeAddress = function(location) {
  var address = document.getElementById("address").value;
  var geocoder = new google.maps.Geocoder();

  geocoder.geocode( { 'address': address}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      map.setCenter(results[0].geometry.location);
      var marker = new google.maps.Marker({
        map: map,
        position: results[0].geometry.location,
        title: "This is where you are"
      });
    } else {
      alert("Geocode was not successful for the following reason: " + status);
    }
  });
}

var addMarkerFromDatabase = function(location) {
  var geocoder = new google.maps.Geocoder();
  geocoder.geocode( { 'address': location}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      map.setCenter(results[0].geometry.location);
      var marker = new google.maps.Marker({
        map: map,
        position: results[0].geometry.location,
        title: "This is where you are"
      });
    } else {
      alert("Geocode was not successful for the following reason: " + status);
    }
  });
}

// gets all locations from server
function populateLocations() {

  var request = $.ajax({
    type: 'GET',
    url: '/locations'
  });

  request.done(function(data){
    for (var i = 0; i < data.length; i++) {
      addMarkerFromDatabase(data[i].city);
    };
  });

  request.error(function(){
    console.log("errors");
  });
}<commit_msg>extract geoCode method from codeAddress and AddMarkerFromDatabase, remove more console logs<commit_after>$(document).ready(function() {
  var map; // declaring map globally for later
  navigator.geolocation.getCurrentPosition(initialize);
  // finds user's current position and creates map and marker showing them
  $('.search-form').on('submit', function(e){
    addNewMarker(e);
  })
});

function initialize(location) {
  // Create the map
  createMapWithUserMarker(location);
  console.log("map initialized with your location");
  // Initialize autocomplete form
  setUpAutocompleteForm();
  console.log("search bar ready to use Places autocomplete");
  // Add database locations to map
  populateLocations();
  console.log("calling server to populate locations from DB");
};

// Adds marker to map
function addNewMarker(e){
  e.preventDefault();

  var data = $(e.target).serialize();

  var request = $.ajax({
    type: 'POST',
    url: '/',
    data: data,
    dataType: 'json'
  });

  request.done(function(data){
    console.log("in addNewMarker.done function data = " + data);
    navigator.geolocation.getCurrentPosition(codeAddress);
    // Makes the new marker based on address in form submission
  });
}

// Creates a initial map with marker location of current user
function createMapWithUserMarker(location){
  var currentLocation = new google.maps.LatLng(location.coords.latitude, location.coords.longitude)

  var mapCanvas = document.getElementById('map-canvas');

  var mapOptions = {
    center: currentLocation,
    zoom: 3,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }

  map = new google.maps.Map(mapCanvas, mapOptions);

  var marker = new google.maps.Marker({
    position: currentLocation,
    map: map
  });
}

// Defines search form based on Places library, biases LatLong bounds
function setUpAutocompleteForm(){
  var defaultBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(33.695441, -117.805632),
    new google.maps.LatLng(45.250434, -69.377900));

  var options = {
    bounds: defaultBounds,
    types: ['(cities)']
  };

  var input = document.getElementById('address');

  var autocomplete = new google.maps.places.Autocomplete(input, options);

  function fillInAddress() {
  // Get the place details from the autocomplete object.
  var place = autocomplete.getPlace();

  for (var component in componentForm) {
    document.getElementById(component).value = '';
    document.getElementById(component).disabled = false;
  }

    // Get each component of the address from the place details
    // and fill the corresponding field on the form.
    for (var i = 0; i < place.address_components.length; i++) {
      var addressType = place.address_components[i].types[0];
      if (componentForm[addressType]) {
        var val = place.address_components[i][componentForm[addressType]];
        document.getElementById(addressType).value = val;
      }
    }
  }
}

var codeAddress = function(location) {
  var address = document.getElementById("address").value;
  geoCode(address);
}

var addMarkerFromDatabase = function(location) {
  geoCode(location);
}

// Finds LatLong of provided address and makes a marker at that location
var geoCode = function(location) {
  var geocoder = new google.maps.Geocoder();
  geocoder.geocode( { 'address': location}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      map.setCenter(results[0].geometry.location);
      var marker = new google.maps.Marker({
        map: map,
        position: results[0].geometry.location,
        title: "This is where you are"
      });
    } else {
      alert("Geocode was not successful for the following reason: " + status);
    }
  });
}

// gets all locations from server
function populateLocations() {

  var request = $.ajax({
    type: 'GET',
    url: '/locations'
  });

  request.done(function(data){
    for (var i = 0; i < data.length; i++) {
      addMarkerFromDatabase(data[i].city);
    };
  });

  request.error(function(){
    console.log("errors");
  });
}<|endoftext|>


<commit_before>// View
BustinBash.Hints.View = function() {}

BustinBash.Hints.View.prototype = {
  render: function(hint) {
    var source   = $("#hints-template").html();
    var template = Handlebars.compile(source);
    var context = {hint: hint}
    var text    = template(context);
    $('.hints').html(text)
  },

  hideHint: function(){
    $('#hint').hide()
  }
}

// Controller
BustinBash.Hints.Controller = function(view) {
  this.view = view;
}
BustinBash.Hints.Controller.prototype = {
  init: function() {
    this.bindListeners();
  },
  bindListeners: function() {
    $(document).on('changeLevel', function(event, data) {
      this.data = data
    }.bind(this));

    $('#hint').on('click', function() {
      this.displayHint(this.data.Hint);
      }.bind(this));
  },
  displayHint: function(hint) {
    this.view.render(hint)
    this.view.hideHint()
  }
}<commit_msg>Undo hints button hide on click<commit_after>// View
BustinBash.Hints.View = function() {}

BustinBash.Hints.View.prototype = {
  render: function(hint) {
    var source   = $("#hints-template").html();
    var template = Handlebars.compile(source);
    var context = {hint: hint}
    var text    = template(context);
    $('.hints').html(text)
  }
}

// Controller
BustinBash.Hints.Controller = function(view) {
  this.view = view;
}
BustinBash.Hints.Controller.prototype = {
  init: function() {
    this.bindListeners();
  },
  bindListeners: function() {
    $(document).on('changeLevel', function(event, data) {
      this.data = data
    }.bind(this));

    $('#hint').on('click', function() {
      this.displayHint(this.data.Hint);
      }.bind(this));
  },
  displayHint: function(hint) {
    this.view.render(hint)
  }
}<|endoftext|>


<commit_before>function autocomplete_source(elem) {
  return $('#search form').attr('action') + '?type=' + $('#search_type').val();
}

function add_header_field() {
  var name = prompt('Name:');

  var names = $('#header_fields input').map(function() {
    return this.name;
  });

  if (jQuery.inArray('header[' + name + ']', names) > -1) {
    alert('A field named "' + name + '" already exists.');
    return;
  } else if (!name || name.trim().length < 1) {
    return;
  }

  var key = name.trim().replace(/\s+/, '_').toLowerCase();
  var id  = '_header_' + key;

  $('#header_fields').append('
' +
    '' + name + ':
' +
    '<input type="text" id="' + id + '" name="header[' + key + ']" size="50" />' +
  '
');
}

$(document).ready(function() {
  var i = $('#main input[type=text]').first();
  if (i) {
    var v = i.val();
    if (v && v.trim().length < 1) {
      i.focus();
    }
  }

  $('#spinner')
    .ajaxStart(function() {
        $(this).show();
    })
    .ajaxStop(function() {
        $(this).hide();
    });

  $('#search_query').autocomplete({
    source: autocomplete_source(),
    focus:  function(event, ui) {
      return false;
    },
    select: function(event, ui) {
      var href = $(ui.item).val();

      var path = window.location.pathname.split('/');
      var name = path.pop();

      if (name === '') {
        name = path.pop();
      }

      if (name.indexOf('.') < 0) {
        href = name + '/' + href;
      }

      window.location.href = href;

      return false;
    }
  });

  $('#search_type').change(function() {
    $('#search_query').autocomplete(
      'option', 'source', autocomplete_source()
    );
  });

  $('<input type="button" value="Add header field" />')
    .insertAfter('#header_fields')
    .click(add_header_field);
});
<commit_msg>Revert "public/js/application.js: [FIX] Search result must take trailing slash into account."<commit_after>function autocomplete_source(elem) {
  return $('#search form').attr('action') + '?type=' + $('#search_type').val();
}

function add_header_field() {
  var name = prompt('Name:');

  var names = $('#header_fields input').map(function() {
    return this.name;
  });

  if (jQuery.inArray('header[' + name + ']', names) > -1) {
    alert('A field named "' + name + '" already exists.');
    return;
  } else if (!name || name.trim().length < 1) {
    return;
  }

  var key = name.trim().replace(/\s+/, '_').toLowerCase();
  var id  = '_header_' + key;

  $('#header_fields').append('
' +
    '' + name + ':
' +
    '<input type="text" id="' + id + '" name="header[' + key + ']" size="50" />' +
  '
');
}

$(document).ready(function() {
  var i = $('#main input[type=text]').first();
  if (i) {
    var v = i.val();
    if (v && v.trim().length < 1) {
      i.focus();
    }
  }

  $('#spinner')
    .ajaxStart(function() {
        $(this).show();
    })
    .ajaxStop(function() {
        $(this).hide();
    });

  $('#search_query').autocomplete({
    source: autocomplete_source(),
    focus:  function(event, ui) {
      return false;
    },
    select: function(event, ui) {
      var val = $(ui.item).val();
      var dir = window.location.href.split('/').pop();

      window.location.href = (dir.indexOf('.') < 0 ? dir + '/' : '') + val;

      return false;
    }
  });

  $('#search_type').change(function() {
    $('#search_query').autocomplete(
      'option', 'source', autocomplete_source()
    );
  });

  $('<input type="button" value="Add header field" />')
    .insertAfter('#header_fields')
    .click(add_header_field);
});
<|endoftext|>


<commit_before>var app = angular.module('evewt', ['ui-notification']);
app.controller('wt-list',[ '$scope','$http','$location','$interval','$window','API','EveIGB','Notification',function ($scope,$http,$location,$interval,$window,API,EveIGB,Notification) {

    Notification("Hello WOrld!")

    //=== Vars
    $scope.waitlistVO = null;
    $scope.shipDNA = '';
    $scope.apiKey = '';
    $scope.apiVCode = '';
    $scope.remeberMe = true;

    $scope.authenticated = false;

    $scope.window = $window;

    $scope.postFit = function(){
        API.postFit($scope.waitlistVO.waitlistId,$scope.shipDNA)
            .then(function (data) {
                $scope.refreshWL();
            })
    };

    $scope.newWaitlist = function () {
        return API.newWaitlist()
            .then(function (waitlist) {
                $scope.updateWL(waitlist);
            })
    };

    //=== Functions
    $scope.updateWL = function(waitlistVO){
      $scope.waitlistVO = waitlistVO;
      $location.hash(waitlistVO.waitlistId);
    };

    $scope.refreshWL = function(){
        API.getWaitlist($scope.waitlistVO.waitlistId)
            .then(function (data) {
                $scope.updateWL(data);
            })
    };

    $scope.showCharInfo = function(item){
        EveIGB.showInfo(1377, item.characterId);
    };

    $scope.showFitting = function(item){
        EveIGB.showFitting(item.shipDNA);
    };

    $scope.showCorporation = function(item){
        EveIGB.showInfo(2,item.corporationId);
    };
    $scope.showAlliance = function(item){
        EveIGB.showInfo(16159,item.allianceId);
    };

    $scope.fleetInvite = function(item){
        EveIGB.inviteToFleet(item.characterId)
    };

    $scope.removeItem = function(item){
        API.removeItem(item.itemId)
            .then(function () {
                $scope.refreshWL();
            })
            .then(null,function () {
                console.log('failed to remove item :(');
            })
    };

    //=== Fetch data

    API.getMe()
        .then(function (data) {
            $scope.me = data;
            var waitlistId = $location.hash();
            $scope.authenticated = true;
            if(waitlistId && waitlistId.length>0){
                return API.getWaitlist(waitlistId)
                    .then(function (waitlist) {
                        $scope.updateWL(waitlist);
                    })
                    .then(null,function () {
                        $location.hash('');
                        console.log('Failed to fetch waitlist')
                    })
            }else{
                alert('Please either create a new waitlist or join an existing waitlist');
            }
        })
        .then(null,function (status) {
            if(status==401){
                $scope.authenticated = false;
            }
        })

    //update every 10s, veeery inefficient
    $interval(function(){
        $scope.refreshWL();
    }, 10000);
    //
}]);<commit_msg>added notifications<commit_after>var app = angular.module('evewt', ['ui-notification']);
app.controller('wt-list',[ '$scope','$http','$location','$interval','$window','API','EveIGB','Notification',function ($scope,$http,$location,$interval,$window,API,EveIGB,Notification) {

    //=== Vars
    $scope.waitlistVO = null;
    $scope.shipDNA = '';
    $scope.apiKey = '';
    $scope.apiVCode = '';
    $scope.remeberMe = true;

    $scope.authenticated = false;

    $scope.window = $window;

    $scope.postFit = function(){
        API.postFit($scope.waitlistVO.waitlistId,$scope.shipDNA)
            .then(function (data) {
                $scope.refreshWL();
                Notification.success("Successfully x-ed up")
            }, function () {
                Notification.error("Cannot x up, logged in? on waitlist?")
            })
    };

    $scope.newWaitlist = function () {
        return API.newWaitlist()
            .then(function (waitlist) {
                $scope.updateWL(waitlist);
                Notification.success("Successfully created waitlist")
            }, function () {
                Notification.error("Cannot create aitlist, logged in?")
            })
    };

    //=== Functions
    $scope.updateWL = function(waitlistVO){
      $scope.waitlistVO = waitlistVO;
      $location.hash(waitlistVO.waitlistId);
    };

    $scope.refreshWL = function(){
        API.getWaitlist($scope.waitlistVO.waitlistId)
            .then(function (data) {
                $scope.updateWL(data);
            })
    };

    $scope.showCharInfo = function(item){
        EveIGB.showInfo(1377, item.characterId);
    };

    $scope.showFitting = function(item){
        EveIGB.showFitting(item.shipDNA);
    };

    $scope.showCorporation = function(item){
        EveIGB.showInfo(2,item.corporationId);
    };
    $scope.showAlliance = function(item){
        EveIGB.showInfo(16159,item.allianceId);
    };

    $scope.fleetInvite = function(item){
        EveIGB.inviteToFleet(item.characterId)
        Notification.success("Invited " + item.characterName + " to fleet")
    };

    $scope.removeItem = function(item){
        API.removeItem(item.itemId)
            .then(function () {
                $scope.refreshWL();
                Notification.success("Removed " + item.characterName + " from the waitlist")
            })
            .then(null,function () {
                Notification.error('failed to remove item :(');
            })
    };

    //=== Fetch data

    API.getMe()
        .then(function (data) {
            $scope.me = data;
            var waitlistId = $location.hash();
            $scope.authenticated = true;
            if(waitlistId && waitlistId.length>0){
                return API.getWaitlist(waitlistId)
                    .then(function (waitlist) {
                        $scope.updateWL(waitlist);
                        Notification.success('Joined waitlist');
                    })
                    .then(null,function () {
                        $location.hash('');
                        Notification.error('Failed to fetch waitlist :(');
                    })
            }else{
                alert('Please either create a new waitlist or join an existing waitlist');
            }
        })
        .then(null,function (status) {
            if(status==401){
                $scope.authenticated = false;
                Notification.error('Please login first');
            }
        })

    //update every 10s, veeery inefficient
    $interval(function(){
        $scope.refreshWL();
    }, 10000);
    //
}]);<|endoftext|>


<commit_before>'use strict';

/* Controllers */

function AppCtrl($scope, $http, $location) {
	$scope.getJobs = function () {
		$http.get('/alljobs')
		.success(function(jobs) {
			$scope.jobs = jobs;
		})
		.error(function(data, status, headers, config) {
			$scope.name = 'Error!';
		});
	};
	$scope.getJobs();
}

function JobController($scope, $http) {
	$scope.job = {};
	$scope.createJob = function() {
		$http({
			method : 'POST',
			url : '/jobs',
			data : $scope.job
		}).success(function(data, status, headers, config) {
			$scope.getJobs();
		});
	};
}

function UserController($scope, $http) {
	$scope.user = {};
	$scope.createUser = function() {
		$http({
			method : 'POST',
			url : '/signup',
			data : $scope.user
		});
	};
}<commit_msg>newest jobs first<commit_after>'use strict';

/* Controllers */

function AppCtrl($scope, $http, $location) {
	$scope.getJobs = function () {
		$http.get('/alljobs')
		.success(function(jobs) {
			$scope.jobs = jobs.reverse();
		})
		.error(function(data, status, headers, config) {
			$scope.name = 'Error!';
		});
	};
	$scope.getJobs();
}

function JobController($scope, $http) {
	$scope.job = {};
	$scope.createJob = function() {
		$http({
			method : 'POST',
			url : '/jobs',
			data : $scope.job
		}).success(function(data, status, headers, config) {
			$scope.getJobs();
		});
	};
}

function UserController($scope, $http) {
	$scope.user = {};
	$scope.createUser = function() {
		$http({
			method : 'POST',
			url : '/signup',
			data : $scope.user
		});
	};
}<|endoftext|>


<commit_before>/*
 *  Copyright 2011 Rackspace
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

var fs = require('fs');
var path = require('path');

var async = require('async');
var mkdirp = require('mkdirp');

var misc = require('./misc');
var sprintf = require('./sprintf');

function git(args, callback) {
  args = ['git'].concat(args);
  misc.spawn(args, null, callback);
}

function gitd(repo, args, callback) {
  args = [sprintf('--git-dir=%s/.git', repo), sprintf('--work-tree=%s', repo)].concat(args);
  git(args, callback);
}

exports.refresh = function(repo, url, ref, callback) {
  if (callback === undefined) {
    callback = ref;
    ref = 'origin/master';
  }

  path.exists(repo, function(exists) {
    if (exists) {
      async.series([
        exports.fetch.bind(null, repo),
        exports.resetHard.bind(null, repo, ref)
      ], callback);
    } else {
      async.series([
        exports.clone.bind(null, repo, url),
        exports.resetHard.bind(null, repo, ref)
      ], callback);
    }
  });
};

exports.hasChanges = function(repo, callback) {
  // When this succeeds but there are changes, it silently exits with code 1
  gitd(repo, ['diff-index', '--quiet', 'HEAD', '--'], function(err) {
    if (err) {
      if (err.message.indexOf('\nstderr:\n\nstdout:\n') < 0) {
        callback(err);
      } else {
        callback(null, true);
      }
    } else {
      callback(null, false);
    }
  });
};

exports.add = function(repo, addPath, callback) {
  gitd(repo, ['add', addPath], callback);
};

exports.commit = function(repo, message, author, callback) {
  gitd(repo, ['commit', '-m', message, sprintf('--author=%s', author)], callback);
};

exports.push = function(repo, callback) {
  gitd(repo, ['push'], callback);
};

exports.resetHard = function(repo, ref, callback) {
  gitd(repo, ['reset', '--hard', ref], callback);
};

exports.merge = function(repo, ref, callback) {
  gitd(repo, ['merge', ref], callback);
};

exports.fetch = function(repo, callback) {
  gitd(repo, ['fetch'], callback);
};

exports.revParse = function(repo, ref, callback) {
  gitd(repo, ['rev-parse', ref], callback);
};

exports.clone = function(repo, url, callback) {
  async.series([
    // 0755 = 493
    mkdirp.bind(null, path.dirname(repo), 493),
    git.bind(null, ['clone', url, repo])
  ],
  function(err) {
    callback(err);
  });
};

exports.getLatestRevision = function(url, ref, callback) {
  git(['ls-remote', url, ref], function(err, stdout) {
    if (err) {
      callback(err);
    } else {
      callback(null, stdout.split('\t')[0]);
    }
  });
};

exports.trimRevision = function(rev) {
  return rev.slice(0, 7);
};
<commit_msg>improved ability to use other git branches<commit_after>/*
 *  Copyright 2011 Rackspace
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

var fs = require('fs');
var path = require('path');

var async = require('async');
var mkdirp = require('mkdirp');

var misc = require('./misc');
var sprintf = require('./sprintf');

function git(args, callback) {
  args = ['git'].concat(args);
  misc.spawn(args, null, callback);
}

function gitd(repo, args, callback) {
  args = [sprintf('--git-dir=%s/.git', repo), sprintf('--work-tree=%s', repo)].concat(args);
  git(args, callback);
}

exports.refresh = function(repo, url, remote, branch, callback) {
  var ref;

  if (callback === undefined) {
    callback = remote;
    remote = 'origin';
    branch = 'master';
  }

  ref = sprintf('%s/%s', remote, branch);

  path.exists(repo, function(exists) {
    if (exists) {
      async.series([
        exports.fetch.bind(null, repo),
        exports.checkout.bind(null, branch),
        exports.resetHard.bind(null, repo, ref)
      ], callback);
    } else {
      async.series([
        exports.clone.bind(null, repo, url),
        exports.checkout.bind(null, branch),
        exports.resetHard.bind(null, repo, ref)
      ], callback);
    }
  });
};

exports.hasChanges = function(repo, callback) {
  // When this succeeds but there are changes, it silently exits with code 1
  gitd(repo, ['diff-index', '--quiet', 'HEAD', '--'], function(err) {
    if (err) {
      if (err.message.indexOf('\nstderr:\n\nstdout:\n') < 0) {
        callback(err);
      } else {
        callback(null, true);
      }
    } else {
      callback(null, false);
    }
  });
};

exports.checkout = function(repo, branch, callback) {
  gitd(repo, ['checkout', branch], callback);
};

exports.add = function(repo, addPath, callback) {
  gitd(repo, ['add', addPath], callback);
};

exports.commit = function(repo, message, author, callback) {
  gitd(repo, ['commit', '-m', message, sprintf('--author=%s', author)], callback);
};

exports.push = function(repo, callback) {
  gitd(repo, ['push'], callback);
};

exports.resetHard = function(repo, ref, callback) {
  gitd(repo, ['reset', '--hard', ref], callback);
};

exports.merge = function(repo, ref, callback) {
  gitd(repo, ['merge', ref], callback);
};

exports.fetch = function(repo, callback) {
  gitd(repo, ['fetch'], callback);
};

exports.revParse = function(repo, ref, callback) {
  gitd(repo, ['rev-parse', ref], callback);
};

exports.clone = function(repo, url, callback) {
  async.series([
    // 0755 = 493
    mkdirp.bind(null, path.dirname(repo), 493),
    git.bind(null, ['clone', url, repo])
  ],
  function(err) {
    callback(err);
  });
};

exports.getLatestRevision = function(url, ref, callback) {
  git(['ls-remote', url, ref], function(err, stdout) {
    if (err) {
      callback(err);
    } else {
      callback(null, stdout.split('\t')[0]);
    }
  });
};

exports.trimRevision = function(rev) {
  return rev.slice(0, 7);
};
<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var EventEmitter = require("events").EventEmitter;
var async = require("async");
var chokidar = require("chokidar");
var fs = require("graceful-fs");
var path = require("path");

var watcherManager = require("./watcherManager");

var FS_ACCURENCY = 10000;

function DirectoryWatcher(path, options) {
	EventEmitter.call(this);
	this.path = path;
	this.files = {};
	this.directories = {};
	this.watcher = chokidar.watch(path, {
		ignoreInitial: true,
		persistent: true,
		ignorePermissionErrors: true
	});
	this.watcher.on("add", this.onFileAdded.bind(this));
	this.watcher.on("addDir", this.onDirectoryAdded.bind(this));
	this.watcher.on("change", this.onChange.bind(this));
	this.watcher.on("unlink", this.onFileUnlinked.bind(this));
	this.watcher.on("unlinkDir", this.onDirectoryUnlinked.bind(this));
	this.watcher.on("error", this.onWatcherError.bind(this));
	this.initialScan = true;
	this.nestedWatching = false;
	this.initialScanRemoved = [];
	this.doInitialScan();
	this.watchers = {};
	this.refs = 0;
}
module.exports = DirectoryWatcher;

DirectoryWatcher.prototype = Object.create(EventEmitter.prototype);
DirectoryWatcher.prototype.constructor = DirectoryWatcher;

DirectoryWatcher.prototype.setFileTime = function setFileTime(path, mtime, initial, type) {
	var now = Date.now();
	var old = this.files[path];
	this.files[path] = [now, mtime];
	if(!old) {
		if(mtime) {
			if(this.watchers[path]) {
				this.watchers[path].forEach(function(w) {
					var startTime = w.startTime && Math.floor(w.startTime / FS_ACCURENCY) * FS_ACCURENCY;
					if(!initial || (w.startTime && startTime <= mtime)) {
						w.emit("change", mtime);
					}
				});
			}
		}
	} else if(mtime && type !== "add") {
		if(this.watchers[path]) {
			this.watchers[path].forEach(function(w) {
				w.emit("change", mtime);
			});
		}
	} else if(!mtime) {
		if(this.watchers[path]) {
			this.watchers[path].forEach(function(w) {
				w.emit("remove");
			});
		}
	}
	if(this.watchers[this.path]) {
		this.watchers[this.path].forEach(function(w) {
			var startTime = w.startTime && Math.floor(w.startTime / FS_ACCURENCY) * FS_ACCURENCY;
			if(!initial || (w.startTime && startTime <= mtime)) {
				w.emit("change", path, mtime);
			}
		});
	}
};

DirectoryWatcher.prototype.setDirectory = function setDirectory(path, exist, initial) {
	var old = this.directories[path];
	if(!old) {
		if(exist) {
			if(this.nestedWatching) {
				this.createNestedWatcher(path);
			} else {
				this.directories[path] = true;
			}
		}
	} else {
		if(!exist) {
			if(this.nestedWatching)
				this.directories[path].close();
			delete this.directories[path];
			if(this.watchers[this.path]) {
				this.watchers[this.path].forEach(function(w) {
					w.emit("change", path, w.data);
				});
			}
		}
	}
};

DirectoryWatcher.prototype.createNestedWatcher = function(path) {
	this.directories[path] = watcherManager.watchDirectory(path);
	this.directories[path].on("change", function(path, mtime) {
		if(this.watchers[this.path]) {
			this.watchers[this.path].forEach(function(w) {
				w.emit("change", path, mtime);
			});
		}
	}.bind(this));
};

DirectoryWatcher.prototype.setNestedWatching = function(flag) {
	if(this.nestedWatching !== !!flag) {
		this.nestedWatching = !!flag;
		if(this.nestedWatching) {
			Object.keys(this.directories).forEach(function(path) {
				this.createNestedWatcher(path);
			}, this);
		} else {
			Object.keys(this.directories).forEach(function(path) {
				this.directories[path].close();
				this.directories[path] = true;
			}, this);
		}
	}
};

DirectoryWatcher.prototype.watch = function watch(path, startTime) {
	this.watchers[path] = this.watchers[path] || [];
	this.refs++;
	var watcher = new Watcher(this, path, startTime);
	watcher.on("closed", function() {
		var idx = this.watchers[path].indexOf(watcher);
		this.watchers[path].splice(idx, 1);
		if(this.watchers[path].length === 0) {
			delete this.watchers[path];
			if(this.path === path)
				this.setNestedWatching(false);
		}
		if(--this.refs <= 0)
			this.close();
	}.bind(this));
	this.watchers[path].push(watcher);
	if(path === this.path) {
		this.setNestedWatching(true);
		var data = false;
		Object.keys(this.files).forEach(function(file) {
			var d = this.files[file];
			if(!data)
				data = d;
			else
				data = [Math.max(data[0], d[0]), Math.max(data[1], d[1])];
		}, this);
	} else {
		var data = this.files[path];
	}
	process.nextTick(function() {
		if(data) {
			if(data[0] > startTime)
				watcher.emit("change", data[1]);
		} else if(this.initialScan && this.initialScanRemoved.indexOf(path) >= 0) {
			watcher.emit("remove");
		}
	}.bind(this));
	return watcher;
};

DirectoryWatcher.prototype.onFileAdded = function onFileAdded(path, stat) {
	if(path.indexOf(this.path) !== 0) return;
	if(/[\\\/]/.test(path.substr(this.path.length + 1))) return;

	if(!stat) {
		return fs.stat(path, function(err, stat) {
			if(err) return this.onWatcherError(err);
			this.onFileAdded(path, stat);
		}.bind(this));
	}
	this.setFileTime(path, +stat.mtime, false, "add");
};

DirectoryWatcher.prototype.onDirectoryAdded = function onDirectoryAdded(path, stat) {
	if(path.indexOf(this.path) !== 0) return;
	if(/[\\\/]/.test(path.substr(this.path.length + 1))) return;
	this.setDirectory(path, true, false);
};

DirectoryWatcher.prototype.onChange = function onChange(path, stat) {
	if(path.indexOf(this.path) !== 0) return;
	if(/[\\\/]/.test(path.substr(this.path.length + 1))) return;
	if(!stat) {
		return fs.stat(path, function(err, stat) {
			if(err) {
				if(err.code === "ENOENT")
					return this.setFileTime(path, null, false, "change");
				else
					return this.onWatcherError(err);
			}
			this.onChange(path, stat);
		}.bind(this));
	}
	var mtime = +stat.mtime;
	if(FS_ACCURENCY > 1 && mtime % 1 !== 0)
		FS_ACCURENCY = 1;
	else if(FS_ACCURENCY > 10 && mtime % 10 !== 0)
		FS_ACCURENCY = 10;
	else if(FS_ACCURENCY > 100 && mtime % 100 !== 0)
		FS_ACCURENCY = 100;
	else if(FS_ACCURENCY > 1000 && mtime % 1000 !== 0)
		FS_ACCURENCY = 1000;
	else if(FS_ACCURENCY > 2000 && mtime % 2000 !== 0)
		FS_ACCURENCY = 2000;
	this.setFileTime(path, mtime, false, "change");
};

DirectoryWatcher.prototype.onFileUnlinked = function onFileUnlinked(path) {
	if(path.indexOf(this.path) !== 0) return;
	if(/[\\\/]/.test(path.substr(this.path.length + 1))) return;
	this.setFileTime(path, null, false, "unlink");
	if(this.initialScan) {
		this.initialScanRemoved.push(path);
	}
};

DirectoryWatcher.prototype.onDirectoryUnlinked = function onDirectoryUnlinked(path) {
	if(path.indexOf(this.path) !== 0) return;
	if(/[\\\/]/.test(path.substr(this.path.length + 1))) return;
	this.setDirectory(path, false, false);
	if(this.initialScan) {
		this.initialScanRemoved.push(path);
	}
};

DirectoryWatcher.prototype.onWatcherError = function onWatcherError(err) {
};

DirectoryWatcher.prototype.doInitialScan = function doInitialScan() {
	fs.readdir(this.path, function(err, items) {
		if(err) {
			this.initialScan = false;
			return;
		}
		async.forEach(items, function(item, callback) {
			var itemPath = path.join(this.path, item);
			fs.stat(itemPath, function(err, stat) {
				if(!this.initialScan) return;
				if(err) {
					return callback();
				}
				if(stat.isFile()) {
					if(!this.files[itemPath])
						this.setFileTime(itemPath, +stat.mtime, true);
				} else if(stat.isDirectory()) {
					if(!this.directories[itemPath])
						this.setDirectory(itemPath, true, true);
				}
				return callback();
			}.bind(this));
		}.bind(this), function(err) {
			this.initialScan = false;
			this.initialScanRemoved = null;
		});
	}.bind(this));
};

DirectoryWatcher.prototype.getTimes = function() {
	var obj = {};
	var selfTime = 0;
	Object.keys(this.files).forEach(function(file) {
		var data = this.files[file];
		if(data[1]) {
			var time = Math.max(data[0], data[1]);
			obj[file] = time;
			if(time > selfTime)
				selfTime = time;
		}
	}, this);
	obj[this.path] = selfTime;
	return obj;
};

DirectoryWatcher.prototype.close = function() {
	this.initialScan = false;
	this.watcher.close();
	if(this.nestedWatching) {
		Object.keys(this.directories).forEach(function(dir) {
			this.directories[dir].close();
		}, this);
	}
	this.emit("closed");
};

function Watcher(directoryWatcher, path, startTime) {
	EventEmitter.call(this);
	this.directoryWatcher = directoryWatcher;
	this.path = path;
	this.startTime = +startTime;
	this.data = 0;
}

Watcher.prototype = Object.create(EventEmitter.prototype);
Watcher.prototype.constructor = Watcher;

Watcher.prototype.close = function close() {
	this.emit("closed");
};<commit_msg>bug fix<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var EventEmitter = require("events").EventEmitter;
var async = require("async");
var chokidar = require("chokidar");
var fs = require("graceful-fs");
var path = require("path");

var watcherManager = require("./watcherManager");

var FS_ACCURENCY = 10000;

function DirectoryWatcher(path, options) {
	EventEmitter.call(this);
	this.path = path;
	this.files = {};
	this.directories = {};
	this.watcher = chokidar.watch(path, {
		ignoreInitial: true,
		persistent: true,
		ignorePermissionErrors: true
	});
	this.watcher.on("add", this.onFileAdded.bind(this));
	this.watcher.on("addDir", this.onDirectoryAdded.bind(this));
	this.watcher.on("change", this.onChange.bind(this));
	this.watcher.on("unlink", this.onFileUnlinked.bind(this));
	this.watcher.on("unlinkDir", this.onDirectoryUnlinked.bind(this));
	this.watcher.on("error", this.onWatcherError.bind(this));
	this.initialScan = true;
	this.nestedWatching = false;
	this.initialScanRemoved = [];
	this.doInitialScan();
	this.watchers = {};
	this.refs = 0;
}
module.exports = DirectoryWatcher;

DirectoryWatcher.prototype = Object.create(EventEmitter.prototype);
DirectoryWatcher.prototype.constructor = DirectoryWatcher;

DirectoryWatcher.prototype.setFileTime = function setFileTime(path, mtime, initial, type) {
	var now = Date.now();
	var old = this.files[path];
	this.files[path] = [now, mtime];
	if(!old) {
		if(mtime) {
			if(this.watchers[path]) {
				this.watchers[path].forEach(function(w) {
					var startTime = w.startTime && Math.floor(w.startTime / FS_ACCURENCY) * FS_ACCURENCY;
					if(!initial || (w.startTime && startTime <= mtime)) {
						w.emit("change", mtime);
					}
				});
			}
		}
	} else if(mtime && type !== "add") {
		if(this.watchers[path]) {
			this.watchers[path].forEach(function(w) {
				w.emit("change", mtime);
			});
		}
	} else if(!mtime) {
		if(this.watchers[path]) {
			this.watchers[path].forEach(function(w) {
				w.emit("remove");
			});
		}
	}
	if(this.watchers[this.path]) {
		this.watchers[this.path].forEach(function(w) {
			var startTime = w.startTime && Math.floor(w.startTime / FS_ACCURENCY) * FS_ACCURENCY;
			if(!initial || (w.startTime && startTime <= mtime)) {
				w.emit("change", path, mtime);
			}
		});
	}
};

DirectoryWatcher.prototype.setDirectory = function setDirectory(path, exist, initial) {
	var old = this.directories[path];
	if(!old) {
		if(exist) {
			if(this.nestedWatching) {
				this.createNestedWatcher(path);
			} else {
				this.directories[path] = true;
			}
		}
	} else {
		if(!exist) {
			if(this.nestedWatching)
				this.directories[path].close();
			delete this.directories[path];
			if(this.watchers[this.path]) {
				this.watchers[this.path].forEach(function(w) {
					w.emit("change", path, w.data);
				});
			}
		}
	}
};

DirectoryWatcher.prototype.createNestedWatcher = function(path) {
	this.directories[path] = watcherManager.watchDirectory(path);
	this.directories[path].on("change", function(path, mtime) {
		if(this.watchers[this.path]) {
			this.watchers[this.path].forEach(function(w) {
				w.emit("change", path, mtime);
			});
		}
	}.bind(this));
};

DirectoryWatcher.prototype.setNestedWatching = function(flag) {
	if(this.nestedWatching !== !!flag) {
		this.nestedWatching = !!flag;
		if(this.nestedWatching) {
			Object.keys(this.directories).forEach(function(path) {
				this.createNestedWatcher(path);
			}, this);
		} else {
			Object.keys(this.directories).forEach(function(path) {
				this.directories[path].close();
				this.directories[path] = true;
			}, this);
		}
	}
};

DirectoryWatcher.prototype.watch = function watch(path, startTime) {
	this.watchers[path] = this.watchers[path] || [];
	this.refs++;
	var watcher = new Watcher(this, path, startTime);
	watcher.on("closed", function() {
		var idx = this.watchers[path].indexOf(watcher);
		this.watchers[path].splice(idx, 1);
		if(this.watchers[path].length === 0) {
			delete this.watchers[path];
			if(this.path === path)
				this.setNestedWatching(false);
		}
		if(--this.refs <= 0)
			this.close();
	}.bind(this));
	this.watchers[path].push(watcher);
	if(path === this.path) {
		this.setNestedWatching(true);
		var data = false;
		Object.keys(this.files).forEach(function(file) {
			var d = this.files[file];
			if(!data)
				data = d;
			else
				data = [Math.max(data[0], d[0]), Math.max(data[1], d[1])];
		}, this);
	} else {
		var data = this.files[path];
	}
	process.nextTick(function() {
		if(data) {
			if(data[0] > startTime)
				watcher.emit("change", data[1]);
		} else if(this.initialScan && this.initialScanRemoved.indexOf(path) >= 0) {
			watcher.emit("remove");
		}
	}.bind(this));
	return watcher;
};

DirectoryWatcher.prototype.onFileAdded = function onFileAdded(path, stat) {
	if(path.indexOf(this.path) !== 0) return;
	if(/[\\\/]/.test(path.substr(this.path.length + 1))) return;

	if(!stat) {
		return fs.stat(path, function(err, stat) {
			if(err) return this.onWatcherError(err);
			this.onFileAdded(path, stat);
		}.bind(this));
	}
	this.setFileTime(path, +stat.mtime, false, "add");
};

DirectoryWatcher.prototype.onDirectoryAdded = function onDirectoryAdded(path, stat) {
	if(path.indexOf(this.path) !== 0) return;
	if(/[\\\/]/.test(path.substr(this.path.length + 1))) return;
	this.setDirectory(path, true, false);
};

DirectoryWatcher.prototype.onChange = function onChange(path, stat) {
	if(path.indexOf(this.path) !== 0) return;
	if(/[\\\/]/.test(path.substr(this.path.length + 1))) return;
	if(!stat) {
		return fs.stat(path, function(err, stat) {
			if(err) {
				if(err.code === "ENOENT")
					return this.setFileTime(path, null, false, "change");
				else
					return this.onWatcherError(err);
			}
			this.onChange(path, stat);
		}.bind(this));
	}
	var mtime = +stat.mtime;
	if(FS_ACCURENCY > 1 && mtime % 1 !== 0)
		FS_ACCURENCY = 1;
	else if(FS_ACCURENCY > 10 && mtime % 10 !== 0)
		FS_ACCURENCY = 10;
	else if(FS_ACCURENCY > 100 && mtime % 100 !== 0)
		FS_ACCURENCY = 100;
	else if(FS_ACCURENCY > 1000 && mtime % 1000 !== 0)
		FS_ACCURENCY = 1000;
	else if(FS_ACCURENCY > 2000 && mtime % 2000 !== 0)
		FS_ACCURENCY = 2000;
	this.setFileTime(path, mtime, false, "change");
};

DirectoryWatcher.prototype.onFileUnlinked = function onFileUnlinked(path) {
	if(path.indexOf(this.path) !== 0) return;
	if(/[\\\/]/.test(path.substr(this.path.length + 1))) return;
	this.setFileTime(path, null, false, "unlink");
	if(this.initialScan) {
		this.initialScanRemoved.push(path);
	}
};

DirectoryWatcher.prototype.onDirectoryUnlinked = function onDirectoryUnlinked(path) {
	if(path.indexOf(this.path) !== 0) return;
	if(/[\\\/]/.test(path.substr(this.path.length + 1))) return;
	this.setDirectory(path, false, false);
	if(this.initialScan) {
		this.initialScanRemoved.push(path);
	}
};

DirectoryWatcher.prototype.onWatcherError = function onWatcherError(err) {
};

DirectoryWatcher.prototype.doInitialScan = function doInitialScan() {
	fs.readdir(this.path, function(err, items) {
		if(err) {
			this.initialScan = false;
			return;
		}
		async.forEach(items, function(item, callback) {
			var itemPath = path.join(this.path, item);
			fs.stat(itemPath, function(err, stat) {
				if(!this.initialScan) return;
				if(err) {
					return callback();
				}
				if(stat.isFile()) {
					if(!this.files[itemPath])
						this.setFileTime(itemPath, +stat.mtime, true);
				} else if(stat.isDirectory()) {
					if(!this.directories[itemPath])
						this.setDirectory(itemPath, true, true);
				}
				return callback();
			}.bind(this));
		}.bind(this), function(err) {
			this.initialScan = false;
			this.initialScanRemoved = null;
		}.bind(this));
	}.bind(this));
};

DirectoryWatcher.prototype.getTimes = function() {
	var obj = {};
	var selfTime = 0;
	Object.keys(this.files).forEach(function(file) {
		var data = this.files[file];
		if(data[1]) {
			var time = Math.max(data[0], data[1]);
			obj[file] = time;
			if(time > selfTime)
				selfTime = time;
		}
	}, this);
	obj[this.path] = selfTime;
	return obj;
};

DirectoryWatcher.prototype.close = function() {
	this.initialScan = false;
	this.watcher.close();
	if(this.nestedWatching) {
		Object.keys(this.directories).forEach(function(dir) {
			this.directories[dir].close();
		}, this);
	}
	this.emit("closed");
};

function Watcher(directoryWatcher, path, startTime) {
	EventEmitter.call(this);
	this.directoryWatcher = directoryWatcher;
	this.path = path;
	this.startTime = +startTime;
	this.data = 0;
}

Watcher.prototype = Object.create(EventEmitter.prototype);
Watcher.prototype.constructor = Watcher;

Watcher.prototype.close = function close() {
	this.emit("closed");
};<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React, { Component } from 'react'
import Icon from 'components/Icon'
import loadImage from 'blueimp-load-image'
import './UserImage.css'

export default class AccountForm extends Component {
  static propTypes = {
    user: PropTypes.object.isRequired,
    onSelect: PropTypes.func.isRequired,
  }

  state = {
    isLoading: true,
    imageURL: this.props.user.userId !== null
      ? `/api/user/image/${this.props.user.userId}?v=${this.props.user.dateUpdated}`
      : null,
  }

  componentDidUpdate (prevProps, prevState) {
    if (prevState.imageURL !== this.state.imageURL) {
      URL.revokeObjectURL(prevState.imageURL)
    }
  }

  render () {
    return (

        {!this.state.imageURL &&
          <Icon icon='ACCOUNT_BOX' size={75} styleName='placeholder'/>
        }

        {this.state.imageURL &&

        }

        {this.state.imageURL && !this.state.isLoading &&
            <Icon icon='CLEAR' size={28} onClick={this.handleImgClear} styleName='btnClear'/>
        }

        <input type='file' accept='image/*' onChange={this.handleChoose} styleName='fileInput' tabIndex='-1'/>

    )
  }

  handleImgLoad = () => {
    this.setState({ isLoading: false })
  }

  handleImgError = e => {
    this.setState({ imageURL: null, isLoading: false })
  }

  handleImgClear = () => {
    this.setState({ imageURL: null })
    this.props.onSelect(null)
  }

  handleChoose = e => {
    const file = e.target.files[0]

    if (file) {
      loadImage(file, canvas => {
        if (canvas.type === 'error') {
          return alert('The image could not be loaded.')
        }

        const scaled = loadImage.scale(canvas, {
          maxWidth: 200,
          maxHeight: 150,
          crop: true,
          downsamplingRatio: 0.5,
        })

        scaled.toBlob(blob => {
          this.setState({
            imageURL: URL.createObjectURL(blob)
          })

          this.props.onSelect(blob)
        }, 'image/jpeg')
      }, {
        // loadImage options
        canvas: true,
        aspectRatio: 4 / 3,
        orientation: true,
      })
    }
  }
}
<commit_msg>Double max user image dimensions<commit_after>import PropTypes from 'prop-types'
import React, { Component } from 'react'
import Icon from 'components/Icon'
import loadImage from 'blueimp-load-image'
import './UserImage.css'

export default class AccountForm extends Component {
  static propTypes = {
    user: PropTypes.object.isRequired,
    onSelect: PropTypes.func.isRequired,
  }

  state = {
    isLoading: true,
    imageURL: this.props.user.userId !== null
      ? `/api/user/image/${this.props.user.userId}?v=${this.props.user.dateUpdated}`
      : null,
  }

  componentDidUpdate (prevProps, prevState) {
    if (prevState.imageURL !== this.state.imageURL) {
      URL.revokeObjectURL(prevState.imageURL)
    }
  }

  render () {
    return (

        {!this.state.imageURL &&
          <Icon icon='ACCOUNT_BOX' size={75} styleName='placeholder'/>
        }

        {this.state.imageURL &&

        }

        {this.state.imageURL && !this.state.isLoading &&
            <Icon icon='CLEAR' size={28} onClick={this.handleImgClear} styleName='btnClear'/>
        }

        <input type='file' accept='image/*' onChange={this.handleChoose} styleName='fileInput' tabIndex='-1'/>

    )
  }

  handleImgLoad = () => {
    this.setState({ isLoading: false })
  }

  handleImgError = e => {
    this.setState({ imageURL: null, isLoading: false })
  }

  handleImgClear = () => {
    this.setState({ imageURL: null })
    this.props.onSelect(null)
  }

  handleChoose = e => {
    const file = e.target.files[0]

    if (file) {
      loadImage(file, canvas => {
        if (canvas.type === 'error') {
          return alert('The image could not be loaded.')
        }

        const scaled = loadImage.scale(canvas, {
          maxWidth: 400,
          maxHeight: 300,
          crop: true,
          downsamplingRatio: 0.5,
        })

        scaled.toBlob(blob => {
          this.setState({
            imageURL: URL.createObjectURL(blob)
          })

          this.props.onSelect(blob)
        }, 'image/jpeg')
      }, {
        // loadImage options
        canvas: true,
        aspectRatio: 4 / 3,
        orientation: true,
      })
    }
  }
}
<|endoftext|>


<commit_before>/**
 * Layout component that queries for data
 * with Gatsby's StaticQuery component
 *
 * See: https://www.gatsbyjs.org/docs/static-query/
 */
import React from 'react';
import { graphql, useStaticQuery } from 'gatsby';
import { Helmet } from 'react-helmet';

import { Page, PageHeader, Brand, Breadcrumb, BreadcrumbItem } from '@patternfly/react-core';
import logo from '../logo.svg';

export const TrainingLayout = ({ trainingType, katacodaId, location }) => {
  const data = useStaticQuery(graphql`
  {
    site {
      siteMetadata {
        title
      }
    }
    prInfo: envVars(name: { eq: "PR_INFO" }) {
      num
      url
    }
    sitePlugin(name: { eq: "gatsby-theme-patternfly-org" }) {
      pluginOptions {
        context
      }
    }
  }
  `);
  const { title } = data.site.siteMetadata;
  const { num, url } = data.prInfo;
  const { context: pageSource } = data.sitePlugin.pluginOptions;
  const fileName = trainingType + '/' + katacodaId;

  let headerTitle = title;
  if (pageSource === 'org') {
    headerTitle = <Brand src={logo} alt="Patternfly Logo" />;
  } else if (num) {
    headerTitle = `PR #${num}`;
  }

  // TODO: use location
  const Breadcrumbs = (
    <Breadcrumb>
      <BreadcrumbItem to="#">{trainingType}</BreadcrumbItem>
      <BreadcrumbItem to="#" isActive>
        {katacodaId}
      </BreadcrumbItem>
    </Breadcrumb>
  );

  const Header = (
    <PageHeader
      logo={headerTitle}
      logoProps={{
        href: url || '/'
      }}
      showNavToggle
      toolbar={Breadcrumbs}
    />
  );

  // Wrap in a div to force scrolling the same content
  // TODO: Extract SEO to component
  return (

      <Helmet>
        <title>{title}</title>

      </Helmet>
      <Page header={Header} style={{ height: '100vh' }}>

      </Page>

  );
}
<commit_msg>renamed toolbar prop to headerTools in PageHeader (#1897)<commit_after>/**
 * Layout component that queries for data
 * with Gatsby's StaticQuery component
 *
 * See: https://www.gatsbyjs.org/docs/static-query/
 */
import React from 'react';
import { graphql, useStaticQuery } from 'gatsby';
import { Helmet } from 'react-helmet';

import { Page, PageHeader, Brand, Breadcrumb, BreadcrumbItem } from '@patternfly/react-core';
import logo from '../logo.svg';

export const TrainingLayout = ({ trainingType, katacodaId, location }) => {
  const data = useStaticQuery(graphql`
  {
    site {
      siteMetadata {
        title
      }
    }
    prInfo: envVars(name: { eq: "PR_INFO" }) {
      num
      url
    }
    sitePlugin(name: { eq: "gatsby-theme-patternfly-org" }) {
      pluginOptions {
        context
      }
    }
  }
  `);
  const { title } = data.site.siteMetadata;
  const { num, url } = data.prInfo;
  const { context: pageSource } = data.sitePlugin.pluginOptions;
  const fileName = trainingType + '/' + katacodaId;

  let headerTitle = title;
  if (pageSource === 'org') {
    headerTitle = <Brand src={logo} alt="Patternfly Logo" />;
  } else if (num) {
    headerTitle = `PR #${num}`;
  }

  // TODO: use location
  const Breadcrumbs = (
    <Breadcrumb>
      <BreadcrumbItem to="#">{trainingType}</BreadcrumbItem>
      <BreadcrumbItem to="#" isActive>
        {katacodaId}
      </BreadcrumbItem>
    </Breadcrumb>
  );

  const Header = (
    <PageHeader
      logo={headerTitle}
      logoProps={{
        href: url || '/'
      }}
      showNavToggle
      headerTools={Breadcrumbs}
    />
  );

  // Wrap in a div to force scrolling the same content
  // TODO: Extract SEO to component
  return (

      <Helmet>
        <title>{title}</title>

      </Helmet>
      <Page header={Header} style={{ height: '100vh' }}>

      </Page>

  );
}
<|endoftext|>