<commit_before>import { default as computed, on, observes } from 'ember-addons/ember-computed-decorators';
import { headerHeight } from 'discourse/views/header';

const PANEL_BODY_MARGIN = 30;
const mutationSupport = !!window['MutationObserver'];

export default Ember.Component.extend({
  classNameBindings: [':menu-panel', 'visible::hidden', 'viewMode'],

  showClose: Ember.computed.equal('viewMode', 'slide-in'),

  _layoutComponent() {
    if (!this.get('visible')) { return; }

    const $window = $(window);
    let width = this.get('maxWidth') || 300;
    const windowWidth = parseInt($window.width());

    if ((windowWidth - width) < 50) {
      width = windowWidth - 50;
    }

    const viewMode = this.get('viewMode');
    const $panelBody = this.$('.panel-body');
    let contentHeight = parseInt(this.$('.panel-body-contents').height());

    if (viewMode === 'drop-down') {
      const $buttonPanel = $('header ul.icons');
      if ($buttonPanel.length === 0) { return; }

      // These values need to be set here, not in the css file - this is to deal with the
      // possibility of the window being resized and the menu changing from .slide-in to .drop-down.
      this.$().css({ top: '100%', height: 'auto' });

      // adjust panel height
      const fullHeight = parseInt($window.height());
      const offsetTop = this.$().offset().top;
      const scrollTop = $window.scrollTop();

      if (contentHeight + (offsetTop - scrollTop) + PANEL_BODY_MARGIN > fullHeight) {
        contentHeight = fullHeight - (offsetTop - scrollTop) - PANEL_BODY_MARGIN;
      }
      $panelBody.height(contentHeight);
      $('body').addClass('drop-down-visible');
    } else {
      const menuTop = headerHeight();

      let height;
      const winHeight = $(window).height() - 16;
      if ((menuTop + contentHeight) < winHeight) {
        height = contentHeight + "px";
      } else {
        height = winHeight - menuTop;
      }

      $panelBody.height('100%');
      this.$().css({ top: menuTop + "px", height });
      $('body').removeClass('drop-down-visible');
    }

    this.$().width(width);
  },

  @computed('force')
  viewMode() {
    const force = this.get('force');
    if (force) { return force; }

    const headerWidth = $('#main-outlet .container').width() || 1100;
    const screenWidth = $(window).width();
    const remaining = parseInt((screenWidth - headerWidth) / 2);

    return (remaining < 50) ? 'slide-in' : 'drop-down';
  },

  @observes('viewMode', 'visible')
  _visibleChanged() {
    if (this.get('visible')) {
      // Allow us to hook into things being shown
      Ember.run.scheduleOnce('afterRender', () => this.sendAction('onVisible'));
      $('html').on('click.close-menu-panel', (e) => {
        const $target = $(e.target);
        if ($target.closest('.header-dropdown-toggle').length > 0) { return; }
        if ($target.closest('.menu-panel').length > 0) { return; }
        this.hide();
      });
      this.performLayout();
      this._watchSizeChanges();

      // iOS does not handle scroll events well
      if (!this.capabilities.touch) {
        $(window).on('scroll.discourse-menu-panel', () => this.performLayout());
      }
    } else {
      Ember.run.scheduleOnce('afterRender', () => this.sendAction('onHidden'));
      $('html').off('click.close-menu-panel');
      $(window).off('scroll.discourse-menu-panel');
      this._stopWatchingSize();
      $('body').removeClass('drop-down-visible');
    }
  },

  @computed()
  showKeyboardShortcuts() {
    return !Discourse.Mobile.mobileView && !this.capabilities.touch;
  },

  @computed()
  showMobileToggle() {
    return Discourse.Mobile.mobileView || (this.siteSettings.enable_mobile_theme && this.capabilities.touch);
  },

  @computed()
  mobileViewLinkTextKey() {
    return Discourse.Mobile.mobileView ? "desktop_view" : "mobile_view";
  },

  @computed()
  faqUrl() {
    return this.siteSettings.faq_url ? this.siteSettings.faq_url : Discourse.getURL('/faq');
  },

  performLayout() {
    Ember.run.scheduleOnce('afterRender', this, this._layoutComponent);
  },

  _watchSizeChanges() {
    if (mutationSupport) {
      this._observer.disconnect();
      this._observer.observe(this.element, { childList: true, subtree: true });
    } else {
      clearInterval(this._resizeInterval);
      this._resizeInterval = setInterval(() => {
        Ember.run(() => {
          const $panelBodyContents = this.$('.panel-body-contents');
          if ($panelBodyContents && $panelBodyContents.length) {
            const contentHeight = parseInt($panelBodyContents.height());
            if (contentHeight !== this._lastHeight) { this.performLayout(); }
            this._lastHeight = contentHeight;
          }
        });
      }, 500);
    }
  },

  _stopWatchingSize() {
    if (mutationSupport) {
      this._observer.disconnect();
    } else {
      clearInterval(this._resizeInterval);
    }
  },

  @on('didInsertElement')
  _bindEvents() {
    this.$().on('click.discourse-menu-panel', 'a', e => {
      if (e.metaKey || e.ctrlKey || e.shiftKey) { return; }
      const $target = $(e.target);
      if ($target.data('ember-action') || $target.closest('.search-link').length > 0) { return; }
      this.hide();
    });

    this.appEvents.on('dropdowns:closeAll', this, this.hide);
    this.appEvents.on('dom:clean', this, this.hide);

    $('body').on('keydown.discourse-menu-panel', e => {
      if (e.which === 27) {
        this.hide();
      }
    });

    $(window).on('resize.discourse-menu-panel', () => {
      this.propertyDidChange('viewMode');
      this.performLayout();
    });

    if (mutationSupport) {
      this._observer = new MutationObserver(() => {
        Ember.run(() => this.performLayout());
      });
    }

    this.propertyDidChange('viewMode');
  },

  @on('willDestroyElement')
  _removeEvents() {
    this.appEvents.off('dom:clean', this, this.hide);
    this.appEvents.off('dropdowns:closeAll', this, this.hide);
    this.$().off('click.discourse-menu-panel');
    $('body').off('keydown.discourse-menu-panel');
    $('html').off('click.close-menu-panel');
    $(window).off('resize.discourse-menu-panel');
    $(window).off('scroll.discourse-menu-panel');
  },

  hide() {
    this.set('visible', false);
  },

  actions: {
    close() {
      this.hide();
    }
  }
});
<commit_msg>FIX: Tweak the mutationObserver to respect attributes.<commit_after>import { default as computed, on, observes } from 'ember-addons/ember-computed-decorators';
import { headerHeight } from 'discourse/views/header';

const PANEL_BODY_MARGIN = 30;
const mutationSupport = !!window['MutationObserver'];

export default Ember.Component.extend({
  classNameBindings: [':menu-panel', 'visible::hidden', 'viewMode'],

  showClose: Ember.computed.equal('viewMode', 'slide-in'),

  _layoutComponent() {
    if (!this.get('visible')) { return; }

    const $window = $(window);
    let width = this.get('maxWidth') || 300;
    const windowWidth = parseInt($window.width());

    if ((windowWidth - width) < 50) {
      width = windowWidth - 50;
    }

    const viewMode = this.get('viewMode');
    const $panelBody = this.$('.panel-body');
    let contentHeight = parseInt(this.$('.panel-body-contents').height());

    // We use a mutationObserver to check for style changes, so it's important
    // we don't set it if it doesn't change. Same goes for the $panelBody!
    const style = this.$().prop('style');

    if (viewMode === 'drop-down') {
      const $buttonPanel = $('header ul.icons');
      if ($buttonPanel.length === 0) { return; }

      // These values need to be set here, not in the css file - this is to deal with the
      // possibility of the window being resized and the menu changing from .slide-in to .drop-down.
      if (style.top !== '100%' || style.height !== 'auto') {
        this.$().css({ top: '100%', height: 'auto' });
      }

      // adjust panel height
      const fullHeight = parseInt($window.height());
      const offsetTop = this.$().offset().top;
      const scrollTop = $window.scrollTop();

      if (contentHeight + (offsetTop - scrollTop) + PANEL_BODY_MARGIN > fullHeight) {
        contentHeight = fullHeight - (offsetTop - scrollTop) - PANEL_BODY_MARGIN;
      }
      if ($panelBody.height() !== contentHeight) {
        $panelBody.height(contentHeight);
      }
      $('body').addClass('drop-down-visible');
    } else {
      const menuTop = headerHeight();

      let height;
      const winHeight = $(window).height() - 16;
      if ((menuTop + contentHeight) < winHeight) {
        height = contentHeight + "px";
      } else {
        height = winHeight - menuTop;
      }

      if ($panelBody.prop('style').height !== '100%') {
        $panelBody.height('100%');
      }
      if (style.top !== menuTop + "px" || style.height !== height) {
        this.$().css({ top: menuTop + "px", height });
      }
      $('body').removeClass('drop-down-visible');
    }

    this.$().width(width);
  },

  @computed('force')
  viewMode() {
    const force = this.get('force');
    if (force) { return force; }

    const headerWidth = $('#main-outlet .container').width() || 1100;
    const screenWidth = $(window).width();
    const remaining = parseInt((screenWidth - headerWidth) / 2);

    return (remaining < 50) ? 'slide-in' : 'drop-down';
  },

  @observes('viewMode', 'visible')
  _visibleChanged() {
    if (this.get('visible')) {
      // Allow us to hook into things being shown
      Ember.run.scheduleOnce('afterRender', () => this.sendAction('onVisible'));
      $('html').on('click.close-menu-panel', (e) => {
        const $target = $(e.target);
        if ($target.closest('.header-dropdown-toggle').length > 0) { return; }
        if ($target.closest('.menu-panel').length > 0) { return; }
        this.hide();
      });
      this.performLayout();
      this._watchSizeChanges();

      // iOS does not handle scroll events well
      if (!this.capabilities.touch) {
        $(window).on('scroll.discourse-menu-panel', () => this.performLayout());
      }
    } else {
      Ember.run.scheduleOnce('afterRender', () => this.sendAction('onHidden'));
      $('html').off('click.close-menu-panel');
      $(window).off('scroll.discourse-menu-panel');
      this._stopWatchingSize();
      $('body').removeClass('drop-down-visible');
    }
  },

  @computed()
  showKeyboardShortcuts() {
    return !Discourse.Mobile.mobileView && !this.capabilities.touch;
  },

  @computed()
  showMobileToggle() {
    return Discourse.Mobile.mobileView || (this.siteSettings.enable_mobile_theme && this.capabilities.touch);
  },

  @computed()
  mobileViewLinkTextKey() {
    return Discourse.Mobile.mobileView ? "desktop_view" : "mobile_view";
  },

  @computed()
  faqUrl() {
    return this.siteSettings.faq_url ? this.siteSettings.faq_url : Discourse.getURL('/faq');
  },

  performLayout() {
    Ember.run.scheduleOnce('afterRender', this, this._layoutComponent);
  },

  _watchSizeChanges() {
    if (mutationSupport) {
      this._observer.disconnect();
      this._observer.observe(this.element, { childList: true, subtree: true, characterData: true, attributes: true });
    } else {
      clearInterval(this._resizeInterval);
      this._resizeInterval = setInterval(() => {
        Ember.run(() => {
          const $panelBodyContents = this.$('.panel-body-contents');
          if ($panelBodyContents && $panelBodyContents.length) {
            const contentHeight = parseInt($panelBodyContents.height());
            if (contentHeight !== this._lastHeight) { this.performLayout(); }
            this._lastHeight = contentHeight;
          }
        });
      }, 500);
    }
  },

  _stopWatchingSize() {
    if (mutationSupport) {
      this._observer.disconnect();
    } else {
      clearInterval(this._resizeInterval);
    }
  },

  @on('didInsertElement')
  _bindEvents() {
    this.$().on('click.discourse-menu-panel', 'a', e => {
      if (e.metaKey || e.ctrlKey || e.shiftKey) { return; }
      const $target = $(e.target);
      if ($target.data('ember-action') || $target.closest('.search-link').length > 0) { return; }
      this.hide();
    });

    this.appEvents.on('dropdowns:closeAll', this, this.hide);
    this.appEvents.on('dom:clean', this, this.hide);

    $('body').on('keydown.discourse-menu-panel', e => {
      if (e.which === 27) {
        this.hide();
      }
    });

    $(window).on('resize.discourse-menu-panel', () => {
      this.propertyDidChange('viewMode');
      this.performLayout();
    });

    if (mutationSupport) {
      this._observer = new MutationObserver(() => {
        Ember.run.debounce(this, this.performLayout, 50);
      });
    }

    this.propertyDidChange('viewMode');
  },

  @on('willDestroyElement')
  _removeEvents() {
    this.appEvents.off('dom:clean', this, this.hide);
    this.appEvents.off('dropdowns:closeAll', this, this.hide);
    this.$().off('click.discourse-menu-panel');
    $('body').off('keydown.discourse-menu-panel');
    $('html').off('click.close-menu-panel');
    $(window).off('resize.discourse-menu-panel');
    $(window).off('scroll.discourse-menu-panel');
  },

  hide() {
    this.set('visible', false);
  },

  actions: {
    close() {
      this.hide();
    }
  }
});
<|endoftext|>


<commit_before>(function ($) {
  var ident = 0;

  window.Swiftype = window.Swiftype || {};
  Swiftype.root_url = 'https://api.swiftype.com';
  Swiftype.pingUrl = function(endpoint, callback) {
    var img  = new Image();
    img.onload = img.onerror = callback;
    img.src = endpoint;
    setTimeout(callback, 350);
    return false;
  };
  Swiftype.pingAutoSelection = function(engineKey, entryId, value, callback) {
    var params = {
      t: new Date().getTime(),
      engine_key: engineKey,
      entry_id: entryId,
      prefix: value
    };
    var url = Swiftype.root_url + '/api/v1/public/analytics/pas?' + $.param(params);
    Swiftype.pingUrl(url, callback);
  };

  $.fn.swiftype = function (options) {
    var options = $.extend({}, $.fn.swiftype.defaults, options);

    return this.each(function () {
      var $this = $(this);
      var config = $.meta ? $.extend({}, options, $this.data()) : options;
      $this.attr('autocomplete', 'off');
      $this.data('swiftype-config', config);
      $this.submitted = false;
      $this.cache = new LRUCache(10);
      $this.emptyQueries = [];

      $this.computeDropdownStyles = function() {
        var $attachEl = config.attachTo ? $(config.attachTo) : $this;
        var offset = $attachEl.offset();
        var styles = {
          'position': 'absolute',
          'z-index': 9999,
          'top': offset.top + $attachEl.outerHeight() + 1,
          'left': offset.left
        };
        if (config.setWidth) {
          styles['width'] = $attachEl.outerWidth() - 2;
        }
        return styles;
      }

      $this.isEmpty = function(query) {
        return $.inArray(normalize(query), this.emptyQueries) >= 0
      };

      $this.addEmpty = function(query) {
        $this.emptyQueries.unshift(normalize(query));
      };

      var styles = $this.computeDropdownStyles();
      var $list = $('<' + config.suggestionListType + ' />').addClass(config.suggestionListClass).appendTo('body').hide().css(styles);
      $this.data('swiftype-list', $list);

      $this.abortCurrent = function() {
        if ($this.currentRequest) {
          $this.currentRequest.abort();
        }
      };

      $this.hideList = function() {
        setTimeout(function() { $list.hide(); }, 10);
      };

      $this.focused = function() {
        return $this.is(':focus');
      };

      $this.submitting = function() {
        $this.submitted = true;
      };

      $this.listResults = function() {
        return $(config.resultListSelector, $list);
      };

      $this.activeResult = function() {
        return $this.listResults().filter('.' + config.activeItemClass).first();
      };

      $this.prevResult = function() {
        var list = $this.listResults(),
          currentIdx = list.index($this.activeResult()),
          nextIdx = currentIdx - 1,
          next = list.eq(nextIdx);
        $this.listResults().removeClass(config.activeItemClass);
        if (nextIdx >= 0) {
          next.addClass(config.activeItemClass);
        }
      };

      $this.nextResult = function() {
        var list = $this.listResults(),
          currentIdx = list.index($this.activeResult()),
          nextIdx = currentIdx + 1,
          next = list.eq(nextIdx);
        $this.listResults().removeClass(config.activeItemClass);
        if (nextIdx >= 0) {
          next.addClass(config.activeItemClass);
        }
      };

      $this.selectedCallback = function(data) {
        return function() {
          var value = $this.val(),
            callback = function() {
              config.onComplete(data, value);
            };
          Swiftype.pingAutoSelection(config.engineKey, data['id'], value, callback);
        };
      };

      $this.registerResult = function($element, data) {
        $element.data('swiftype-item', data);
        $element.click($this.selectedCallback(data)).mouseover(function () {
          $this.listResults().removeClass(config.activeItemClass);
          $element.addClass(config.activeItemClass);
        });
      };

      $this.getContext = function() {
        return {
          config: config,
          list: $list,
          registerResult: $this.registerResult
        };
      };

      var typingDelayPointer;
      var suppressKey = false;
      $this.lastValue = '';
      $this.keyup(function (event) {
        if (suppressKey) {
          suppressKey = false;
          return;
        }

        // ignore arrow keys, shift
        if (((event.which > 36) && (event.which < 41)) || (event.which == 16)) return;

        if (config.typingDelay > 0) {
          clearTimeout(typingDelayPointer);
          typingDelayPointer = setTimeout(function () {
            processInput($this);
          }, config.typingDelay);
        } else {
          processInput($this);
        }
      });

      $this.styleDropdown = function() {
        $list.css($this.computeDropdownStyles());
      };

      $this.keydown(function (event) {
        $this.styleDropdown();
        // enter = 13; up = 38; down = 40; esc = 27
        var $active = $this.activeResult();
        switch (event.which) {
        case 13:
          if (($active.length !== 0) && ($list.is(':visible'))) {
            event.preventDefault();
            $this.selectedCallback($active.data('swiftype-item'))();
          } else if ($this.currentRequest) {
            $this.submitting();
          }
          $this.hideList();
          suppressKey = true;
          break;
        case 38:
          event.preventDefault();
          if ($active.length === 0) {
            $this.listResults().last().addClass(config.activeItemClass);
          } else {
            $this.prevResult();
          }
          break;
        case 40:
          event.preventDefault();
          if ($active.length === 0) {
            $this.listResults().first().addClass(config.activeItemClass);
          } else if ($active != $this.listResults().last()) {
            $this.nextResult();
          }
          break;
        case 27:
          $this.hideList();
          suppressKey = true;
          break;
        default:
          $this.submitted = false;
          break;
        }
      });

      // opera wants keypress rather than keydown to prevent the form submit
      $this.keypress(function (event) {
        if ((event.which == 13) && ($this.activeResult().length > 0)) {
          event.preventDefault();
        }
      });

      // stupid hack to get around loss of focus on mousedown
      var mouseDown = false;
      var blurWait = false;
      $(document).bind('mousedown.swiftype' + ++ident, function () {
        mouseDown = true;
      });
      $(document).bind('mouseup.swiftype' + ident, function () {
        mouseDown = false;
        if (blurWait) {
          blurWait = false;
          $this.hideList();
        }
      });
      $this.blur(function () {
        if (mouseDown) {
          blurWait = true;
        } else {
          $this.hideList();
        }
      });
      $this.focus(function () {
        setTimeout(function() { $this.select() }, 10);
        if ($this.listResults().filter(':not(.' + config.noResultsClass + ')').length > 0) {
          $list.show();
        }
      });
    });
  };

  var normalize = function(str) {
    return $.trim(str).toLowerCase();
  };

  var callRemote = function ($this, term) {
    $this.abortCurrent();

    var params = {},
      config = $this.data('swiftype-config');

    params['q'] = term;
    params['engine_key'] = config.engineKey;

    function handleFunctionParam(field) {
      if (field !== undefined) {
        var evald = field;
        if (typeof evald === 'function') {
          evald = evald.call();
        }
        return evald;
      }
      return undefined;
    }

    params['search_fields'] = handleFunctionParam(config.searchFields);
    params['fetch_fields'] = handleFunctionParam(config.fetchFields);
    params['filters'] = handleFunctionParam(config.filters);
    params['document_types'] = handleFunctionParam(config.documentTypes);
    params['functional_boosts'] = handleFunctionParam(config.functionalBoosts);
    params['sort_field'] = handleFunctionParam(config.sortField);
    params['sort_direction'] = handleFunctionParam(config.sortDirection);
    params['per_page'] = config.resultLimit;

    var endpoint = Swiftype.root_url + '/api/v1/public/engines/suggest.json';
    $this.currentRequest = $.ajax({
      type: 'GET',
      dataType: 'jsonp',
      url: endpoint,
      data: params
    }).success(function(data) {
      var norm = normalize(term);
      if (data.record_count > 0) {
        $this.cache.put(norm, data.records);
      } else {
        $this.addEmpty(norm);
        $this.data('swiftype-list').empty().hide();
        return;
      }
      processData($this, data.records, term);
    });
  };

  var getResults = function($this, term) {
    var norm = normalize(term);
    if ($this.isEmpty(norm)) {
      $this.data('swiftype-list').empty().hide();
      return;
    }
    var cached = $this.cache.get(norm);
    if (cached) {
      processData($this, cached, term);
    } else {
      callRemote($this, term);
    }
  };

  // private helpers
  var processInput = function ($this) {
      var term = $this.val();
      if (term === $this.lastValue) {
        return;
      }
      $this.lastValue = term;
      if ($.trim(term) === '') {
        $this.data('swiftype-list').empty().hide();
        return;
      }
      if (typeof $this.data('swiftype-config').engineKey !== 'undefined') {
        getResults($this, term);
      }
    };

  var processData = function ($this, data, term) {
      var $list = $this.data('swiftype-list'),
        config = $this.data('swiftype-config');

      $list.empty().hide();
      config.resultRenderFunction($this.getContext(), data);

      var totalItems = $this.listResults().length;
      if ((totalItems > 0 && $this.focused()) || (config.noResultsMessage !== undefined)) {
        if ($this.submitted) {
          $this.submitted = false;
        } else {
          $list.show();
        }
      }
    };

  var defaultResultRenderFunction = function(ctx, results) {
    var $list = ctx.list,
      config = ctx.config;

    $.each(results, function(document_type, items) {
      $.each(items, function(idx, item) {
        ctx.registerResult($('
' + config.renderFunction(document_type, item) + '
').appendTo($list), item);
      });
    });
  };

  var defaultRenderFunction = function(document_type, item) {
    return '
' + item['title'] + '
';
  };

  var defaultOnComplete = function(item, prefix) {
    window.location = item['url'];
  };

	// simple client-side LRU Cache, based on https://github.com/rsms/js-lru

	function LRUCache(limit) {
	  this.size = 0;
	  this.limit = limit;
	  this._keymap = {};
	}

  LRUCache.prototype.put = function (key, value) {
    var entry = {
      key: key,
      value: value
    };
    this._keymap[key] = entry;
    if (this.tail) {
      this.tail.newer = entry;
      entry.older = this.tail;
    } else {
      this.head = entry;
    }
    this.tail = entry;
    if (this.size === this.limit) {
      return this.shift();
    } else {
      this.size++;
    }
  };

  LRUCache.prototype.shift = function () {
    var entry = this.head;
    if (entry) {
      if (this.head.newer) {
        this.head = this.head.newer;
        this.head.older = undefined;
      } else {
        this.head = undefined;
      }
      entry.newer = entry.older = undefined;
      delete this._keymap[entry.key];
    }
    return entry;
  };

  LRUCache.prototype.get = function (key, returnEntry) {
    var entry = this._keymap[key];
    if (entry === undefined) return;
    if (entry === this.tail) {
      return entry.value;
    }
    if (entry.newer) {
      if (entry === this.head) this.head = entry.newer;
      entry.newer.older = entry.older;
    }
    if (entry.older) entry.older.newer = entry.newer;
    entry.newer = undefined;
    entry.older = this.tail;
    if (this.tail) this.tail.newer = entry;
    this.tail = entry;
    return returnEntry ? entry : entry.value;
  };

  LRUCache.prototype.remove = function (key) {
    var entry = this._keymap[key];
    if (!entry) return;
    delete this._keymap[entry.key];
    if (entry.newer && entry.older) {
      entry.older.newer = entry.newer;
      entry.newer.older = entry.older;
    } else if (entry.newer) {
      entry.newer.older = undefined;
      this.head = entry.newer;
    } else if (entry.older) {
      entry.older.newer = undefined;
      this.tail = entry.older;
    } else {
      this.head = this.tail = undefined;
    }

    this.size--;
    return entry.value;
  };

  LRUCache.prototype.clear = function () {
    this.head = this.tail = undefined;
    this.size = 0;
    this._keymap = {};
  };

  if (typeof Object.keys === 'function') {
    LRUCache.prototype.keys = function () {
      return Object.keys(this._keymap);
    };
  } else {
    LRUCache.prototype.keys = function () {
      var keys = [];
      for (var k in this._keymap) keys.push(k);
      return keys;
    };
  }

  $.fn.swiftype.defaults = {
    activeItemClass: 'active',
    attachTo: undefined,
    documentTypes: undefined,
    filters: undefined,
    engineKey: undefined,
    searchFields: undefined,
    functionalBoosts: undefined,
    sortField: undefined,
    sortDirection: undefined,
    fetchFields: undefined,
    noResultsClass: 'noResults',
    noResultsMessage: undefined,
    onComplete: defaultOnComplete,
    resultRenderFunction: defaultResultRenderFunction,
    renderFunction: defaultRenderFunction,
    resultLimit: undefined,
    suggestionListType: 'ul',
    suggestionListClass: 'st-autocomplete',
    resultListSelector: 'li',
    setWidth: true,
    typingDelay: 80
  };

})(jQuery);
<commit_msg>use doc_id<commit_after>(function ($) {
  var ident = 0;

  window.Swiftype = window.Swiftype || {};
  Swiftype.root_url = 'https://api.swiftype.com';
  Swiftype.pingUrl = function(endpoint, callback) {
    var img  = new Image();
    img.onload = img.onerror = callback;
    img.src = endpoint;
    setTimeout(callback, 350);
    return false;
  };
  Swiftype.pingAutoSelection = function(engineKey, docId, value, callback) {
    var params = {
      t: new Date().getTime(),
      engine_key: engineKey,
      doc_id: docId,
      prefix: value
    };
    var url = Swiftype.root_url + '/api/v1/public/analytics/pas?' + $.param(params);
    Swiftype.pingUrl(url, callback);
  };

  $.fn.swiftype = function (options) {
    var options = $.extend({}, $.fn.swiftype.defaults, options);

    return this.each(function () {
      var $this = $(this);
      var config = $.meta ? $.extend({}, options, $this.data()) : options;
      $this.attr('autocomplete', 'off');
      $this.data('swiftype-config', config);
      $this.submitted = false;
      $this.cache = new LRUCache(10);
      $this.emptyQueries = [];

      $this.computeDropdownStyles = function() {
        var $attachEl = config.attachTo ? $(config.attachTo) : $this;
        var offset = $attachEl.offset();
        var styles = {
          'position': 'absolute',
          'z-index': 9999,
          'top': offset.top + $attachEl.outerHeight() + 1,
          'left': offset.left
        };
        if (config.setWidth) {
          styles['width'] = $attachEl.outerWidth() - 2;
        }
        return styles;
      }

      $this.isEmpty = function(query) {
        return $.inArray(normalize(query), this.emptyQueries) >= 0
      };

      $this.addEmpty = function(query) {
        $this.emptyQueries.unshift(normalize(query));
      };

      var styles = $this.computeDropdownStyles();
      var $list = $('<' + config.suggestionListType + ' />').addClass(config.suggestionListClass).appendTo('body').hide().css(styles);
      $this.data('swiftype-list', $list);

      $this.abortCurrent = function() {
        if ($this.currentRequest) {
          $this.currentRequest.abort();
        }
      };

      $this.hideList = function() {
        setTimeout(function() { $list.hide(); }, 10);
      };

      $this.focused = function() {
        return $this.is(':focus');
      };

      $this.submitting = function() {
        $this.submitted = true;
      };

      $this.listResults = function() {
        return $(config.resultListSelector, $list);
      };

      $this.activeResult = function() {
        return $this.listResults().filter('.' + config.activeItemClass).first();
      };

      $this.prevResult = function() {
        var list = $this.listResults(),
          currentIdx = list.index($this.activeResult()),
          nextIdx = currentIdx - 1,
          next = list.eq(nextIdx);
        $this.listResults().removeClass(config.activeItemClass);
        if (nextIdx >= 0) {
          next.addClass(config.activeItemClass);
        }
      };

      $this.nextResult = function() {
        var list = $this.listResults(),
          currentIdx = list.index($this.activeResult()),
          nextIdx = currentIdx + 1,
          next = list.eq(nextIdx);
        $this.listResults().removeClass(config.activeItemClass);
        if (nextIdx >= 0) {
          next.addClass(config.activeItemClass);
        }
      };

      $this.selectedCallback = function(data) {
        return function() {
          var value = $this.val(),
            callback = function() {
              config.onComplete(data, value);
            };
          Swiftype.pingAutoSelection(config.engineKey, data['id'], value, callback);
        };
      };

      $this.registerResult = function($element, data) {
        $element.data('swiftype-item', data);
        $element.click($this.selectedCallback(data)).mouseover(function () {
          $this.listResults().removeClass(config.activeItemClass);
          $element.addClass(config.activeItemClass);
        });
      };

      $this.getContext = function() {
        return {
          config: config,
          list: $list,
          registerResult: $this.registerResult
        };
      };

      var typingDelayPointer;
      var suppressKey = false;
      $this.lastValue = '';
      $this.keyup(function (event) {
        if (suppressKey) {
          suppressKey = false;
          return;
        }

        // ignore arrow keys, shift
        if (((event.which > 36) && (event.which < 41)) || (event.which == 16)) return;

        if (config.typingDelay > 0) {
          clearTimeout(typingDelayPointer);
          typingDelayPointer = setTimeout(function () {
            processInput($this);
          }, config.typingDelay);
        } else {
          processInput($this);
        }
      });

      $this.styleDropdown = function() {
        $list.css($this.computeDropdownStyles());
      };

      $this.keydown(function (event) {
        $this.styleDropdown();
        // enter = 13; up = 38; down = 40; esc = 27
        var $active = $this.activeResult();
        switch (event.which) {
        case 13:
          if (($active.length !== 0) && ($list.is(':visible'))) {
            event.preventDefault();
            $this.selectedCallback($active.data('swiftype-item'))();
          } else if ($this.currentRequest) {
            $this.submitting();
          }
          $this.hideList();
          suppressKey = true;
          break;
        case 38:
          event.preventDefault();
          if ($active.length === 0) {
            $this.listResults().last().addClass(config.activeItemClass);
          } else {
            $this.prevResult();
          }
          break;
        case 40:
          event.preventDefault();
          if ($active.length === 0) {
            $this.listResults().first().addClass(config.activeItemClass);
          } else if ($active != $this.listResults().last()) {
            $this.nextResult();
          }
          break;
        case 27:
          $this.hideList();
          suppressKey = true;
          break;
        default:
          $this.submitted = false;
          break;
        }
      });

      // opera wants keypress rather than keydown to prevent the form submit
      $this.keypress(function (event) {
        if ((event.which == 13) && ($this.activeResult().length > 0)) {
          event.preventDefault();
        }
      });

      // stupid hack to get around loss of focus on mousedown
      var mouseDown = false;
      var blurWait = false;
      $(document).bind('mousedown.swiftype' + ++ident, function () {
        mouseDown = true;
      });
      $(document).bind('mouseup.swiftype' + ident, function () {
        mouseDown = false;
        if (blurWait) {
          blurWait = false;
          $this.hideList();
        }
      });
      $this.blur(function () {
        if (mouseDown) {
          blurWait = true;
        } else {
          $this.hideList();
        }
      });
      $this.focus(function () {
        setTimeout(function() { $this.select() }, 10);
        if ($this.listResults().filter(':not(.' + config.noResultsClass + ')').length > 0) {
          $list.show();
        }
      });
    });
  };

  var normalize = function(str) {
    return $.trim(str).toLowerCase();
  };

  var callRemote = function ($this, term) {
    $this.abortCurrent();

    var params = {},
      config = $this.data('swiftype-config');

    params['q'] = term;
    params['engine_key'] = config.engineKey;

    function handleFunctionParam(field) {
      if (field !== undefined) {
        var evald = field;
        if (typeof evald === 'function') {
          evald = evald.call();
        }
        return evald;
      }
      return undefined;
    }

    params['search_fields'] = handleFunctionParam(config.searchFields);
    params['fetch_fields'] = handleFunctionParam(config.fetchFields);
    params['filters'] = handleFunctionParam(config.filters);
    params['document_types'] = handleFunctionParam(config.documentTypes);
    params['functional_boosts'] = handleFunctionParam(config.functionalBoosts);
    params['sort_field'] = handleFunctionParam(config.sortField);
    params['sort_direction'] = handleFunctionParam(config.sortDirection);
    params['per_page'] = config.resultLimit;

    var endpoint = Swiftype.root_url + '/api/v1/public/engines/suggest.json';
    $this.currentRequest = $.ajax({
      type: 'GET',
      dataType: 'jsonp',
      url: endpoint,
      data: params
    }).success(function(data) {
      var norm = normalize(term);
      if (data.record_count > 0) {
        $this.cache.put(norm, data.records);
      } else {
        $this.addEmpty(norm);
        $this.data('swiftype-list').empty().hide();
        return;
      }
      processData($this, data.records, term);
    });
  };

  var getResults = function($this, term) {
    var norm = normalize(term);
    if ($this.isEmpty(norm)) {
      $this.data('swiftype-list').empty().hide();
      return;
    }
    var cached = $this.cache.get(norm);
    if (cached) {
      processData($this, cached, term);
    } else {
      callRemote($this, term);
    }
  };

  // private helpers
  var processInput = function ($this) {
      var term = $this.val();
      if (term === $this.lastValue) {
        return;
      }
      $this.lastValue = term;
      if ($.trim(term) === '') {
        $this.data('swiftype-list').empty().hide();
        return;
      }
      if (typeof $this.data('swiftype-config').engineKey !== 'undefined') {
        getResults($this, term);
      }
    };

  var processData = function ($this, data, term) {
      var $list = $this.data('swiftype-list'),
        config = $this.data('swiftype-config');

      $list.empty().hide();
      config.resultRenderFunction($this.getContext(), data);

      var totalItems = $this.listResults().length;
      if ((totalItems > 0 && $this.focused()) || (config.noResultsMessage !== undefined)) {
        if ($this.submitted) {
          $this.submitted = false;
        } else {
          $list.show();
        }
      }
    };

  var defaultResultRenderFunction = function(ctx, results) {
    var $list = ctx.list,
      config = ctx.config;

    $.each(results, function(document_type, items) {
      $.each(items, function(idx, item) {
        ctx.registerResult($('
' + config.renderFunction(document_type, item) + '
').appendTo($list), item);
      });
    });
  };

  var defaultRenderFunction = function(document_type, item) {
    return '
' + item['title'] + '
';
  };

  var defaultOnComplete = function(item, prefix) {
    window.location = item['url'];
  };

	// simple client-side LRU Cache, based on https://github.com/rsms/js-lru

	function LRUCache(limit) {
	  this.size = 0;
	  this.limit = limit;
	  this._keymap = {};
	}

  LRUCache.prototype.put = function (key, value) {
    var entry = {
      key: key,
      value: value
    };
    this._keymap[key] = entry;
    if (this.tail) {
      this.tail.newer = entry;
      entry.older = this.tail;
    } else {
      this.head = entry;
    }
    this.tail = entry;
    if (this.size === this.limit) {
      return this.shift();
    } else {
      this.size++;
    }
  };

  LRUCache.prototype.shift = function () {
    var entry = this.head;
    if (entry) {
      if (this.head.newer) {
        this.head = this.head.newer;
        this.head.older = undefined;
      } else {
        this.head = undefined;
      }
      entry.newer = entry.older = undefined;
      delete this._keymap[entry.key];
    }
    return entry;
  };

  LRUCache.prototype.get = function (key, returnEntry) {
    var entry = this._keymap[key];
    if (entry === undefined) return;
    if (entry === this.tail) {
      return entry.value;
    }
    if (entry.newer) {
      if (entry === this.head) this.head = entry.newer;
      entry.newer.older = entry.older;
    }
    if (entry.older) entry.older.newer = entry.newer;
    entry.newer = undefined;
    entry.older = this.tail;
    if (this.tail) this.tail.newer = entry;
    this.tail = entry;
    return returnEntry ? entry : entry.value;
  };

  LRUCache.prototype.remove = function (key) {
    var entry = this._keymap[key];
    if (!entry) return;
    delete this._keymap[entry.key];
    if (entry.newer && entry.older) {
      entry.older.newer = entry.newer;
      entry.newer.older = entry.older;
    } else if (entry.newer) {
      entry.newer.older = undefined;
      this.head = entry.newer;
    } else if (entry.older) {
      entry.older.newer = undefined;
      this.tail = entry.older;
    } else {
      this.head = this.tail = undefined;
    }

    this.size--;
    return entry.value;
  };

  LRUCache.prototype.clear = function () {
    this.head = this.tail = undefined;
    this.size = 0;
    this._keymap = {};
  };

  if (typeof Object.keys === 'function') {
    LRUCache.prototype.keys = function () {
      return Object.keys(this._keymap);
    };
  } else {
    LRUCache.prototype.keys = function () {
      var keys = [];
      for (var k in this._keymap) keys.push(k);
      return keys;
    };
  }

  $.fn.swiftype.defaults = {
    activeItemClass: 'active',
    attachTo: undefined,
    documentTypes: undefined,
    filters: undefined,
    engineKey: undefined,
    searchFields: undefined,
    functionalBoosts: undefined,
    sortField: undefined,
    sortDirection: undefined,
    fetchFields: undefined,
    noResultsClass: 'noResults',
    noResultsMessage: undefined,
    onComplete: defaultOnComplete,
    resultRenderFunction: defaultResultRenderFunction,
    renderFunction: defaultRenderFunction,
    resultLimit: undefined,
    suggestionListType: 'ul',
    suggestionListClass: 'st-autocomplete',
    resultListSelector: 'li',
    setWidth: true,
    typingDelay: 80
  };

})(jQuery);
<|endoftext|>


<commit_before>Game.resources = {
    'food': 0,
    'wood': 0,
    'iron': 0,
    'metal': 0,
    'cash': 0,
};

Game.techs = [
    {
    'name': 'smelting',
    'title': 'Smelting',
    'resources': { // resources required
        'iron': 10
    },
    'buildings': { // buildings required for tech to be available
        'farm': 0
    },
}
]
Game.techs_unlocked = {} // for fast lookup, presence in hash indicates the tech is unlocked

Game.buildings = [
    {
    'name': 'hut',
    'title': 'Hut',
    'uses': { // resources consumed per tick
        'food': 0
    },
    'resources': { // resources required to build
        'food': 0
    },
    'requires': [ // techs required to build, list of names

    ],
    'produces': { // resources produced
        'food': 1
    },
    'provides': [ // techs provided
    ],
    'count': 0
}
]

Game.buildings_unlocked = {} // building => count
<commit_msg>Added a mine and a sawmill<commit_after>Game.resources = {
    'food': 0,
    'wood': 0,
    'iron': 0,
    'metal': 0,
    'cash': 0,
};

Game.techs = [
    {
    'name': 'smelting',
    'title': 'Smelting',
    'resources': { // resources required
        'iron': 10
    },
    'buildings': { // buildings required for tech to be available
        'farm': 0
    },
}
];

Game.techs_unlocked = {}; // for fast lookup, presence in hash indicates the tech is unlocked

Game.buildings = [
    {
    'name': 'hut',
    'title': 'Hut',
    'consumes': { // resources consumed per tick
        'food': 0
    },
    'produces': { // resources produced
        'food': 1
    },
    'resources': { // resources required to build
        'wood': 1
    },
    'requires': [ // techs required to build, list of names
    ],
    'provides': [ // techs provided
    ]
},
{
    'name': 'sawmill',
    'title': 'Sawmill',
    'consumes': {'food': 1},
    'produces': {'wood': 1},
    'resources': {'food': 1},
    'requires': [],
    'provides': []
},
{
    'name': 'mine',
    'title': 'Mine',
    'consumes': {'food': 1, 'wood': 1},
    'produces': {'ore': 1},
    'resources': {'food': 10, 'wood': 10},
    'requires': [],
    'provides': []
}

];

Game.buildings_unlocked = { // building => count
'hut' => 1
};
<|endoftext|>


<commit_before>'use strict'
var AstWalker = require('../util/astWalker')

/**
  * return all contract definitions of the given @astList
  *
  * @param {Object} sourcesList - sources list (containing root AST node)
  * @return {Object} - returns a mapping from AST node ids to AST nodes for the contracts
  */
function extractContractDefinitions (sourcesList) {
  var ret = {
    contractsById: {},
    contractsByName: {}
  }
  var walker = new AstWalker()
  walker.walkAstList(sourcesList, { 'ContractDefinition': function (node) {
    ret.contractsById[node.id] = node
    ret.contractsByName[node.attributes.name] = node
    return false
  }})
  return ret
}

/**
  * returns the linearized base contracts of the contract @arg id
  *
  * @param {Int} id - contract id to resolve
  * @param {Map} contracts  - all contracts defined in the current context
  * @return {Array} - array of base contracts in derived to base order as AST nodes.
  */
function getLinearizedBaseContracts (id, contractsById) {
  return contractsById[id].attributes.linearizedBaseContracts.map(function (id) { return contractsById[id] })
}

/**
  * return state var and type definition of the given contract
  *
  * @param {String} contractName - contract for which state var should be resolved
  * @param {Object} sourcesList - sources list (containing root AST node)
  * @param {Object} [contracts] - map of contract definitions (contains contractsById, contractsByName)
  * @return {Object} - return an object containing: stateItems - list of all the children node of the @arg contractName
  *                                                 stateVariables - list of all the variable declaration of the @arg contractName
  */
function extractStateDefinitions (contractName, sourcesList, contracts) {
  if (!contracts) {
    contracts = extractContractDefinitions(sourcesList)
  }
  var node = contracts.contractsByName[contractName]
  if (node) {
    var stateItems = []
    var stateVar = []
    var baseContracts = getLinearizedBaseContracts(node.id, contracts.contractsById)
    baseContracts.reverse()
    for (var k in baseContracts) {
      var ctr = baseContracts[k]
      for (var i in ctr.children) {
        var item = ctr.children[i]
        stateItems.push(item)
        if (item.name === 'VariableDeclaration') {
          stateVar.push(item)
        }
      }
    }
    return {
      stateDefinitions: stateItems,
      stateVariables: stateVar
    }
  }
  return null
}

/**
  * return state var and type definition of all the contracts from the given @args sourcesList
  *
  * @param {Object} sourcesList - sources list (containing root AST node)
  * @return {Object} - returns a mapping between contract name and contract state
  */
function extractStatesDefinitions (sourcesList) {
  var contracts = extractContractDefinitions(sourcesList)
  var ret = {}
  for (var contract in contracts.contractsById) {
    var name = contracts.contractsById[contract].attributes.name
    ret[name] = extractStateDefinitions(name, sourcesList, contracts)
  }
  return ret
}

module.exports = {
  extractStatesDefinitions: extractStatesDefinitions,
  extractStateDefinitions: extractStateDefinitions,
  extractContractDefinitions: extractContractDefinitions,
  getLinearizedBaseContracts: getLinearizedBaseContracts
}
<commit_msg>add optional param<commit_after>'use strict'
var AstWalker = require('../util/astWalker')

/**
  * return all contract definitions of the given @astList
  *
  * @param {Object} sourcesList - sources list (containing root AST node)
  * @return {Object} - returns a mapping from AST node ids to AST nodes for the contracts
  */
function extractContractDefinitions (sourcesList) {
  var ret = {
    contractsById: {},
    contractsByName: {}
  }
  var walker = new AstWalker()
  walker.walkAstList(sourcesList, { 'ContractDefinition': function (node) {
    ret.contractsById[node.id] = node
    ret.contractsByName[node.attributes.name] = node
    return false
  }})
  return ret
}

/**
  * returns the linearized base contracts of the contract @arg id
  *
  * @param {Int} id - contract id to resolve
  * @param {Map} contracts  - all contracts defined in the current context
  * @return {Array} - array of base contracts in derived to base order as AST nodes.
  */
function getLinearizedBaseContracts (id, contractsById) {
  return contractsById[id].attributes.linearizedBaseContracts.map(function (id) { return contractsById[id] })
}

/**
  * return state var and type definition of the given contract
  *
  * @param {String} contractName - contract for which state var should be resolved
  * @param {Object} sourcesList - sources list (containing root AST node)
  * @param {Object} [contracts] - map of contract definitions (contains contractsById, contractsByName)
  * @return {Object} - return an object containing: stateItems - list of all the children node of the @arg contractName
  *                                                 stateVariables - list of all the variable declaration of the @arg contractName
  */
function extractStateDefinitions (contractName, sourcesList, contracts) {
  if (!contracts) {
    contracts = extractContractDefinitions(sourcesList)
  }
  var node = contracts.contractsByName[contractName]
  if (node) {
    var stateItems = []
    var stateVar = []
    var baseContracts = getLinearizedBaseContracts(node.id, contracts.contractsById)
    baseContracts.reverse()
    for (var k in baseContracts) {
      var ctr = baseContracts[k]
      for (var i in ctr.children) {
        var item = ctr.children[i]
        stateItems.push(item)
        if (item.name === 'VariableDeclaration') {
          stateVar.push(item)
        }
      }
    }
    return {
      stateDefinitions: stateItems,
      stateVariables: stateVar
    }
  }
  return null
}

/**
  * return state var and type definition of all the contracts from the given @args sourcesList
  *
  * @param {Object} sourcesList - sources list (containing root AST node)
  * @param {Object} [contracts] - map of contract definitions (contains contractsById, contractsByName)
  * @return {Object} - returns a mapping between contract name and contract state
  */
function extractStatesDefinitions (sourcesList, contracts) {
  if (!contracts) {
    contracts = extractContractDefinitions(sourcesList)
  }
  var ret = {}
  for (var contract in contracts.contractsById) {
    var name = contracts.contractsById[contract].attributes.name
    ret[name] = extractStateDefinitions(name, sourcesList, contracts)
  }
  return ret
}

module.exports = {
  extractStatesDefinitions: extractStatesDefinitions,
  extractStateDefinitions: extractStateDefinitions,
  extractContractDefinitions: extractContractDefinitions,
  getLinearizedBaseContracts: getLinearizedBaseContracts
}
<|endoftext|>


<commit_before>(function() {
    window.avalltJS = {};
    var addFn = function(fnName, fn) {
        window.avalltJS[fnName] = fn;
    }

    /**
     * Determines whether the passed value is an array
     *
     * @param  {Object} value   the object to be checked
     * @return {boolean}        true, if value is an array
     */
    var isArray = function(value) {
        return toString.call(value) === '[object Array]';
    }
    addFn('isArray', isArray);

    /**
     * Determines whether the passed value is an object
     *
     * @param  {Object} value   the object to be checked
     * @return {boolean}        true, if value is an object
     */
    var isObject = function(value) {
        return toString.call(value) === '[object Object]';
    };

    /*******************************************************************/

    /**
     * Analyses the diff between given objects
     *
     * @param  {Object} objectL
     * @param  {Object} objectR
     * @return {Object} calculated diff information about the given objects
     */
    var diff = function(objectL, objectR) {
        var propertiesOfLeft = [],
            propertiesOfRight = [],
            missingPropertiesLeft = [],
            missingPropertiesRight = [],
            valuesDiff = [];

        for (var property in objectL) {
            if (objectL.hasOwnProperty(property)) {
                propertiesOfLeft.push(property);
            }
        }

        for (var property in objectR) {
            if (objectR.hasOwnProperty(property)) {
                propertiesOfRight.push(property);
            }
        }
        var propertyExistsInList = function(property, list) {
            for (var j = 0; j < list.length; j++) {
                if (property === list[j]) {
                    return true;
                }
            }
            return false;
        }

        for (var i = 0; i < propertiesOfLeft.length; i++) {
            var property = propertiesOfLeft[i];

            if (propertyExistsInList(property, propertiesOfRight) === false) {
                missingPropertiesLeft.push(property);
            }
        }

        for (var i = 0; i < propertiesOfRight.length; i++) {
            var property = propertiesOfRight[i];

            if (propertyExistsInList(property, propertiesOfLeft) === false) {
                missingPropertiesRight.push(property);
            } else {
                valuesDiff.push({
                    property: property,
                    left: objectL[property],
                    right: objectR[property]
                });
            }
        }

        return {
            propsLeft: propertiesOfLeft,
            propsRight: propertiesOfRight,
            missingPropsLeft: missingPropertiesLeft,
            missingPropsRight: missingPropertiesRight,
            valuesDiff: valuesDiff
        }
    }
    addFn('diff', diff);

    /*******************************************************************/

    var _handleObjectProperty = function(item, property) {
        if (isObject(item)) {
            removeNestedProperty(item, property);
        } else if (isArray(item)) {
            for (var i = 0; i < item.length; i++) {
                removeNestedProperty(item[i], property);
            }
        }
    }

    /**
     * Frees the source object from given property. It also detects and removes
     * the given property in nested objects.
     *
     * @param  {Object} obj      source object
     * @param  {String} property property to remove
     * @return {Object}          object, which is freed from given property
     */
    var removeNestedProperty = function(obj, property) {
        for (var prop in obj) {
            if (obj.hasOwnProperty(prop)) {
                if (prop === property) {
                    delete obj[prop];
                } else {
                    _handleObjectProperty(obj[prop], property);
                }
            }
        }
        return obj;
    }
    addFn('removeNestedProperty', removeNestedProperty);

    /*******************************************************************/

})()
<commit_msg>Add function isObject<commit_after>(function() {
    window.avalltJS = {};
    var addFn = function(fnName, fn) {
        window.avalltJS[fnName] = fn;
    }

    /**
     * Determines whether the passed value is an array
     *
     * @param  {Object} value   the object to be checked
     * @return {boolean}        true, if value is an array
     */
    var isArray = function(value) {
        return toString.call(value) === '[object Array]';
    }
    addFn('isArray', isArray);

    /**
     * Determines whether the passed value is an object
     *
     * @param  {Object} value   the object to be checked
     * @return {boolean}        true, if value is an object
     */
    var isObject = function(value) {
        return toString.call(value) === '[object Object]';
    };
    addFn('isObject', isObject);

    /*******************************************************************/

    /**
     * Analyses the diff between given objects
     *
     * @param  {Object} objectL
     * @param  {Object} objectR
     * @return {Object} calculated diff information about the given objects
     */
    var diff = function(objectL, objectR) {
        var propertiesOfLeft = [],
            propertiesOfRight = [],
            missingPropertiesLeft = [],
            missingPropertiesRight = [],
            valuesDiff = [];

        for (var property in objectL) {
            if (objectL.hasOwnProperty(property)) {
                propertiesOfLeft.push(property);
            }
        }

        for (var property in objectR) {
            if (objectR.hasOwnProperty(property)) {
                propertiesOfRight.push(property);
            }
        }
        var propertyExistsInList = function(property, list) {
            for (var j = 0; j < list.length; j++) {
                if (property === list[j]) {
                    return true;
                }
            }
            return false;
        }

        for (var i = 0; i < propertiesOfLeft.length; i++) {
            var property = propertiesOfLeft[i];

            if (propertyExistsInList(property, propertiesOfRight) === false) {
                missingPropertiesLeft.push(property);
            }
        }

        for (var i = 0; i < propertiesOfRight.length; i++) {
            var property = propertiesOfRight[i];

            if (propertyExistsInList(property, propertiesOfLeft) === false) {
                missingPropertiesRight.push(property);
            } else {
                valuesDiff.push({
                    property: property,
                    left: objectL[property],
                    right: objectR[property]
                });
            }
        }

        return {
            propsLeft: propertiesOfLeft,
            propsRight: propertiesOfRight,
            missingPropsLeft: missingPropertiesLeft,
            missingPropsRight: missingPropertiesRight,
            valuesDiff: valuesDiff
        }
    }
    addFn('diff', diff);

    /*******************************************************************/

    var _handleObjectProperty = function(item, property) {
        if (isObject(item)) {
            removeNestedProperty(item, property);
        } else if (isArray(item)) {
            for (var i = 0; i < item.length; i++) {
                removeNestedProperty(item[i], property);
            }
        }
    }

    /**
     * Frees the source object from given property. It also detects and removes
     * the given property in nested objects.
     *
     * @param  {Object} obj      source object
     * @param  {String} property property to remove
     * @return {Object}          object, which is freed from given property
     */
    var removeNestedProperty = function(obj, property) {
        for (var prop in obj) {
            if (obj.hasOwnProperty(prop)) {
                if (prop === property) {
                    delete obj[prop];
                } else {
                    _handleObjectProperty(obj[prop], property);
                }
            }
        }
        return obj;
    }
    addFn('removeNestedProperty', removeNestedProperty);

    /*******************************************************************/

})()
<|endoftext|>


<commit_before>'use strict';

module.exports = {
  plugins: ['unicorn'],
  rules: {
    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/catch-error-name.md
    'unicorn/catch-error-name': ['error', { name: 'err' }],

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/explicit-length-check.md
    'unicorn/explicit-length-check': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/filename-case.md
    'unicorn/filename-case': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-abusive-eslint-disable.md
    'unicorn/no-abusive-eslint-disable': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-process-exit.md
    'unicorn/no-process-exit': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/throw-new-error.md
    'unicorn/throw-new-error': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/number-literal-case.md
    'unicorn/number-literal-case': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/escape-case.md
    'unicorn/escape-case': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-array-instanceof.md
    'unicorn/no-array-instanceof': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-new-buffer.md
    'unicorn/no-new-buffer': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-hex-escape.md
    'unicorn/no-hex-escape': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/custom-error-definition.md
    'unicorn/custom-error-definition': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-starts-ends-with.md
    'unicorn/prefer-starts-ends-with': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-type-error.md
    'unicorn/prefer-type-error': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-fn-reference-in-iterator.md
    'unicorn/no-fn-reference-in-iterator': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/import-index.md
    'unicorn/import-index': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/new-for-builtins.md
    'unicorn/new-for-builtins': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/regex-shorthand.md
    'unicorn/regex-shorthand': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-spread.md
    'unicorn/prefer-spread': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/error-message.md
    'unicorn/error-message': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-unsafe-regex.md
    'unicorn/no-unsafe-regex': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-add-event-listener.md
    'unicorn/prefer-add-event-listener': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-exponentiation-operator.md
    'unicorn/prefer-exponentiation-operator': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-query-selector.md
    'unicorn/prefer-query-selector': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-node-append.md
    'unicorn/prefer-node-append': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-unused-properties.md
    'unicorn/no-unused-properties': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-unreadable-array-destructuring.md
    'unicorn/no-unreadable-array-destructuring': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-console-spaces.md
    'unicorn/no-console-spaces': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prevent-abbreviations.md
    'unicorn/prevent-abbreviations': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-for-loop.md
    'unicorn/no-for-loop': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-zero-fractions.md
    'unicorn/no-zero-fractions': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-includes.md
    'unicorn/prefer-includes': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-text-content.md
    'unicorn/prefer-text-content': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-node-remove.md
    'unicorn/prefer-node-remove': 'error',
  },
};
<commit_msg>fix: disable unicorn/prevent-abbreviations<commit_after>'use strict';

module.exports = {
  plugins: ['unicorn'],
  rules: {
    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/catch-error-name.md
    'unicorn/catch-error-name': ['error', { name: 'err' }],

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/explicit-length-check.md
    'unicorn/explicit-length-check': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/filename-case.md
    'unicorn/filename-case': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-abusive-eslint-disable.md
    'unicorn/no-abusive-eslint-disable': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-process-exit.md
    'unicorn/no-process-exit': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/throw-new-error.md
    'unicorn/throw-new-error': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/number-literal-case.md
    'unicorn/number-literal-case': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/escape-case.md
    'unicorn/escape-case': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-array-instanceof.md
    'unicorn/no-array-instanceof': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-new-buffer.md
    'unicorn/no-new-buffer': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-hex-escape.md
    'unicorn/no-hex-escape': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/custom-error-definition.md
    'unicorn/custom-error-definition': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-starts-ends-with.md
    'unicorn/prefer-starts-ends-with': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-type-error.md
    'unicorn/prefer-type-error': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-fn-reference-in-iterator.md
    'unicorn/no-fn-reference-in-iterator': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/import-index.md
    'unicorn/import-index': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/new-for-builtins.md
    'unicorn/new-for-builtins': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/regex-shorthand.md
    'unicorn/regex-shorthand': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-spread.md
    'unicorn/prefer-spread': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/error-message.md
    'unicorn/error-message': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-unsafe-regex.md
    'unicorn/no-unsafe-regex': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-add-event-listener.md
    'unicorn/prefer-add-event-listener': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-exponentiation-operator.md
    'unicorn/prefer-exponentiation-operator': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-query-selector.md
    'unicorn/prefer-query-selector': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-node-append.md
    'unicorn/prefer-node-append': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-unused-properties.md
    'unicorn/no-unused-properties': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-unreadable-array-destructuring.md
    'unicorn/no-unreadable-array-destructuring': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-console-spaces.md
    'unicorn/no-console-spaces': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prevent-abbreviations.md
    'unicorn/prevent-abbreviations': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-for-loop.md
    'unicorn/no-for-loop': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-zero-fractions.md
    'unicorn/no-zero-fractions': 'off',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-includes.md
    'unicorn/prefer-includes': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-text-content.md
    'unicorn/prefer-text-content': 'error',

    // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prefer-node-remove.md
    'unicorn/prefer-node-remove': 'error',
  },
};
<|endoftext|>


<commit_before>import { StateNavigator } from 'navigation';
import * as React from 'react';
import { Motion, TransitionMotion } from 'react-motion';
import spring from './spring.js'

class NavigationMotion extends React.Component {
    onNavigate(oldState, state, data, asyncData) {
        this.setState((prevState) => {
            var {url, crumbs} = this.getStateNavigator().stateContext;
            var scenes = {[url]: {element: state.renderScene(data, this.moveScene(url), asyncData)}};
            for(var i = 0; i < crumbs.length; i++) {
                scenes[crumbs[i].url] = {
                    ...prevState.scenes[crumbs[i].url],
                    style: null
                };
            }
            return {scenes};
        });
    }
    constructor(props, context) {
        super(props, context);
        this.onNavigate = this.onNavigate.bind(this);
        this.state = {scenes: {}};
    }
    getStateNavigator(){
        return this.props.stateNavigator || (this.context as any).stateNavigator;
    }
    componentDidMount() {
        var stateNavigator = this.getStateNavigator();
        stateNavigator.onNavigate(this.onNavigate);
        var {startStateKey, startNavigationData} = this.props;
        if (startStateKey)
            stateNavigator.navigate(startStateKey, startNavigationData);
    }
    componentWillUnmount() {
        this.getStateNavigator().offNavigate(this.onNavigate);
    }
    moveScene(url) {
        return style => {
            this.setState((prevState) => {
                var scenes = {...prevState.scenes};
                if (scenes[url])
                    scenes[url].style = style;
                return {scenes};
            }
        )};
    }
    renderScene({key, data: {scene, state, data, mount}, style: {transitioning, ...transitionStyle}}) {
        var {mountedStyle, crumbStyle, children} = this.props;
        var style = (scene && scene.style) || getStyle(mount ? mountedStyle : crumbStyle, state, data);
        return (
            <Motion key={key} style={transitioning ? transitionStyle : style}>
                {(tweenStyle) => children(tweenStyle, scene && scene.element, state, data)}
            </Motion>
        );
    }
    render() {
        var {oldState, oldData, state, data, crumbs, nextCrumb} = this.getStateNavigator().stateContext;
        if (!state)
            return null;
        var {unmountedStyle, mountedStyle, style} = this.props;
        var sceneContexts = crumbs.concat(nextCrumb);
        return (
            <TransitionMotion
                willEnter={() => getStyle(unmountedStyle, state, data, 1, true)}
                willLeave={() => getStyle(unmountedStyle, oldState, oldData, 1)}
                styles={sceneContexts.map(({state, data, url}) => {
                    var scene = this.state.scenes[url];
                    return {
                        key: url,
                        data: {scene, state, data, mount: url === nextCrumb.url},
                        style: getStyle((scene && scene.style) || mountedStyle, state, data, spring(0))
                    }
                })}>
                {tweenStyles => (

                        {tweenStyles.map((config) => this.renderScene(config))}

                )}
            </TransitionMotion>
        );
    }
}

function getStyle(styleProp, state, data, transitioning, strip) {
    var style = typeof styleProp === 'function' ? styleProp(state, data) : styleProp;
    var newStyle = {};
    for(var key in style) {
        newStyle[key] = (!strip || typeof style[key] === 'number') ? style[key] : style[key].val;
    }
    if (transitioning)
        newStyle.transitioning = transitioning;
    return newStyle;
}

NavigationMotion.contextTypes = {
    stateNavigator: React.PropTypes.object
}

export default NavigationMotion;
<commit_msg>Removed typescript typing<commit_after>import { StateNavigator } from 'navigation';
import * as React from 'react';
import { Motion, TransitionMotion } from 'react-motion';
import spring from './spring.js'

class NavigationMotion extends React.Component {
    onNavigate(oldState, state, data, asyncData) {
        this.setState((prevState) => {
            var {url, crumbs} = this.getStateNavigator().stateContext;
            var scenes = {[url]: {element: state.renderScene(data, this.moveScene(url), asyncData)}};
            for(var i = 0; i < crumbs.length; i++) {
                scenes[crumbs[i].url] = {
                    ...prevState.scenes[crumbs[i].url],
                    style: null
                };
            }
            return {scenes};
        });
    }
    constructor(props, context) {
        super(props, context);
        this.onNavigate = this.onNavigate.bind(this);
        this.state = {scenes: {}};
    }
    getStateNavigator(){
        return this.props.stateNavigator || this.context.stateNavigator;
    }
    componentDidMount() {
        var stateNavigator = this.getStateNavigator();
        stateNavigator.onNavigate(this.onNavigate);
        var {startStateKey, startNavigationData} = this.props;
        if (startStateKey)
            stateNavigator.navigate(startStateKey, startNavigationData);
    }
    componentWillUnmount() {
        this.getStateNavigator().offNavigate(this.onNavigate);
    }
    moveScene(url) {
        return style => {
            this.setState((prevState) => {
                var scenes = {...prevState.scenes};
                if (scenes[url])
                    scenes[url].style = style;
                return {scenes};
            }
        )};
    }
    renderScene({key, data: {scene, state, data, mount}, style: {transitioning, ...transitionStyle}}) {
        var {mountedStyle, crumbStyle, children} = this.props;
        var style = (scene && scene.style) || getStyle(mount ? mountedStyle : crumbStyle, state, data);
        return (
            <Motion key={key} style={transitioning ? transitionStyle : style}>
                {(tweenStyle) => children(tweenStyle, scene && scene.element, state, data)}
            </Motion>
        );
    }
    render() {
        var {oldState, oldData, state, data, crumbs, nextCrumb} = this.getStateNavigator().stateContext;
        if (!state)
            return null;
        var {unmountedStyle, mountedStyle, style} = this.props;
        var sceneContexts = crumbs.concat(nextCrumb);
        return (
            <TransitionMotion
                willEnter={() => getStyle(unmountedStyle, state, data, 1, true)}
                willLeave={() => getStyle(unmountedStyle, oldState, oldData, 1)}
                styles={sceneContexts.map(({state, data, url}) => {
                    var scene = this.state.scenes[url];
                    return {
                        key: url,
                        data: {scene, state, data, mount: url === nextCrumb.url},
                        style: getStyle((scene && scene.style) || mountedStyle, state, data, spring(0))
                    }
                })}>
                {tweenStyles => (

                        {tweenStyles.map((config) => this.renderScene(config))}

                )}
            </TransitionMotion>
        );
    }
}

function getStyle(styleProp, state, data, transitioning, strip) {
    var style = typeof styleProp === 'function' ? styleProp(state, data) : styleProp;
    var newStyle = {};
    for(var key in style) {
        newStyle[key] = (!strip || typeof style[key] === 'number') ? style[key] : style[key].val;
    }
    if (transitioning)
        newStyle.transitioning = transitioning;
    return newStyle;
}

NavigationMotion.contextTypes = {
    stateNavigator: React.PropTypes.object
}

export default NavigationMotion;
<|endoftext|>


<commit_before>'use strict';

import React from 'react-native'
import {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  TouchableHighlight,
  View,
} from 'react-native';
import { colors } from './globalStyle';

class HomeView extends Component {

  constructor(props: any) {
    super(props);
    this.state = {
      selectedButton: null,
      selectedButtonSize: 80,
    };
  }

  increaseButtonSize() {
    this.setState({
      selectedButtonSize: 100,
    });
  }

  navigateToBoopView() {
    this.props.navigator.push({
      name: 'boop-view',
    });
  }

  render() {
    const { data } = this.props;
    const self = this;
    const colors = [
      '#1f77b4',
      '#ff7f0e',
      '#2ca02c',
      '#d62728',
      '#9467bd',
      '#8c564b',
      '#e377c2',
      '#7f7f7f',
      '#bcbd22',
      '#17becf',
    ];
    const friendElems = data.friends.map(function(friend, index) {
      const color = colors[index % colors.length];
      const buttonSize = (
        self.state.selectedButton == friend.id ?
        self.state.selectedButtonSize :
        80
      );
      const circleButtonStyle = {
        width: buttonSize,
        height: buttonSize,
      };
      return (
        <View key={index} style={styles.friendElem}>
          <View style={styles.friendButton}>
          <TouchableHighlight
            style={styles.circleTouchable}
            onPress={() => {
              self.setState({
                selectedButton: friend.id,
              });
              self.increaseButtonSize();
              setTimeout(function() {
                self.navigateToBoopView();
              }, 1000);
            }}
            underlayColor='#CDCDCD'>
              <View style={[styles.circle, circleButtonStyle, {backgroundColor: color}]} />
            </TouchableHighlight>
            <Text
              style={styles.friendName}>
                {friend.firstName}
            </Text>
          </View>
        </View>
      );
    });
    return (
      <View style={styles.container}>
        {friendElems}
      </View>
    );
  }
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    flexWrap: 'wrap',
    justifyContent: 'space-around',
    padding: 20,
    backgroundColor: colors.darkTheme.primary,
  },
  friendElem: {
    height: 120,
    width: 100,
    margin: 4,
  },
  friendButton: {
    flex: 1,
    padding: 10,
    alignItems: 'center',
  },
  circle: {
    borderRadius: 100/2,
    backgroundColor: 'red'
  },
  circleTouchable: {
    borderRadius: 100/2,
  },
  friendName: {
    textAlign: 'center',
    fontSize: 16,
    color: colors.darkTheme.text1,
  },
});

AppRegistry.registerComponent('HomeView', () => HomeView);
export default HomeView;
<commit_msg>Handle multiple clicks with navigation delay.<commit_after>'use strict';

import React from 'react-native'
import {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  TouchableHighlight,
  View,
} from 'react-native';
import { colors } from './globalStyle';

class HomeView extends Component {

  constructor(props: any) {
    super(props);
    this.state = {
      selectedButton: null,
      selectedButtonSize: 80,
      navigateToBoopViewInProgress: false,
    };
  }

  increaseButtonSize() {
    this.setState({
      selectedButtonSize: 100,
    });
  }

  navigateToBoopView() {
    this.props.navigator.push({
      name: 'boop-view',
    });
  }

  navigateToBoopViewDelay() {
    if (this.state.navigateToBoopViewInProgress) {
      return;
    }
    this.setState({
      navigateToBoopViewInProgress: true,
    });
    const self = this;
    const t = setTimeout(function() {
      self.navigateToBoopView();
      self.setState({
        navigateToBoopViewInProgress: false,
      });
    }, 1000);
  }

  render() {
    const { data } = this.props;
    const self = this;
    const colors = [
      '#1f77b4',
      '#ff7f0e',
      '#2ca02c',
      '#d62728',
      '#9467bd',
      '#8c564b',
      '#e377c2',
      '#7f7f7f',
      '#bcbd22',
      '#17becf',
    ];
    const friendElems = data.friends.map(function(friend, index) {
      const color = colors[index % colors.length];
      const buttonSize = (
        self.state.selectedButton == friend.id ?
        self.state.selectedButtonSize :
        80
      );
      const circleButtonStyle = {
        width: buttonSize,
        height: buttonSize,
      };
      return (
        <View key={index} style={styles.friendElem}>
          <View style={styles.friendButton}>
          <TouchableHighlight
            style={styles.circleTouchable}
            onPress={() => {
              self.setState({
                selectedButton: friend.id,
              });
              self.increaseButtonSize();
              self.navigateToBoopViewDelay();
            }}
            underlayColor='#CDCDCD'>
              <View style={[styles.circle, circleButtonStyle, {backgroundColor: color}]} />
            </TouchableHighlight>
            <Text
              style={styles.friendName}>
                {friend.firstName}
            </Text>
          </View>
        </View>
      );
    });
    return (
      <View style={styles.container}>
        {friendElems}
      </View>
    );
  }
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    flexWrap: 'wrap',
    justifyContent: 'space-around',
    padding: 20,
    backgroundColor: colors.darkTheme.primary,
  },
  friendElem: {
    height: 120,
    width: 100,
    margin: 4,
  },
  friendButton: {
    flex: 1,
    padding: 10,
    alignItems: 'center',
  },
  circle: {
    borderRadius: 100/2,
    backgroundColor: 'red'
  },
  circleTouchable: {
    borderRadius: 100/2,
  },
  friendName: {
    textAlign: 'center',
    fontSize: 16,
    color: colors.darkTheme.text1,
  },
});

AppRegistry.registerComponent('HomeView', () => HomeView);
export default HomeView;
<|endoftext|>


<commit_before>/** Copyright 2015 Board of Trustees of University of Illinois
 * All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
var router = express.Router();
var fs = require('fs');
var client = require('./../../modules/redis');

var dashboardMustache = fs.readFileSync(mustachePath + 'dashboard.mustache').toString();

router.get('/dashboard', function (request, response) {
    if (request.isAuthenticated()) {
        response.writeHead(200, {
            'Content-Type': 'text/html'
        });

        var email = request.user.email;
        var user = email.substr(0, email.indexOf('@'));
        var html = Mustache.render(dashboardMustache, { user: user });

        response.end(html);
    } else {
        response.redirect('../');
    }
});

module.exports = router;<commit_msg>added documentation for dashboard<commit_after>/** Copyright 2015 Board of Trustees of University of Illinois
 * All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
var router = express.Router();
var fs = require('fs');
var client = require('./../../modules/redis');

// Get the mustache page that will be rendered for the dashboard route
var dashboardMustache = fs.readFileSync(mustachePath + 'dashboard.mustache').toString();

// Render the dashboard mustache page; if account is not authenticated, redirect to homepage
router.get('/dashboard', function (request, response) {
    if (request.isAuthenticated()) {
        response.writeHead(200, {
            'Content-Type': 'text/html'
        });

        // Obtain user information to display user data
        var email = request.user.email;
        var user = email.substr(0, email.indexOf('@'));
        var html = Mustache.render(dashboardMustache, { user: user });

        response.end(html);
    } else {
        response.redirect('../');
    }
});

module.exports = router;<|endoftext|>


<commit_before>/// <reference path="../App.js" />

(function () {
    "use strict";

        var _calOnly =
        "Only available on appointment or meeting request items.";

    // The Office initialize function must be run each time a new page is loaded
    Office.initialize = function (reason) {
        $(document).ready(function () {
            app.initialize();

            displayItemDetails();
            window.createAppointment = createAppointment;
        });
    };

    var _isCalendarItem = function() {
        if ( (_item.itemType ==
            Office.MailboxEnums.ItemType.Appointment) ||
             (_item.itemClass.indexOf("IPM.Schedule") != -1) )
        {
            return true;
        }

        return false;
    }

    // Displays the "Subject" and "From" fields, based on the current mail item
    function displayItemDetails() {
        var item = Office.cast.item.toItemRead(Office.context.mailbox.item);
        $('#subject').text(item.subject);

        var from;
        if (item.itemType === Office.MailboxEnums.ItemType.Message) {
            from = Office.cast.item.toMessageRead(item).from;
        } else if (item.itemType === Office.MailboxEnums.ItemType.Appointment) {
            from = Office.cast.item.toAppointmentRead(item).organizer;
        }

        if (from) {
            $('#from').text(from.displayName);
            $('#from').click(function () {
                app.showNotification(from.displayName, from.emailAddress);
            });
        }

        var _getDateString = function (date) {
            // var date = item.start;

            // Show how to extract the different components of
            // a date-time value.
            return ""+(date.getMonth()+1).toString()
                        +'/'+date.getDate().toString()
                        +'/'+date.getFullYear().toString();
        }
        var _getStart = function() {
            if (_isCalendarItem()) {

                // var date = item.start;

                // // Show how to extract the different components of
                // // a date-time value.
                // var info = ""+(date.getMonth()+1).toString()
                //             +'/'+date.getDate().toString()
                //             +'/'+date.getFullYear().toString();
                // // info += "Full Date : " + date.toString() + "
";
                // // info += "Full Year : " + date.getFullYear() + "
";
                // // // date.getMonth returns 0-based values, so increment by 1.
                // // info += "Month : " + (date.getMonth()+1) + "
";
                // // info += "Day of Month : " + date.getDate() + "
";
                // // info += "Day of Week : " + date.getDay() + "
";
                // // info += "Hours : " + date.getHours() + "
";
                // // info += "Minutes : " + date.getMinutes() + "
";
                // // info += "Seconds : " + date.getSeconds() + "
";

                $("td#start").html(_getDateString(item.start));
            } else  {
                $("td#start").text(_calOnly);
            }
        }

        var _getEnd = function() {
            if (_isCalendarItem()) {
                // var date = item.end;

                // // Show how to extract the different components of
                // // a date-time value.
                // var info = ""+(date.getMonth()+1).toString()
                //             +'/'+date.getDate().toString()
                //             +'/'+date.getFullYear().toString();
                // // info += "Full Date : " + date.toString() + "
";
                // // info += "Full Year : " + date.getFullYear() + "
";
                // // // date.getMonth returns 0-based values, so increment by 1.
                // // info += "Month : " + (date.getMonth()+1) + "
";
                // // info += "Day of Month : " + date.getDate() + "
";
                // // info += "Day of Week : " + date.getDay() + "
";
                // // info += "Hours : " + date.getHours() + "
";
                // // info += "Minutes : " + date.getMinutes() + "
";
                // // info += "Seconds : " + date.getSeconds() + "
";

                $("td#end").html(_getDateString(item.end));
            }
            else
            {
                $("td#end").text(_calOnly);
            }
        }

        _getStart();

        _getEnd();

    }

    function getAppointmentDateFromBody() {

    }

    function createAppointment() {
        var formParameters =
        {
            "requiredAttendees" : ["wendy@contoso.com", "derek@contoso.com"],
            "optionalAttendees" : ["shane@contoso.com", "michael@contoso.com"],
            "start" : new Date("September 27, 2012 11:15:00"),
            "end" : new Date("September 27, 2012 12:30:00"),
            "location" : "Conf room 200",
            "resources" : ['sound', 'lighting', 'recording'],
            "subject" : "Next rehearsal",
            "body" : "This is about the next rehearsal."
        }

        // Display a form to create an appointment with
        // the specified parameters.
        Office.context.mailbox.displayNewAppointmentForm(formParameters);
    }
})();<commit_msg>move item var<commit_after>/// <reference path="../App.js" />

(function () {
    "use strict";

        var _calOnly =
        "Only available on appointment or meeting request items.";

    // The Office initialize function must be run each time a new page is loaded
    Office.initialize = function (reason) {
        $(document).ready(function () {
            app.initialize();

            displayItemDetails();
            window.createAppointment = createAppointment;
        });
    };

    // Displays the "Subject" and "From" fields, based on the current mail item
    function displayItemDetails() {
        var item = Office.cast.item.toItemRead(Office.context.mailbox.item);
        $('#subject').text(item.subject);

        var from;
        if (item.itemType === Office.MailboxEnums.ItemType.Message) {
            from = Office.cast.item.toMessageRead(item).from;
        } else if (item.itemType === Office.MailboxEnums.ItemType.Appointment) {
            from = Office.cast.item.toAppointmentRead(item).organizer;
        }

        if (from) {
            $('#from').text(from.displayName);
            $('#from').click(function () {
                app.showNotification(from.displayName, from.emailAddress);
            });
        }

        var _isCalendarItem = function() {
            if ( (item.itemType ==
                Office.MailboxEnums.ItemType.Appointment) ||
                 (item.itemClass.indexOf("IPM.Schedule") != -1) )
            {
                return true;
            }

            return false;
        }

        var _getDateString = function (date) {
            // var date = item.start;

            // Show how to extract the different components of
            // a date-time value.
            return ""+(date.getMonth()+1).toString()
                        +'/'+date.getDate().toString()
                        +'/'+date.getFullYear().toString();
        }
        var _getStart = function() {
            if (_isCalendarItem()) {

                // var date = item.start;

                // // Show how to extract the different components of
                // // a date-time value.
                // var info = ""+(date.getMonth()+1).toString()
                //             +'/'+date.getDate().toString()
                //             +'/'+date.getFullYear().toString();
                // // info += "Full Date : " + date.toString() + "
";
                // // info += "Full Year : " + date.getFullYear() + "
";
                // // // date.getMonth returns 0-based values, so increment by 1.
                // // info += "Month : " + (date.getMonth()+1) + "
";
                // // info += "Day of Month : " + date.getDate() + "
";
                // // info += "Day of Week : " + date.getDay() + "
";
                // // info += "Hours : " + date.getHours() + "
";
                // // info += "Minutes : " + date.getMinutes() + "
";
                // // info += "Seconds : " + date.getSeconds() + "
";

                $("td#start").html(_getDateString(item.start));
            } else  {
                $("td#start").text(_calOnly);
            }
        }

        var _getEnd = function() {
            if (_isCalendarItem()) {
                // var date = item.end;

                // // Show how to extract the different components of
                // // a date-time value.
                // var info = ""+(date.getMonth()+1).toString()
                //             +'/'+date.getDate().toString()
                //             +'/'+date.getFullYear().toString();
                // // info += "Full Date : " + date.toString() + "
";
                // // info += "Full Year : " + date.getFullYear() + "
";
                // // // date.getMonth returns 0-based values, so increment by 1.
                // // info += "Month : " + (date.getMonth()+1) + "
";
                // // info += "Day of Month : " + date.getDate() + "
";
                // // info += "Day of Week : " + date.getDay() + "
";
                // // info += "Hours : " + date.getHours() + "
";
                // // info += "Minutes : " + date.getMinutes() + "
";
                // // info += "Seconds : " + date.getSeconds() + "
";

                $("td#end").html(_getDateString(item.end));
            }
            else
            {
                $("td#end").text(_calOnly);
            }
        }

        _getStart();

        _getEnd();

    }

    function getAppointmentDateFromBody() {

    }

    function createAppointment() {
        var formParameters =
        {
            "requiredAttendees" : ["wendy@contoso.com", "derek@contoso.com"],
            "optionalAttendees" : ["shane@contoso.com", "michael@contoso.com"],
            "start" : new Date("September 27, 2012 11:15:00"),
            "end" : new Date("September 27, 2012 12:30:00"),
            "location" : "Conf room 200",
            "resources" : ['sound', 'lighting', 'recording'],
            "subject" : "Next rehearsal",
            "body" : "This is about the next rehearsal."
        }

        // Display a form to create an appointment with
        // the specified parameters.
        Office.context.mailbox.displayNewAppointmentForm(formParameters);
    }
})();<|endoftext|>