<commit_before>import React from 'react';
import PropTypes from 'prop-types';

import * as events from '../util/events';
import { getProp, isControlledProp } from '../util/props';
import { withParentContext } from '../Context';
import withYMaps from '../withYMaps';
import applyRef from '../util/ref';

export class ObjectManager extends React.Component {
  constructor() {
    super();
    this.state = { instance: null };
  }

  componentDidMount() {
    const instance = ObjectManager.mountObject(
      this.props.ymaps.ObjectManager,
      this.props
    );

    this.setState({ instance });
  }

  componentDidUpdate(prevProps) {
    if (this.state.instance !== null) {
      ObjectManager.updateObject(this.state.instance, prevProps, this.props);
    }
  }

  componentWillUnmount() {
    ObjectManager.unmountObject(this.state.instance, this.props);
  }

  render() {
    return null;
  }

  static mountObject(ObjectManager, props) {
    const { instanceRef, parent, _events } = events.separateEvents(props);

    const options = getProp(props, 'options');
    const features = getProp(props, 'features');
    const filter = getProp(props, 'filter');
    const objects = getProp(props, 'objects');
    const clusters = getProp(props, 'clusters');

    const instance = new ObjectManager(options);

    instance.add(features || []);

    instance.setFilter(filter);

    instance.objects.options.set(objects);
    instance.clusters.options.set(clusters);

    Object.keys(_events).forEach(key =>
      events.addEvent(instance, key, _events[key])
    );

    if (parent.geoObjects && typeof parent.geoObjects.add === 'function') {
      parent.geoObjects.add(instance);
    } else if (parent.add && typeof parent.add === 'function') {
      parent.add(instance);
    } else {
      throw new Error('No parent found to mount ObjectManager');
    }

    applyRef(null, instanceRef, instance);

    return instance;
  }

  static updateObject(instance, oldProps, newProps) {
    const { _events: newEvents, instanceRef } = events.separateEvents(newProps);
    const { _events: oldEvents, instanceRef: oldRef } = events.separateEvents(
      oldProps
    );

    if (isControlledProp(newProps, 'options')) {
      const oldOptions = getProp(oldProps, 'options');
      const newOptions = getProp(newProps, 'options');

      if (oldOptions !== newOptions) {
        instance.options.set(newOptions);
      }
    }

    if (isControlledProp(newProps, 'objects')) {
      const oldObjectsOptions = getProp(oldProps, 'objects');
      const newObjectsOptions = getProp(newProps, 'objects');

      if (oldObjectsOptions !== newObjectsOptions) {
        instance.objects.options.set(newObjectsOptions);
      }
    }

    if (isControlledProp(newProps, 'clusters')) {
      const oldClustersOptions = getProp(oldProps, 'clusters');
      const newClustersOptions = getProp(newProps, 'clusters');

      if (oldClustersOptions !== newClustersOptions) {
        instance.clusters.options.set(newClustersOptions);
      }
    }

    if (isControlledProp(newProps, 'filter')) {
      const oldFilter = getProp(oldProps, 'filter');
      const newFilter = getProp(newProps, 'filter');

      if (oldFilter !== newFilter) {
        instance.options.set(newFilter);
      }
    }

    if (isControlledProp(newProps, 'features')) {
      const oldFeatures = getProp(oldProps, 'features');
      const newFeatures = getProp(newProps, 'features');

      if (oldFeatures !== newFeatures) {
        instance.remove(oldFeatures);
        instance.add(newFeatures);
      }
    }

    events.updateEvents(instance, oldEvents, newEvents);

    applyRef(oldRef, instanceRef, instance);
  }

  static unmountObject(instance, props) {
    const { instanceRef, parent, _events } = events.separateEvents(props);

    if (instance !== null) {
      Object.keys(_events).forEach(key =>
        events.removeEvent(instance, key, _events[key])
      );

      if (parent.geoObjects && typeof parent.geoObjects.remove === 'function') {
        parent.geoObjects.remove(instance);
      } else if (parent.remove && typeof parent.remove === 'function') {
        parent.remove(instance);
      }

      applyRef(instanceRef);
    }
  }
}

if (process.env.NODE_ENV !== 'production') {
  const TYPE_FEATURE = 'Feature';

  const TYPE_FEATURE_COLLECTION = 'FeatureCollection';

  // https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#add-param-objects
  const FeaturePropType = PropTypes.shape({
    id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
    type: PropTypes.oneOf([TYPE_FEATURE]).isRequired,
    geometry: PropTypes.object.isRequired,
    options: PropTypes.object,
    properties: PropTypes.object,
  });

  // INFO: A hack to make recursive prop-type check work properly
  const FeatureCollection = {
    type: PropTypes.oneOf([TYPE_FEATURE_COLLECTION]).isRequired,
  };

  FeatureCollection.features = PropTypes.arrayOf(
    PropTypes.oneOfType([PropTypes.shape(FeatureCollection), FeaturePropType])
  ).isRequired;

  const FeatureCollectionPropType = PropTypes.shape(FeatureCollection);

  const FeaturesPropType = PropTypes.oneOfType([
    PropTypes.arrayOf(
      PropTypes.oneOfType([FeatureCollectionPropType, FeaturePropType])
    ),
    FeatureCollectionPropType,
  ]);

  const FilterPropType = PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.func,
  ]);

  // TODO
  const ObjectManagerOptionsPropType = PropTypes.shape({});

  // TODO
  const ObjectManagerObjectsOptionsPropType = PropTypes.shape({});

  // TODO
  const ObjectManagerClustersOptionsPropType = PropTypes.shape({});

  ObjectManager.propTypes = {
    /**
     * ObjectManager [features](https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#method_detail__add-param-objects)
     */
    features: FeaturesPropType,
    /**
     * Uncontrolled ObjectManager [features](https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#method_detail__add-param-objects)
     */
    defaultFeatures: FeaturesPropType,

    /**
     * ObjectManager [features filter](https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#method_detail__setFilter-param-filterFunction)
     */
    filter: FilterPropType,
    /**
     * Uncontrolled ObjectManager [features filter](https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#method_detail__setFilter-param-filterFunction)
     */
    defaultFilter: FilterPropType,

    /**
     * ObjectManager [options](https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#ObjectManager__param-options)
     */
    options: ObjectManagerOptionsPropType,
    /**
     * Uncontrolled ObjectManager [options](https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#ObjectManager__param-options)
     */
    defaultOptions: ObjectManagerOptionsPropType,

    /** ObjectManager object options */
    objects: ObjectManagerObjectsOptionsPropType,
    defaultObjects: ObjectManagerObjectsOptionsPropType,

    /** ObjectManager clusters options */
    clusters: ObjectManagerClustersOptionsPropType,
    defaultClusters: ObjectManagerClustersOptionsPropType,

    /** ref prop but for Yandex.Maps object instances */
    instanceRef: PropTypes.func,

    /**
     * @ignore
     * Yandex.Maps API object
     */
    ymaps: PropTypes.object,

    /**
     * @ignore
     * Parent object (e.g, ymaps.Map or ymaps.Clusterer)
     */
    parent: PropTypes.object,
  };
}

export default withParentContext(
  withYMaps(ObjectManager, true, ['ObjectManager'])
);
<commit_msg>fixed ObjectManager filter changing<commit_after>import React from 'react';
import PropTypes from 'prop-types';

import * as events from '../util/events';
import { getProp, isControlledProp } from '../util/props';
import { withParentContext } from '../Context';
import withYMaps from '../withYMaps';
import applyRef from '../util/ref';

export class ObjectManager extends React.Component {
  constructor() {
    super();
    this.state = { instance: null };
  }

  componentDidMount() {
    const instance = ObjectManager.mountObject(
      this.props.ymaps.ObjectManager,
      this.props
    );

    this.setState({ instance });
  }

  componentDidUpdate(prevProps) {
    if (this.state.instance !== null) {
      ObjectManager.updateObject(this.state.instance, prevProps, this.props);
    }
  }

  componentWillUnmount() {
    ObjectManager.unmountObject(this.state.instance, this.props);
  }

  render() {
    return null;
  }

  static mountObject(ObjectManager, props) {
    const { instanceRef, parent, _events } = events.separateEvents(props);

    const options = getProp(props, 'options');
    const features = getProp(props, 'features');
    const filter = getProp(props, 'filter');
    const objects = getProp(props, 'objects');
    const clusters = getProp(props, 'clusters');

    const instance = new ObjectManager(options);

    instance.add(features || []);

    instance.setFilter(filter);

    instance.objects.options.set(objects);
    instance.clusters.options.set(clusters);

    Object.keys(_events).forEach(key =>
      events.addEvent(instance, key, _events[key])
    );

    if (parent.geoObjects && typeof parent.geoObjects.add === 'function') {
      parent.geoObjects.add(instance);
    } else if (parent.add && typeof parent.add === 'function') {
      parent.add(instance);
    } else {
      throw new Error('No parent found to mount ObjectManager');
    }

    applyRef(null, instanceRef, instance);

    return instance;
  }

  static updateObject(instance, oldProps, newProps) {
    const { _events: newEvents, instanceRef } = events.separateEvents(newProps);
    const { _events: oldEvents, instanceRef: oldRef } = events.separateEvents(
      oldProps
    );

    if (isControlledProp(newProps, 'options')) {
      const oldOptions = getProp(oldProps, 'options');
      const newOptions = getProp(newProps, 'options');

      if (oldOptions !== newOptions) {
        instance.options.set(newOptions);
      }
    }

    if (isControlledProp(newProps, 'objects')) {
      const oldObjectsOptions = getProp(oldProps, 'objects');
      const newObjectsOptions = getProp(newProps, 'objects');

      if (oldObjectsOptions !== newObjectsOptions) {
        instance.objects.options.set(newObjectsOptions);
      }
    }

    if (isControlledProp(newProps, 'clusters')) {
      const oldClustersOptions = getProp(oldProps, 'clusters');
      const newClustersOptions = getProp(newProps, 'clusters');

      if (oldClustersOptions !== newClustersOptions) {
        instance.clusters.options.set(newClustersOptions);
      }
    }

    if (isControlledProp(newProps, 'filter')) {
      const oldFilter = getProp(oldProps, 'filter');
      const newFilter = getProp(newProps, 'filter');

      if (oldFilter !== newFilter) {
        instance.setFilter(newFilter);
      }
    }

    if (isControlledProp(newProps, 'features')) {
      const oldFeatures = getProp(oldProps, 'features');
      const newFeatures = getProp(newProps, 'features');

      if (oldFeatures !== newFeatures) {
        instance.remove(oldFeatures);
        instance.add(newFeatures);
      }
    }

    events.updateEvents(instance, oldEvents, newEvents);

    applyRef(oldRef, instanceRef, instance);
  }

  static unmountObject(instance, props) {
    const { instanceRef, parent, _events } = events.separateEvents(props);

    if (instance !== null) {
      Object.keys(_events).forEach(key =>
        events.removeEvent(instance, key, _events[key])
      );

      if (parent.geoObjects && typeof parent.geoObjects.remove === 'function') {
        parent.geoObjects.remove(instance);
      } else if (parent.remove && typeof parent.remove === 'function') {
        parent.remove(instance);
      }

      applyRef(instanceRef);
    }
  }
}

if (process.env.NODE_ENV !== 'production') {
  const TYPE_FEATURE = 'Feature';

  const TYPE_FEATURE_COLLECTION = 'FeatureCollection';

  // https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#add-param-objects
  const FeaturePropType = PropTypes.shape({
    id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
    type: PropTypes.oneOf([TYPE_FEATURE]).isRequired,
    geometry: PropTypes.object.isRequired,
    options: PropTypes.object,
    properties: PropTypes.object,
  });

  // INFO: A hack to make recursive prop-type check work properly
  const FeatureCollection = {
    type: PropTypes.oneOf([TYPE_FEATURE_COLLECTION]).isRequired,
  };

  FeatureCollection.features = PropTypes.arrayOf(
    PropTypes.oneOfType([PropTypes.shape(FeatureCollection), FeaturePropType])
  ).isRequired;

  const FeatureCollectionPropType = PropTypes.shape(FeatureCollection);

  const FeaturesPropType = PropTypes.oneOfType([
    PropTypes.arrayOf(
      PropTypes.oneOfType([FeatureCollectionPropType, FeaturePropType])
    ),
    FeatureCollectionPropType,
  ]);

  const FilterPropType = PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.func,
  ]);

  // TODO
  const ObjectManagerOptionsPropType = PropTypes.shape({});

  // TODO
  const ObjectManagerObjectsOptionsPropType = PropTypes.shape({});

  // TODO
  const ObjectManagerClustersOptionsPropType = PropTypes.shape({});

  ObjectManager.propTypes = {
    /**
     * ObjectManager [features](https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#method_detail__add-param-objects)
     */
    features: FeaturesPropType,
    /**
     * Uncontrolled ObjectManager [features](https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#method_detail__add-param-objects)
     */
    defaultFeatures: FeaturesPropType,

    /**
     * ObjectManager [features filter](https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#method_detail__setFilter-param-filterFunction)
     */
    filter: FilterPropType,
    /**
     * Uncontrolled ObjectManager [features filter](https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#method_detail__setFilter-param-filterFunction)
     */
    defaultFilter: FilterPropType,

    /**
     * ObjectManager [options](https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#ObjectManager__param-options)
     */
    options: ObjectManagerOptionsPropType,
    /**
     * Uncontrolled ObjectManager [options](https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/ObjectManager-docpage/#ObjectManager__param-options)
     */
    defaultOptions: ObjectManagerOptionsPropType,

    /** ObjectManager object options */
    objects: ObjectManagerObjectsOptionsPropType,
    defaultObjects: ObjectManagerObjectsOptionsPropType,

    /** ObjectManager clusters options */
    clusters: ObjectManagerClustersOptionsPropType,
    defaultClusters: ObjectManagerClustersOptionsPropType,

    /** ref prop but for Yandex.Maps object instances */
    instanceRef: PropTypes.func,

    /**
     * @ignore
     * Yandex.Maps API object
     */
    ymaps: PropTypes.object,

    /**
     * @ignore
     * Parent object (e.g, ymaps.Map or ymaps.Clusterer)
     */
    parent: PropTypes.object,
  };
}

export default withParentContext(
  withYMaps(ObjectManager, true, ['ObjectManager'])
);
<|endoftext|>


<commit_before>// Components are the smallest unit of event handling and logic
// Components may contain sub-components, but (as of may 12th 2012),
// they are responsible for calling render on those elements
Mast.Component =
{
	// Default HTML to display if table is empty and no emptytemplateis specified
	emptyHTML: "This collection is empty.",

	// HTML to display if nothing can be loaded from the server
	errorHTML: "The specified URL did not return valid data.",

	// Automatic rendering is enabled by default
	autoRender: true,

	// Custom event bindings for specific model attributes
	bindings: {},

	subcomponents: {},
	children: {},

	/**
         * attributes: properties to be added directly to the component
         *              i.e. accessible from component as:
         *                  this.someThing
         *                  this.someThingElse
         *
         * modelAttributes: properties to be added directly to the component's Model
         *              i.e. accessible from component as:
         *                  this.get('someThing')
         *                  this.get('someThingElse')
         *
         * dontRender: whether or not to render this component when it is instantiated
         *              default: false
         */
	initialize: function(attributes,modelAttributes,dontRender){
		// Bind context
		_.bindAll(this);

		// Bring in attributes
		_.extend(this,attributes);

		// Backwards compatibility for autorender / autoRender
		this.autoRender = (this.autorender!==undefined) ? this.autorender : this.autoRender;

		// Parse special notation in events hash
		_.each(this.events,function(handler,name) {
			var splitName = name.split(/\s+/g);
			if (splitName.length > 1 && splitName[1].substr(0,1) == '>') {
				// This is a closest_descendant event so generate new name of event
				var newName = name.replace(/(\S+\s+)>/g, "$1");					// i.e. "click >.button"
				delete this.events[name];
				var newHandler = function (e) {
					// Stop event from propagating up to parent components
					e.stopImmediatePropagation();
					_.isString(handler) ? this[handler](e) : _.bind(handler,this)(e);
					return false;
				}
				_.bind(newHandler,this);
				this.events[newName] = newHandler;
			}
		},this);

		// Build pattern
		if (!this.pattern) {
			if (!this.template) {
				throw new Error ("No pattern or template selector specified for component!");
			}
			else {
				// Create pattern from model and template
				this.pattern = new Mast.Pattern({
					template: this.template,
					model: this.model ? this.model : new Mast.Model
				});

				// Provide direct access to model from component
				this._modelIdentifier = this.model;
				this.model = this.pattern.model;
			}
		}
		else {
			if (this.template || this.model) {
				debug.warn ('A template selector and/or model was specified '+
					' even though a pattern was also specified!! \n'+
					'Ignoring extra attributes and using the specified pattern...');
			}
		}

		// If this belongs to another component, disable autoRender
		if (this.parent) {
			this.autoRender = false;
		}

		// Maintain dictionary of subcomponents
		this.children = {};

		// Extend model with properties specified
		_.each(modelAttributes,function(val,key){
			this.pattern.set(key,val);
		},this);

		// Watch for changes to pattern
		this.pattern.on('change',this.render);

		// Trigger init event
		_.result(this,'init');

		// Watch for and announce events
		this.on('afterRender',this.afterRender);
		this.on('beforeRender',this.beforeRender);
		this.on('beforeDestroy',this.beforeDestroy);
		this.on('afterDestroy',this.afterDestroy);

		// Autorender is on by default
		if (!dontRender && this.autoRender!==false) {
			this.append();
		}

		// Listen for when the socket is live
		// (unless it's already live)
		if (Mast.Socket) {
//			if (!Mast.Socket.connected) {
//				Mast.Socket.off('connect', this.afterConnect);
//				Mast.Socket.on('connect', this.afterConnect);
//			}
//			else {
//				Mast.Socket.off('connect', this.afterConnect);
//				this.afterConnect();
//			}

			Mast.Socket.on('sessionUpdated',this.afterConnect);
		}

		// Bind actions to comet events
		if (this.subscriptions) {
			_.each(this.subscriptions,function(action,route) {					// Use Backbone's Router logic to parse parameters (/variable/parsing/:within/:path)
				Mast.Socket.subscribe(route,_.isFunction(action) ? action: this[action],this);
			},this)
		}
	},

	// Append the pattern to the outlet
	append: function (outlet) {
		var $outlet = this._verifyOutlet(outlet,
			this.parent && this.parent.$el);

		// Render without firing the afterRender event
		this.render(true);
		$outlet.append && $outlet.append(this.$el);
		// Then trigger afterRender after appending the element to the DOM
		this.trigger('afterRender');

		return this;
	},

	// Replace the outlet with the rendered pattern
	replace: function (outlet) {
		var $outlet = this._verifyOutlet(outlet);

		this.setElement($outlet);
		this.render();
		return this;
	},

	// Render the pattern and subcomponents
	render: function (silent,changes) {
		!silent && this.trigger('beforeRender');

		// Determine if all changed attributes are bound
		var allBound = _.all(changes,function(attrVal,attrName) {
			return !_.isUndefined(this.bindings[attrName]);
		},this);

		// if not all attribute changes are bound, or there are no explicit changes, naively rerender
		if (!allBound || !changes ) {
			this.naiveRender(true,changes);
		}
		// Otherwise, perform the specific bindings for this changeset
		else {
			this.renderBindings(changes);
		}

		!silent && this.trigger('afterRender',changes);
		return this;
	},

	// Render the binding functions as they apply to the specified changeset
	// or if no changeset is specified, render all bindings
	renderBindings: function (changes) {
		var bindingsToPerform = _.keys(changes || this.bindings);
		_.each(bindingsToPerform,function(attrName) {
			var handler = this.bindings[attrName];
			handler = _.isString(handler) ? this[handler] : handler;
			if (handler) {
				if (!_.isFunction(handler)) throw new Error ("Bindings contain invalid or non-existent function.");
				handler = _.bind(handler,this);
				handler(this.get(attrName));
			}
		},this);
	},

	// Rip existing element out of DOM, replace with new element, then render subcomponents
	naiveRender: function (silent) {
		var $element = this.generate();
		this.$el.replaceWith($element);
		this.setElement($element);
		this.renderSubcomponents(silent);
	},

	// Render the subcomponents for this component
	renderSubcomponents: function (silent,changes) {
		!silent && this.trigger('beforeRender');
		_.each(this.subcomponents,this.renderSubcomponent,this);
		!silent && this.trigger('afterRender',changes);
	},

	// Render a particular subcomponent
	renderSubcomponent: function(subcomponent,outletSelector) {
		// destroy existing component
		this.children[outletSelector] && this.children[outletSelector].destroy();

		// Create and save new component
//		var subcomponentPrototype = Mast.mixins.provisionPrototype(subcomponent,Mast.components,Mast.Component);
		this.children[outletSelector] = new Mast.components[subcomponent]({
			outlet: outletSelector,
			parent: this
		})

		// append new component to DOM
		this.children[outletSelector].append();
	},

	// Attach a new subcomponent to an outlet in this component
	attach: function(outletSelector, subcomponent){
		this.subcomponents[outletSelector] = subcomponent;
		this.renderSubcomponent(subcomponent,outletSelector);
	},

	// Detach all subcomponents from an outlet
	detach: function(outletSelector){
		if (this.children[outletSelector]) {
			this.children.destroy();
			delete this.subcomponents[outletSelector];
		}
	},

	// Use pattern to generate a DOM element
	generate: function (data) {
		data = this._normalizeData(data);
		return $(this.pattern.generate(data));
	},

	// Free the memory for this component and remove it from the DOM
	destroy: function (silent) {
		!silent && this.trigger('beforeDestroy');

		// Destroy all subcomponents
		_.invoke(this.children,'destroy');

		// Unsubscribe to model change events
		this.pattern.off();
		this.off();

		// Remove from DOM
		this.$el.remove();

		// TODO: Unsubscribe to comet updates

		!silent && this.trigger('afterDestroy');
	},

	// Set pattern's template selector
	setTemplate: function (selector,options){
		options = _.defaults(options || {}, {
			render: true
		});

		// If a render function is specified, use that
		if (_.isFunction(options.render)) {
			// call custom render function with current and new elements (in the proper scope)
			_.bind(options.render,this);
			options.render(this.$el,this.generate());
		}
		// Otherwise just do a basic render by triggering the default behavior
		else {
			this.pattern.setTemplate(selector,options);
		}
		return this.$el;
	},

	// Handle both `"key", value` and `{key: value}` -style arguments.
	_normalizeArgs: function(key,value,options,transformedFn) {
		var attrs;
		if (_.isObject(key) || key == null) {
			attrs = key;
			options = value;
		} else {
			attrs = {};
			attrs[key] = value;
		}
		transformedFn(attrs,options);
	},

	// Change model as a result of set, increment, or decrement
	_changeModel: function (attrs,options) {
		options = _.defaults(options || {}, {
			render: true
		});

		// If a render function is specified, use that
		if (_.isFunction(options.render)) {
			// call custom render function with current and new elements (in the proper scope)
			this.pattern.set(attrs,_.extend(options,{
				silent:true
			}));
			options.render =_.bind(options.render,this);
			options.render(this.$el,this.generate());
			// Fire afterRender unless silent:true was set in options
			!options.silent && this.trigger('afterRender',attrs);
		}
		// Otherwise just do a basic render by triggering the default behavior
		else {
			this.pattern.set(attrs,options);
		}
	},

	// Set pattern's model attribute
	// If the first argument is an object, value can also be an options hash
	set: function (key,value,options){
		var self = this;
		self._normalizeArgs(key, value, options, function(attrs,options) {
			self._changeModel(attrs,options);
		});
	},

	increment: function(key,amount,options) {
		var self = this;
		self._normalizeArgs(key, amount, options, function(attrs,options) {
			attrs = _.objMap(attrs,function(amt,key) {
				return self.get(key)+amt;
			});
			self._changeModel(attrs,options);
		});
	},
	decrement: function(key,amount,options) {
		var self = this;
		self._normalizeArgs(key, amount, options, function(attrs,options) {
			attrs = _.objMap(attrs,function(amt,key) {
				return self.get(key)-amt;
			});
			self._changeModel(attrs,options);
		});
	},

	save: function () {
		this.pattern.model.save(null,{
			silent:true
		});
	},

	get: function(attribute) {
		return this.pattern.get(attribute);
	},

	beforeRender: function(){
	// stub
	},

	afterRender: function(){
	// stub
	},

	beforeDestroy: function(){
	// stub
	},

	afterDestroy: function(){
	// stub
	},

	afterConnect: function(){
	// stub
	},

	// Determine the proper outlet selector and ensure that it is valid
	_verifyOutlet: function (outlet,context) {

		// If a parent component exists, render into that by default
		outlet = outlet || this.outlet || (this.parent && this.parent.$el);

		if (!outlet && !this.parent) {
			throw new Error("No outlet selector specified to render into!");
			return false;
		}

		var $outlet;
		if (_.isString(outlet)) {
			$outlet = (context && context.closest_descendant(outlet)) || $(outlet);
		}
		else {
			$outlet = outlet;
		}

		if ($outlet.length != 1) {

			//			debug.debug($outlet,outlet,this.parent.$el);
			debug.warn(
				(($outlet.length > 1)?"More than one ":"No ")+
				(($outlet.length > 1)?"element exists ":"elements exist ")+
				(context?"in this template context ("+context+ ")":"") +
				"for the specified "+
				(context?"child ":"") +
				"outlet selector! ('"+outlet+"')");
			return false;
		}
		return $outlet;
	},

	// Used for debugging
	_test: function() {
		debug.debug("TEST FUNCTION FIRED!",arguments,this);
	}
}<commit_msg>Solved potential race condition in afterConnect.<commit_after>// Components are the smallest unit of event handling and logic
// Components may contain sub-components, but (as of may 12th 2012),
// they are responsible for calling render on those elements
Mast.Component =
{
	// Default HTML to display if table is empty and no emptytemplateis specified
	emptyHTML: "This collection is empty.",

	// HTML to display if nothing can be loaded from the server
	errorHTML: "The specified URL did not return valid data.",

	// Automatic rendering is enabled by default
	autoRender: true,

	// Custom event bindings for specific model attributes
	bindings: {},

	subcomponents: {},
	children: {},

	/**
         * attributes: properties to be added directly to the component
         *              i.e. accessible from component as:
         *                  this.someThing
         *                  this.someThingElse
         *
         * modelAttributes: properties to be added directly to the component's Model
         *              i.e. accessible from component as:
         *                  this.get('someThing')
         *                  this.get('someThingElse')
         *
         * dontRender: whether or not to render this component when it is instantiated
         *              default: false
         */
	initialize: function(attributes,modelAttributes,dontRender){
		// Bind context
		_.bindAll(this);

		// Bring in attributes
		_.extend(this,attributes);

		// Backwards compatibility for autorender / autoRender
		this.autoRender = (this.autorender!==undefined) ? this.autorender : this.autoRender;

		// Parse special notation in events hash
		_.each(this.events,function(handler,name) {
			var splitName = name.split(/\s+/g);
			if (splitName.length > 1 && splitName[1].substr(0,1) == '>') {
				// This is a closest_descendant event so generate new name of event
				var newName = name.replace(/(\S+\s+)>/g, "$1");					// i.e. "click >.button"
				delete this.events[name];
				var newHandler = function (e) {
					// Stop event from propagating up to parent components
					e.stopImmediatePropagation();
					_.isString(handler) ? this[handler](e) : _.bind(handler,this)(e);
					return false;
				}
				_.bind(newHandler,this);
				this.events[newName] = newHandler;
			}
		},this);

		// Build pattern
		if (!this.pattern) {
			if (!this.template) {
				throw new Error ("No pattern or template selector specified for component!");
			}
			else {
				// Create pattern from model and template
				this.pattern = new Mast.Pattern({
					template: this.template,
					model: this.model ? this.model : new Mast.Model
				});

				// Provide direct access to model from component
				this._modelIdentifier = this.model;
				this.model = this.pattern.model;
			}
		}
		else {
			if (this.template || this.model) {
				debug.warn ('A template selector and/or model was specified '+
					' even though a pattern was also specified!! \n'+
					'Ignoring extra attributes and using the specified pattern...');
			}
		}

		// If this belongs to another component, disable autoRender
		if (this.parent) {
			this.autoRender = false;
		}

		// Maintain dictionary of subcomponents
		this.children = {};

		// Extend model with properties specified
		_.each(modelAttributes,function(val,key){
			this.pattern.set(key,val);
		},this);

		// Watch for changes to pattern
		this.pattern.on('change',this.render);

		// Trigger init event
		_.result(this,'init');

		// Watch for and announce events
		this.on('afterRender',this.afterRender);
		this.on('beforeRender',this.beforeRender);
		this.on('beforeDestroy',this.beforeDestroy);
		this.on('afterDestroy',this.afterDestroy);

		// Autorender is on by default
		if (!dontRender && this.autoRender!==false) {
			this.append();
		}

		// Listen for when the socket is live
		// (unless it's already live)
		if (Mast.Socket) {
			if (!Mast.Socket.connected) {
				Mast.Socket.off('sessionUpdated', this.afterConnect);
				Mast.Socket.on('sessionUpdated',this.afterConnect);
			}
			else {
				this.afterConnect();
			}
		}

		// Bind actions to comet events
		if (this.subscriptions) {
			// Use Backbone's Router logic to parse parameters (/variable/parsing/:within/:path)
			_.each(this.subscriptions,function(action,route) {
				Mast.Socket.subscribe(route,_.isFunction(action) ? action: this[action],this);
			},this)
		}
	},

	// Append the pattern to the outlet
	append: function (outlet) {
		var $outlet = this._verifyOutlet(outlet,
			this.parent && this.parent.$el);

		// Render without firing the afterRender event
		this.render(true);
		$outlet.append && $outlet.append(this.$el);
		// Then trigger afterRender after appending the element to the DOM
		this.trigger('afterRender');

		return this;
	},

	// Replace the outlet with the rendered pattern
	replace: function (outlet) {
		var $outlet = this._verifyOutlet(outlet);

		this.setElement($outlet);
		this.render();
		return this;
	},

	// Render the pattern and subcomponents
	render: function (silent,changes) {
		!silent && this.trigger('beforeRender');

		// Determine if all changed attributes are bound
		var allBound = _.all(changes,function(attrVal,attrName) {
			return !_.isUndefined(this.bindings[attrName]);
		},this);

		// if not all attribute changes are bound, or there are no explicit changes, naively rerender
		if (!allBound || !changes ) {
			this.naiveRender(true,changes);
		}
		// Otherwise, perform the specific bindings for this changeset
		else {
			this.renderBindings(changes);
		}

		!silent && this.trigger('afterRender',changes);
		return this;
	},

	// Render the binding functions as they apply to the specified changeset
	// or if no changeset is specified, render all bindings
	renderBindings: function (changes) {
		var bindingsToPerform = _.keys(changes || this.bindings);
		_.each(bindingsToPerform,function(attrName) {
			var handler = this.bindings[attrName];
			handler = _.isString(handler) ? this[handler] : handler;
			if (handler) {
				if (!_.isFunction(handler)) throw new Error ("Bindings contain invalid or non-existent function.");
				handler = _.bind(handler,this);
				handler(this.get(attrName));
			}
		},this);
	},

	// Rip existing element out of DOM, replace with new element, then render subcomponents
	naiveRender: function (silent) {
		var $element = this.generate();
		this.$el.replaceWith($element);
		this.setElement($element);
		this.renderSubcomponents(silent);
	},

	// Render the subcomponents for this component
	renderSubcomponents: function (silent,changes) {
		!silent && this.trigger('beforeRender');
		_.each(this.subcomponents,this.renderSubcomponent,this);
		!silent && this.trigger('afterRender',changes);
	},

	// Render a particular subcomponent
	renderSubcomponent: function(subcomponent,outletSelector) {
		// destroy existing component
		this.children[outletSelector] && this.children[outletSelector].destroy();

		// Create and save new component
//		var subcomponentPrototype = Mast.mixins.provisionPrototype(subcomponent,Mast.components,Mast.Component);
		this.children[outletSelector] = new Mast.components[subcomponent]({
			outlet: outletSelector,
			parent: this
		})

		// append new component to DOM
		this.children[outletSelector].append();
	},

	// Attach a new subcomponent to an outlet in this component
	attach: function(outletSelector, subcomponent){
		this.subcomponents[outletSelector] = subcomponent;
		this.renderSubcomponent(subcomponent,outletSelector);
	},

	// Detach all subcomponents from an outlet
	detach: function(outletSelector){
		if (this.children[outletSelector]) {
			this.children.destroy();
			delete this.subcomponents[outletSelector];
		}
	},

	// Use pattern to generate a DOM element
	generate: function (data) {
		data = this._normalizeData(data);
		return $(this.pattern.generate(data));
	},

	// Free the memory for this component and remove it from the DOM
	destroy: function (silent) {
		!silent && this.trigger('beforeDestroy');

		// Destroy all subcomponents
		_.invoke(this.children,'destroy');

		// Unsubscribe to model change events
		this.pattern.off();
		this.off();

		// Remove from DOM
		this.$el.remove();

		// TODO: Unsubscribe to comet updates

		!silent && this.trigger('afterDestroy');
	},

	// Set pattern's template selector
	setTemplate: function (selector,options){
		options = _.defaults(options || {}, {
			render: true
		});

		// If a render function is specified, use that
		if (_.isFunction(options.render)) {
			// call custom render function with current and new elements (in the proper scope)
			_.bind(options.render,this);
			options.render(this.$el,this.generate());
		}
		// Otherwise just do a basic render by triggering the default behavior
		else {
			this.pattern.setTemplate(selector,options);
		}
		return this.$el;
	},

	// Handle both `"key", value` and `{key: value}` -style arguments.
	_normalizeArgs: function(key,value,options,transformedFn) {
		var attrs;
		if (_.isObject(key) || key == null) {
			attrs = key;
			options = value;
		} else {
			attrs = {};
			attrs[key] = value;
		}
		transformedFn(attrs,options);
	},

	// Change model as a result of set
	_changeModel: function (attrs,options) {
		options = _.defaults(options || {}, {
			render: true
		});

		// If a render function is specified, use that
		if (_.isFunction(options.render)) {
			// call custom render function with current and new elements (in the proper scope)
			this.pattern.set(attrs,_.extend(options,{
				silent:true
			}));
			options.render =_.bind(options.render,this);
			options.render(this.$el,this.generate());
			// Fire afterRender unless silent:true was set in options
			!options.silent && this.trigger('afterRender',attrs);
		}
		// Otherwise just do a basic render by triggering the default behavior
		else {
			this.pattern.set(attrs,options);
		}
	},

	// Set pattern's model attribute
	// If the first argument is an object, value can also be an options hash
	set: function (key,value,options){
		var self = this;
		self._normalizeArgs(key, value, options, function(attrs,options) {
			self._changeModel(attrs,options);
		});
	},

	increment: function(key,amount,options) {
		var self = this;
		self._normalizeArgs(key, amount, options, function(attrs,options) {
			attrs = _.objMap(attrs,function(amt,key) {
				return self.get(key)+amt;
			});
			self._changeModel(attrs,options);
		});
	},
	decrement: function(key,amount,options) {
		var self = this;
		self._normalizeArgs(key, amount, options, function(attrs,options) {
			attrs = _.objMap(attrs,function(amt,key) {
				return self.get(key)-amt;
			});
			self._changeModel(attrs,options);
		});
	},

	save: function () {
		this.pattern.model.save(null,{
			silent:true
		});
	},

	get: function(attribute) {
		return this.pattern.get(attribute);
	},

	beforeRender: function(){
	// stub
	},

	afterRender: function(){
	// stub
	},

	beforeDestroy: function(){
	// stub
	},

	afterDestroy: function(){
	// stub
	},

	afterConnect: function(){
	// stub
	},

	// Determine the proper outlet selector and ensure that it is valid
	_verifyOutlet: function (outlet,context) {

		// If a parent component exists, render into that by default
		outlet = outlet || this.outlet || (this.parent && this.parent.$el);

		if (!outlet && !this.parent) {
			throw new Error("No outlet selector specified to render into!");
			return false;
		}

		var $outlet;
		if (_.isString(outlet)) {
			$outlet = (context && context.closest_descendant(outlet)) || $(outlet);
		}
		else {
			$outlet = outlet;
		}

		if ($outlet.length != 1) {

			//			debug.debug($outlet,outlet,this.parent.$el);
			debug.warn(
				(($outlet.length > 1)?"More than one ":"No ")+
				(($outlet.length > 1)?"element exists ":"elements exist ")+
				(context?"in this template context ("+context+ ")":"") +
				"for the specified "+
				(context?"child ":"") +
				"outlet selector! ('"+outlet+"')");
			return false;
		}
		return $outlet;
	},

	// Used for debugging
	_test: function() {
		debug.debug("TEST FUNCTION FIRED!",arguments,this);
	}
}<|endoftext|>


<commit_before>var request = require('request')
var asciify = require('asciify')
var fs = require('fs')

var addContributor = require('./contributors.js')
var buildPage = require('./buildpage.js')

var baseURL = 'https://api.github.com/repos/jlord/patchwork/'
var stats = {}

// what happens when multiple people are doing this?!

module.exports = function(pullreq, req) {
  if (pullreq.action && pullreq.action === "closed") return
  if (pullreq.pull_request) pullreq = pullreq.pull_request

  stats.prNum = pullreq.number

  // make sure it's not a non-workshop, normal PR
  if (pullreq.base.ref.match(pullreq.user.login)) return

  var options = {
      url: baseURL +'pulls/' + stats.prNum,
      json: true,
      headers: {
          'User-Agent': 'request',
          'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
      }
  }

  function getTime(error, response, body) {
    if (error) console.log(error)

      if (!error && response.statusCode == 200) {
        var info = body
        stats.time = info.created_at
        stats.username = info.user.login
        getFile(stats.prNum)
      }
  }

  request(options, getTime)

  function getFile(prNum) {
    var options = {
        url: baseURL + 'pulls/' + prNum + '/files',
        json: true,
        headers: {
            'User-Agent': 'request',
            'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
        }
    }

    request(options, function returnFiles(error, response, body) {
      if (error) console.log(error)

        if (!error && response.statusCode == 200) {
          var prInfo = body[0]
          verifyFilename(prInfo)
        }
    })
  }
}

function verifyFilename(prInfo) {
  // add /contributors/ to filename
  var filename = prInfo.filename
  // if (filename.match('/contributors/test.md')) {
  if (filename.match('/contributors/add-' + stats.username + '.md')) {
    console.log("Filename: MATCH")
    verifyContent(prInfo)
  }
  else {
    var message = 'Filename is different than expected: /contributors/add-' + stats.username
    writeComment(message, stats.prNum)
  }
}

function verifyContent(prInfo) {
  // pull out the actual pr content
  var patchArray = prInfo.patch.split('@@')
  var patch = patchArray.pop()
  // generate the expected content
  asciify(stats.username, {font:'isometric2'}, function(err, res){
    if (err) console.log(err)
    if (res.match(patch)) {
      stats.userArt = res
      console.log("Content: MATCH")
      mergePR(stats.prNum)
    }
    else {
      var message = "Ascii art wasn't as expected, did something change?"
      writeComment(message, stats.prNum)
    }
  })
}

function writeComment(message, prNum) {
  console.log("uh oh, writing comment")
   var options = {
      url: baseURL + 'issues/' + prNum + '/comments',
      headers: {
          'User-Agent': 'request',
          'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
      },
      json: {'body': message}
  }

  request.post(options, function done(error, response, body) {
    if (error) console.log(error)
  })
}

function mergePR(prNum) {
  addContributor(stats, buildPage)
  var message = "Merging PR from @" + stats.username
  var options = {
     url: baseURL + 'pulls/' + prNum + '/merge',
     headers: {
         'User-Agent': 'request',
         'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
     },
     json: {'commit_message': message}
 }

 request.put(options, function done(error, response, body) {
   if (error) console.log(error)
   if (!error && response.statusCode == 200) {
       console.log("MERGED")
       // add contributor to file and rebuild page
       addContributor(stats, buildPage)
   }
 })
}<commit_msg>expected filename<commit_after>var request = require('request')
var asciify = require('asciify')
var fs = require('fs')

var addContributor = require('./contributors.js')
var buildPage = require('./buildpage.js')

var baseURL = 'https://api.github.com/repos/jlord/patchwork/'
var stats = {}

// what happens when multiple people are doing this?!

module.exports = function(pullreq, req) {
  if (pullreq.action && pullreq.action === "closed") return
  if (pullreq.pull_request) pullreq = pullreq.pull_request

  stats.prNum = pullreq.number

  // make sure it's not a non-workshop, normal PR
  if (pullreq.base.ref.match(pullreq.user.login)) return

  var options = {
      url: baseURL +'pulls/' + stats.prNum,
      json: true,
      headers: {
          'User-Agent': 'request',
          'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
      }
  }

  function getTime(error, response, body) {
    if (error) console.log(error)

      if (!error && response.statusCode == 200) {
        var info = body
        stats.time = info.created_at
        stats.username = info.user.login
        getFile(stats.prNum)
      }
  }

  request(options, getTime)

  function getFile(prNum) {
    var options = {
        url: baseURL + 'pulls/' + prNum + '/files',
        json: true,
        headers: {
            'User-Agent': 'request',
            'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
        }
    }

    request(options, function returnFiles(error, response, body) {
      if (error) console.log(error)

        if (!error && response.statusCode == 200) {
          var prInfo = body[0]
          verifyFilename(prInfo)
        }
    })
  }
}

function verifyFilename(prInfo) {
  // add /contributors/ to filename
  var filename = prInfo.filename
  console.log(["filename from PR", filename])
  // if (filename.match('/contributors/test.md')) {
  if (filename.match('contributors/add-' + stats.username + '.md')) {
    console.log("Filename: MATCH")
    verifyContent(prInfo)
  }
  else {
    var message = 'Filename is different than expected: contributors/add-' + stats.username
    writeComment(message, stats.prNum)
  }
}

function verifyContent(prInfo) {
  // pull out the actual pr content
  var patchArray = prInfo.patch.split('@@')
  var patch = patchArray.pop()
  // generate the expected content
  asciify(stats.username, {font:'isometric2'}, function(err, res){
    if (err) console.log(err)
    if (res.match(patch)) {
      stats.userArt = res
      console.log("Content: MATCH")
      mergePR(stats.prNum)
    }
    else {
      var message = "Ascii art wasn't as expected, did something change?"
      writeComment(message, stats.prNum)
    }
  })
}

function writeComment(message, prNum) {
  console.log("uh oh, writing comment")
   var options = {
      url: baseURL + 'issues/' + prNum + '/comments',
      headers: {
          'User-Agent': 'request',
          'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
      },
      json: {'body': message}
  }

  request.post(options, function done(error, response, body) {
    if (error) console.log(error)
  })
}

function mergePR(prNum) {
  addContributor(stats, buildPage)
  var message = "Merging PR from @" + stats.username
  var options = {
     url: baseURL + 'pulls/' + prNum + '/merge',
     headers: {
         'User-Agent': 'request',
         'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
     },
     json: {'commit_message': message}
 }

 request.put(options, function done(error, response, body) {
   if (error) console.log(error)
   if (!error && response.statusCode == 200) {
       console.log("MERGED")
       // add contributor to file and rebuild page
       addContributor(stats, buildPage)
   }
 })
}<|endoftext|>


<commit_before>angular.module('loc8rApp', []);

var locationsListCtrl = function($scope, loc8rData, geolocation){
  $scope.message = "Checking your location";
  $scope.getData = function(position){
    $scope.message = "Searching for nearby places";
    loc8rData
      .success(function(data){
        $scope.message = data.length > 0 ? "" : "No locations found";
        $scope.data = {locations: data};
      })
        .error(function(err){
        console.log(err);
        $scope.message = "Sorry, something's gone wrong";
        });
  };
  $scope.showError = function(error){
    $scope.$apply(function(){
      $scope.message = error.message;
    });
  };
  $scope.noGeo = function(){
    $scope.$apply(function(){
      $scope.message = "Geolocation is not supported by your browser";
    });
  };

  geolocation.getPosition($scope.getData, $scope.showError, $scope.noGeo);
};

var _isNumeric = function(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
};

var formatDistance = function() {
  return function(distance){
    var numDistance, unit;
    if (distance && _isNumeric(distance)) {
      if (distance > 1){
        numDistance = parseFloat(distance).toFixed(1);
        unit = 'km';
      } else {
        numDistance = parseInt(distance * 1000,10);
        unit = 'm';
      }
      return numDistance + unit;
    } else {
      return "?";
    }
  };
};

var ratingStars = function(){
  return{
    scope: {
      thisRating: '=rating'
    },
    templateUrl: "/angular/rating-stars.html"
  };
};

var loc8rData = function($http){
  return $http.get('/api/locations?lng=-0.79&lat=51.3&maxDistance=500');
}

var geolocation = function(){
  var getPosition = function(cbSuccess, cbError, cbNoGeo){
    if (navigator.geolocation){
      navigator.geolocation.getCurrentPosition(cbSuccess, cbError);
    } else {
      cbNoGeo();
    }
  };
  return {
    getPosition: getPosition
  };
};

angular
  .module('loc8rApp')
  .controller('locationsListCtrl', locationsListCtrl)
  .filter('formatDistance', formatDistance)
  .directive('ratingStars', ratingStars)
  .service('loc8rData', loc8rData)
  .service('geolocation', geolocation);
<commit_msg>pass location to api call<commit_after>angular.module('loc8rApp', []);

var locationsListCtrl = function($scope, loc8rData, geolocation){
  $scope.message = "Checking your location";
  $scope.getData = function(position){
    var lat = position.coords.latitude,
        lng = position.coords.longitude;
    $scope.message = "Searching for nearby places";
    loc8rData.locationByCoords(lat, lng)
      .success(function(data){
        $scope.message = data.length > 0 ? "" : "No locations found";
        $scope.data = {locations: data};
      })
        .error(function(err){
        console.log(err);
        $scope.message = "Sorry, something's gone wrong";
        });
  };
  $scope.showError = function(error){
    $scope.$apply(function(){
      $scope.message = error.message;
    });
  };
  $scope.noGeo = function(){
    $scope.$apply(function(){
      $scope.message = "Geolocation is not supported by your browser";
    });
  };

  geolocation.getPosition($scope.getData, $scope.showError, $scope.noGeo);
};

var _isNumeric = function(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
};

var formatDistance = function() {
  return function(distance){
    var numDistance, unit;
    if (distance && _isNumeric(distance)) {
      if (distance > 1){
        numDistance = parseFloat(distance).toFixed(1);
        unit = 'km';
      } else {
        numDistance = parseInt(distance * 1000,10);
        unit = 'm';
      }
      return numDistance + unit;
    } else {
      return "?";
    }
  };
};

var ratingStars = function(){
  return{
    scope: {
      thisRating: '=rating'
    },
    templateUrl: "/angular/rating-stars.html"
  };
};

var loc8rData = function($http){
  var locationByCoords = function (lat, lng){
    return $http.get('/api/locations?lng=' + lng + '&lat=' + lat + '&maxDistance=30');
  };
  return {
    locationByCoords: locationByCoords
  };
  // return $http.get('/api/locations?lng=-0.79&lat=51.3&maxDistance=500');
};

var geolocation = function(){
  var getPosition = function(cbSuccess, cbError, cbNoGeo){
    if (navigator.geolocation){
      navigator.geolocation.getCurrentPosition(cbSuccess, cbError);
    } else {
      cbNoGeo();
    }
  };
  return {
    getPosition: getPosition
  };
};

angular
  .module('loc8rApp')
  .controller('locationsListCtrl', locationsListCtrl)
  .filter('formatDistance', formatDistance)
  .directive('ratingStars', ratingStars)
  .service('loc8rData', loc8rData)
  .service('geolocation', geolocation);
<|endoftext|>


<commit_before>var $ = require('../')
  , assert = require('assert')

$.import('Foundation')
$.NSAutoreleasePool('alloc')('init')

// Subclass 'NSObject', creating a new class named 'NRTest'
var NRTest = $.NSObject.extend('NRTest')
  , counter = 0

// Add a new method to the NRTest class responding to the "description" selector
assert.ok(NRTest.addMethod('description', '@@:', function (self, _cmd) {
  counter++
  console.log(_cmd)
  console.log(self.ivar('name'))
  return $.NSString('stringWithUTF8String', 'test')
}))

// Add an instance variable, an NSString* instance.
assert.ok(NRTest.addIvar('name', '@'))

// Finalize the class so the we can make instances of it
NRTest.register()

// Create an instance
var instance = NRTest('alloc')('init')

// call [instance description] in a variety of ways (via toString())
console.log(instance('description')+'')
console.log(instance.toString())
instance.ivar('name', $._('NodObjC Rules!'))
console.log(String(instance))
console.log(''+instance)
console.log(instance+'')
console.log(instance)

assert.equal(counter, 6)
<commit_msg>Add tests for setting the extended Class onto the main exports.<commit_after>var $ = require('../')
  , assert = require('assert')

$.import('Foundation')
$.NSAutoreleasePool('alloc')('init')

// Subclass 'NSObject', creating a new class named 'NRTest'
var NRTest = $.NSObject.extend('NRTest')
  , counter = 0

// Add a new method to the NRTest class responding to the "description" selector
assert.ok(NRTest.addMethod('description', '@@:', function (self, _cmd) {
  counter++
  console.log(_cmd)
  console.log(self.ivar('name'))
  return $.NSString('stringWithUTF8String', 'test')
}))

// Add an instance variable, an NSString* instance.
assert.ok(NRTest.addIvar('name', '@'))

// Test that the Class does not exist on $ before register() is called
assert.ok(!$.NRTest)
assert.notEqual(NRTest, $.NRTest)

// Finalize the class so the we can make instances of it
NRTest.register()

// Test that the Class gets set onto $ after register() is called
assert.strictEqual(NRTest, $.NRTest)

// Create an instance
var instance = NRTest('alloc')('init')

// call [instance description] in a variety of ways (via toString())
console.log(instance('description')+'')
console.log(instance.toString())
instance.ivar('name', $._('NodObjC Rules!'))
console.log(String(instance))
console.log(''+instance)
console.log(instance+'')
console.log(instance)

assert.equal(counter, 6)
<|endoftext|>


<commit_before>'use strict';

// require modules
var tessel = require('tessel');
var ambientlib = require('ambient-attx4');
var Neopixels = require('neopixels');

// initializing modules
var ambient = ambientlib.use(tessel.port.B);
var neopixels = new Neopixels();

// setting constants
var leds = 60;
var clapdelay = 500;
var color = {
  off: [0x00, 0x00, 0x00],
  blue: [0x00, 0x00, 0xFF],
  green: [0xFF, 0x00, 0x00],
  red: [0x00, 0xFF, 0x00]
};
var currentColor = color.off;
var last = Date.now();
var setColor = color.off;

// set all LEDs off
neopixels.animate( leds, Buffer.concat(setAll(leds, color.off)) );

// when ready
ambient.on('ready', function () {
  // ready animation for fun
  neopixels.animate( leds, Buffer.concat(tracer(leds)) );
  // Set a sound level trigger float between 0 and 1
  ambient.setSoundTrigger(0.1);

  ambient.on('sound-trigger', function(data) {
    console.log('Tripped sound threshold at level ', data);
    // Clear it
    ambient.clearSoundTrigger();

    // double clap handler to turn on and off
    if ( Date.now() - last < clapdelay ) {
      setColor = (setColor === color.off) ? color.red : color.off;
    } else if (setColor !== color.off) { // single clap for color switching
      setColor = (setColor === color.red) ? color.green : color.red;
    }

    last = Date.now();
    neopixels.animate( leds, Buffer.concat(setAll(leds, setColor)) );

    //After delay reset sound trigger
    setTimeout(function () {
      ambient.setSoundTrigger(0.1);
    }, 10);
  });

});

// error logging
ambient.on('error', function (err) {
  console.log(err);
});

// set leds to color
function setAll (numLEDs, color) {
  var buf = new Buffer(numLEDs * 3);
  for (var i = 0; i < buf.length; i += 3) {
    buf[i] = color[0];
    buf[i+1] = color[1];
    buf[i+2] = color[2];
  }
  currentColor = color;
  return [buf];
}

// An example animation
function tracer(numLEDs) {
  var trail = 20;
  var arr = new Array(numLEDs);
  for (var i = 0; i < numLEDs; i++) {
    var buf = new Buffer(numLEDs * 3);
    buf.fill(0);
    for (var col = 0; col < 3; col++){
      for (var k = 0; k < trail; k++) {
        buf[(3*(i+numLEDs*col/3)+col+1 +3*k)] = 0xFF*(trail-k)/trail;
      }
    }
    arr[i] = buf;
  }
  var newArr = [];
  for (var i = 0; i < arr.length; i++) {
    newArr.push(arr[i]);
    newArr.push(arr[i]);
    newArr.push(arr[i]);
    newArr.push(arr[i]);
    newArr.push(arr[i]);
    newArr.push(arr[i]);
  }
  return newArr;
}
<commit_msg>full color cycle active<commit_after>'use strict';

// require modules
var tessel = require('tessel');
var ambientlib = require('ambient-attx4');
var Neopixels = require('neopixels');

// initializing modules
var ambient = ambientlib.use(tessel.port.B);
var neopixels = new Neopixels();

// setting constants
var leds = 60;
var clapdelay = 500;
var color = {
  off: [0x00, 0x00, 0x00],
  green: [0xFF, 0x00, 0x00],
  red: [0x00, 0xFF, 0x00],
  blue: [0x00, 0x00, 0xFF],
  purple: [0x00, 0xFF, 0xFF],
  yellow: [0xFF, 0xFF, 0x00],
  cyan: [0xFF, 0x00, 0xFF]
};
var last = Date.now();
var setColor = color.off;

// set all LEDs off
neopixels.animate( leds, Buffer.concat(setAll(leds, color.off)) );

// when ready
ambient.on('ready', function () {
  // ready animation for fun
  neopixels.animate( leds, Buffer.concat(tracer(leds)) );
  // Set a sound level trigger float between 0 and 1
  ambient.setSoundTrigger(0.1);

  ambient.on('sound-trigger', function(data) {
    console.log('Tripped sound threshold at level ', data);
    // Clear it
    ambient.clearSoundTrigger();

    // double clap handler to turn on and off
    if ( Date.now() - last < clapdelay ) {
      setColor = (setColor === color.off) ? color.green : color.off;
    } else if (setColor !== color.off) { // single clap for color switching
      switch (setColor) {
        case color.green:
          setColor = color.red;
          break;
        case color.red:
          setColor = color.blue;
          break;
        case color.blue:
          setColor = color.yellow;
          break;
        case color.yellow:
          setColor = color.purple;
          break;
        case color.purple:
          setColor = color.cyan;
          break;
        case color.cyan:
          setColor = color.green;
          break;
        default:
          setColor = color.green;
      }
    }

    last = Date.now();
    neopixels.animate( leds, Buffer.concat(setAll(leds, setColor)) );

    //After delay reset sound trigger
    setTimeout(function () {
      ambient.setSoundTrigger(0.1);
    }, 10);
  });

});

// error logging
ambient.on('error', function (err) {
  console.log(err);
});

// set leds to color
function setAll (numLEDs, color) {
  var buf = new Buffer(numLEDs * 3);
  for (var i = 0; i < buf.length; i += 3) {
    buf[i] = color[0];
    buf[i+1] = color[1];
    buf[i+2] = color[2];
  }
  return [buf];
}

// An example animation
function tracer(numLEDs) {
  var trail = 20;
  var arr = new Array(numLEDs);
  for (var i = 0; i < numLEDs; i++) {
    var buf = new Buffer(numLEDs * 3);
    buf.fill(0);
    for (var col = 0; col < 3; col++){
      for (var k = 0; k < trail; k++) {
        buf[(3*(i+numLEDs*col/3)+col+1 +3*k)] = 0xFF*(trail-k)/trail;
      }
    }
    arr[i] = buf;
  }
  var newArr = [];
  for (var i = 0; i < arr.length; i++) {
    newArr.push(arr[i]);
    newArr.push(arr[i]);
    newArr.push(arr[i]);
    newArr.push(arr[i]);
    newArr.push(arr[i]);
    newArr.push(arr[i]);
  }
  return newArr;
}
<|endoftext|>


<commit_before>var dbconn = require('../data/dbconnection.js');
var ObjectId = require('mongodb').ObjectId;
var hotelData = require('../data/hotel-data.json');

module.exports.hotelsGetAll = function(req,res){

  var db = dbconn.get();
  var collection = db.collection('hotelCollection');
  //
  var start = 0, count = 3; // which hotel to start at and how many to show
  (req.query.start) ? start = parseInt(req.query.start, 10) : start = 0 ;
  (req.query.count) ? count = parseInt(req.query.count, 10) : count = 5 ;
  //
  collection
    .find()
    .skip(start)
    .limit(count)
    .toArray(function(err, docs){
      console.log('found these hotels: ', docs);
      res
        .status(200)
        .json(docs);
    });
};

module.exports.hotelsGetOne = function(req,res){
  var db = dbconn.get();
  var collection = db.collection('hotelCollection');
  var hotelId = req.params.hotelId; // I named this route in index.js
  console.log("getting one hotel with ID of ", hotelId );
  collection
    .findOne( { _id : ObjectId(hotelId) } , function(err, doc){
      res
        .status(200)
        .json(doc);
    });

};

module.exports.hotelsAddOne = function(req,res){
  var db = dbconn.get();
  var collection = db.collection('hotelCollection');
  console.log('posting new hotel');
  console.log(req.body);
  res
    .status(200)
    .json(req.body);
};
<commit_msg>note to self, lecture 23 tommorrow<commit_after>var dbconn = require('../data/dbconnection.js');
var ObjectId = require('mongodb').ObjectId;
var hotelData = require('../data/hotel-data.json');

module.exports.hotelsGetAll = function(req,res){

  var db = dbconn.get();
  var collection = db.collection('hotelCollection');
  //
  var start = 0, count = 3; // which hotel to start at and how many to show
  (req.query.start) ? start = parseInt(req.query.start, 10) : start = 0 ;
  (req.query.count) ? count = parseInt(req.query.count, 10) : count = 5 ;
  //
  collection
    .find()
    .skip(start)
    .limit(count)
    .toArray(function(err, docs){
      console.log('found these hotels: ', docs);
      res
        .status(200)
        .json(docs);
    });
};

module.exports.hotelsGetOne = function(req,res){
  var db = dbconn.get();
  var collection = db.collection('hotelCollection');
  var hotelId = req.params.hotelId; // I named this route in index.js
  console.log("getting one hotel with ID of ", hotelId );
  collection
    .findOne( { _id : ObjectId(hotelId) } , function(err, doc){
      res
        .status(200)
        .json(doc);
    });
};

// ON lecture 23 09/20/17
module.exports.hotelsAddOne = function(req,res){
  var db = dbconn.get();
  var collection = db.collection('hotelCollection');
  console.log('posting new hotel');
  console.log(req.body);
  res
    .status(200)
    .json(req.body);
};
<|endoftext|>


<commit_before>/* global Exhibit */
/**
 * @fileOverview Slider facet functions and UI
 * @author SkyeWM
 * @author David Karger
 * @author Axel Hecht
 */

/**
 * @class
 * @constructor
 * @param {Element} containerElmt
 * @param {Exhibit.UIContext} uiContext
 */
Exhibit.SliderFacet = function(containerElmt, uiContext) {
    Exhibit.jQuery.extend(this, new Exhibit.Facet("cloud", containerElmt, uiContext));
    this.addSettingSpecs(Exhibit.SliderFacet._settingSpecs);

//  this._selection = {min: null, max: null};
    this._range = {min: null, max: null}; //currently selected range
    this._maxRange = {min: null, max: null}; //total range of slider
};

/**
 * @private
 * @constant
 */
Exhibit.SliderFacet._settingSpecs = {
    "precision":        { "type": "float", "defaultValue": 1 },
    "histogram":        { "type": "boolean", "defaultValue": true },
    "horizontal":       { "type": "boolean", "defaultValue": true },
    "showMissing":      { "type": "boolean", "defaultValue": true},
    "selection":        { "type": "float", "dimensions": 2}
};

/**
 * @static
 * @param {Object} configuration
 * @param {Element} containerElmt
 * @param {Exhibit.UIContext} uiContext
 * @returns {Exhibit.SliderFacet}
 */
Exhibit.SliderFacet.create = function(configuration, containerElmt, uiContext) {
    var facet, thisUIContext;
    thisUIContext = Exhibit.UIContext.create(configuration, uiContext);
    facet = new Exhibit.SliderFacet(containerElmt, thisUIContext);

    Exhibit.SliderFacet._configure(facet, configuration);

    facet._initializeUI();
    thisUIContext.getCollection().addFacet(facet);
    facet.register();

    return facet;
};

/**
 * @static
 * @param {Element} configElmt
 * @param {Element} containerElmt
 * @param {Exhibit.UIContext} uiContext
 * @returns {Exhibit.SliderFacet}
 */
Exhibit.SliderFacet.createFromDOM = function(configElmt, containerElmt, uiContext) {
    var configuration, thisUIContext, facet, expressionString, selection, showMissing;
    configuration = Exhibit.getConfigurationFromDOM(configElmt);
    thisUIContext = Exhibit.UIContext.createFromDOM(configElmt, uiContext);
    facet = new Exhibit.SliderFacet(
    (typeof containerElmt !== "undefined" && containerElmt !== null) ?
            containerElmt :
            configElmt,
    thisUIContext
    );

    //fills facet with configuration information
    Exhibit.SettingsUtilities.collectSettingsFromDOM(configElmt, facet.getSettingSpecs(), facet._settings);

    try {
        expressionString = Exhibit.getAttribute(configElmt, "expression");
        if (typeof expressionString !== "undefined" && expressionString !== null && expressionString.length > 0) {
            facet.setExpression(Exhibit.ExpressionParser.parse(expressionString));
        facet.setExpressionString(expressionString);
        }

        showMissing = Exhibit.getAttribute(configElmt, "showMissing");

        if (showMissing !== null && showMissing.length > 0) {
            facet._showMissing = (showMissing == "true");
        }
        else {
            facet._showMissing=true;
        }

    if ("selection" in facet._settings) {
        selection = facet._settings.selection;
        facet._range = {min: selection[0], max: selection[1]};
    }

    } catch (e) {
        Exhibit.Debug.exception(e, Exhibit._("%facets.error.configuration", "SliderFacet"));
    }

    Exhibit.SliderFacet._configure(facet, configuration);
    facet._initializeUI();
    thisUIContext.getCollection().addFacet(facet);
    facet.register();

    return facet;
};

/**
 * @static
 * @private
 * @param {Exhibit.SliderFacet} facet
 * @param {Object} configuration
 */
Exhibit.SliderFacet._configure = function(facet, configuration) {
    var selection, segment, property;
    Exhibit.SettingsUtilities.collectSettings(configuration, facet.getSettingSpecs(), facet._settings);

    if (typeof configuration.expression !== "undefined") {
        facet.setExpressionString(configuration.expression);
        facet.setExpression(Exhibit.ExpressionParser.parse(configuration.expression));
    }
    if (typeof configuration.selection !== "undefined") {
        selection = configuration.selection;
        facet._range = {min: selection[0], max: selection[1]};
    }
    if (typeof configuration.showMissing !== "undefined") {
        facet._showMissing = configuration.showMissing;
    }

    if (typeof facet._settings.facetLabel === "undefined") {
        if (facet.getExpression() !== null && facet.getExpression().isPath()) {
            segment = facet.getExpression().getPath().getLastSegment();
            property = facet.getUIContext().getDatabase().getProperty(segment.property);
            if (typeof property !== "undefined" && property !== null) {
                facet._settings.facetLabel = segment.forward ? property.getLabel() : property.getReverseLabel();
            }
        }
    }

    facet._cache = new Exhibit.FacetUtilities.Cache(
        facet.getUIContext().getDatabase(),
        facet.getUIContext().getCollection(),
        facet.getExpression()
    );

    facet._maxRange = facet._getMaxRange();
};

/**
 *
 */
Exhibit.SliderFacet.prototype._dispose = function() {
    this._cache.dispose();
    this._cache = null;
//  this._selection = null;
    this._range = null; //currently selected range
    this._maxRange = null; //total range of slider
};

/**
 * @returns {Boolean}
 */
Exhibit.SliderFacet.prototype.hasRestrictions = function() {
    return (this._range.min && this._range.min != this._maxRange.min) ||
           (this._range.max && this._range.max != this._maxRange.max);
};

/**
 *
 */
Exhibit.SliderFacet.prototype.clearAllRestrictions = function() {
    Exhibit.jQuery(this.getContainer()).trigger("onBeforeFacetReset.exhibit");
    this._range = this._maxRange;
    this._notifyCollection();
};

/**
 * @param {Exhibit.Set} items
 * @returns {Exhibit.Set}
 */
Exhibit.SliderFacet.prototype.restrict = function(items) {
    if (!this.hasRestrictions()) {
        return items;
    }

    var set = new Exhibit.Set();

    if (this.getExpression().isPath()){
        var path = this.getExpression().getPath();
        var database = this.getUIContext().getDatabase();
        set=path.rangeBackward(this._range.min, this._range.max, false, items, database).values;
    }
    else {
        this._buildRangeIndex();
        var rangeIndex=this._rangeIndex;
        set=rangeIndex.getSubjectsInRange(this._range.min, this._range.max, false, null, items);
    }

    if (this._showMissing){
        this._cache.getItemsMissingValue(items, set);
    }

    return set;
};

/**
 * @param {Exhibit.Set} items
 */
Exhibit.SliderFacet.prototype.update = function(items) {
    if (this._settings.histogram) {
        var data = [];
        var n = 75; //number of bars on histogram
        var range = (this._maxRange.max - this._maxRange.min)/n; //range represented by each bar
        var missingCount = 0;
        var database = this.getUIContext().getDatabase();

        if (this._selectMissing){
            missingCount = this._cache.getItemsMissingValue(items).size();
        }

        if (this.getExpression().isPath()){
            var path = this.getExpression().getPath();

            for (var i=0; i<n; i++) {
                data[i] = path.rangeBackward(this._maxRange.min+i*range, this._maxRange.min+(i+1)*range, (i+1) === n, items,database).values.size()+missingCount;
            }
        }

        else {
            this._buildRangeIndex();
            var rangeIndex=this._rangeIndex;

            for (var i=0; i<n; i++){
                data[i] = rangeIndex.getSubjectsInRange(this._maxRange.min+i*range, this._maxRange.min+(i+1)*range, (i+1) === n, null, items).size()+missingCount;
            }

        }
        this._slider.updateHistogram(data);
    }
    this._slider._setMin(this._range.min);
    this._slider._setMax(this._range.max);
};

/**
 * @private
 */
Exhibit.SliderFacet.prototype._initializeUI = function() {
    Exhibit.jQuery(this.getContainer()).empty();
    Exhibit.jQuery(this.getContainer()).addClass("exhibit-cloudFacet");

    var dom = Exhibit.jQuery.simileDOM(
        "string",
        this.getContainer(),
        ((typeof this._settings.facetLabel !== "undefined") ?
         (   "
" +
             "" + this.getLabel() + "" +
             "
"
         ) :
         ""
        ) +
            '

'
    );

    this._dom = dom;

    this._slider = new Exhibit.SliderFacet.slider(this._dom.slider, this, this._settings.precision, this._settings.horizontal);
};

/**
 * @private
 * @returns {Object}
 */
//gets maximum range? need to construct a range index for this...
Exhibit.SliderFacet.prototype._getMaxRange = function() {
    var rangeIndex;
    if (this.getExpression().isPath()){
        var path = this.getExpression().getPath();
        var database = this.getUIContext().getDatabase();
        var propertyID = path.getLastSegment().property;
        var property = database.getProperty(propertyID);
        rangeIndex = property.getRangeIndex();
    }
    else {
        this._buildRangeIndex();
        rangeIndex = this._rangeIndex;
    }

    return {min: rangeIndex.getMin(), max: rangeIndex.getMax()};
};

/**
 * @private
 */
Exhibit.SliderFacet.prototype._buildRangeIndex = function() {
    if (typeof this._rangeIndex === "undefined") {
        var expression = this.getExpression();
        var database = this.getUIContext().getDatabase();
        var getter = function(item, f) {
            expression.evaluateOnItem(item, database).values.visit(function(value) {
                if (typeof value != "number") {
                    value = parseFloat(value);
                }
                if (!isNaN(value)) {
                    f(value);
                }
            });
        };

        this._rangeIndex = new Exhibit.Database.RangeIndex(
            this.getUIContext().getCollection().getAllItems(),
            getter
        );
    }
};

/**
 * Used by the actual slider to set the facet values
 */
Exhibit.SliderFacet.prototype.changeRange = function(range) {
    Exhibit.History.pushComponentState(
        this,
        Exhibit.Facet.getRegistryKey(),
        range,
        Exhibit._("%facets.numeric.rangeShort", range.min, range.max),
        true
    );
};

//clear
Exhibit.SliderFacet.prototype._notifyCollection = function() {
    this.getUIContext().getCollection().onFacetUpdated(this);
};

/**
 * @returns {Object}
 */
Exhibit.SliderFacet.prototype.exportEmptyState = function() {
    return {};
};

/**
 * @returns {Object}
 */
Exhibit.SliderFacet.prototype.exportState = function() {
    return this._range;
};

/**
 * @param {Object} state
 */
Exhibit.SliderFacet.prototype.importState = function(state) {
    if (this.stateDiffers(state)) {
        if (typeof state.min === 'undefined' || state.min === null) {
            this._range.min = this._maxRange.min;
        }
        else {
            this._range.min = state.min;
        }
        this._slider._setMin(this._range.min);
        if (typeof state.max === 'undefined' || state.max === null) {
            this._range.max = this._maxRange.max;
        }
        else {
            this._range.max = state.max;
        }
        this._slider._setMax(this._range.max);
    }
    this._notifyCollection();
};

/**
 * @param {Object} state
 */
Exhibit.SliderFacet.prototype.stateDiffers = function(state) {
    if (typeof state.min === 'undefined') {
        if (this._range.min && this._range.min != this._maxRange.min) {
            return true;
        }
    }
    else {
        if (this._range.min !== state.min) {
            return true;
        }
    }
    if (typeof state.max === 'undefined') {
        if (this._range.max && this._range.max != this._maxRange.max) {
            return true;
        }
    }
    else {
        if (this._range.max !== state.min) {
            return true;
        }
    }
    return false;
};
<commit_msg>Missed an option for the slider facet<commit_after>/* global Exhibit */
/**
 * @fileOverview Slider facet functions and UI
 * @author SkyeWM
 * @author David Karger
 * @author Axel Hecht
 */

/**
 * @class
 * @constructor
 * @param {Element} containerElmt
 * @param {Exhibit.UIContext} uiContext
 */
Exhibit.SliderFacet = function(containerElmt, uiContext) {
    Exhibit.jQuery.extend(this, new Exhibit.Facet("cloud", containerElmt, uiContext));
    this.addSettingSpecs(Exhibit.SliderFacet._settingSpecs);

//  this._selection = {min: null, max: null};
    this._range = {min: null, max: null}; //currently selected range
    this._maxRange = {min: null, max: null}; //total range of slider
};

/**
 * @private
 * @constant
 */
Exhibit.SliderFacet._settingSpecs = {
    "precision":        { "type": "float", "defaultValue": 1 },
    "histogram":        { "type": "boolean", "defaultValue": true },
    "horizontal":       { "type": "boolean", "defaultValue": true },
    "showMissing":      { "type": "boolean", "defaultValue": true},
    "inputText":        { type: "boolean", defaultValue: true },
    "selection":        { "type": "float", "dimensions": 2}
};

/**
 * @static
 * @param {Object} configuration
 * @param {Element} containerElmt
 * @param {Exhibit.UIContext} uiContext
 * @returns {Exhibit.SliderFacet}
 */
Exhibit.SliderFacet.create = function(configuration, containerElmt, uiContext) {
    var facet, thisUIContext;
    thisUIContext = Exhibit.UIContext.create(configuration, uiContext);
    facet = new Exhibit.SliderFacet(containerElmt, thisUIContext);

    Exhibit.SliderFacet._configure(facet, configuration);

    facet._initializeUI();
    thisUIContext.getCollection().addFacet(facet);
    facet.register();

    return facet;
};

/**
 * @static
 * @param {Element} configElmt
 * @param {Element} containerElmt
 * @param {Exhibit.UIContext} uiContext
 * @returns {Exhibit.SliderFacet}
 */
Exhibit.SliderFacet.createFromDOM = function(configElmt, containerElmt, uiContext) {
    var configuration, thisUIContext, facet, expressionString, selection, showMissing;
    configuration = Exhibit.getConfigurationFromDOM(configElmt);
    thisUIContext = Exhibit.UIContext.createFromDOM(configElmt, uiContext);
    facet = new Exhibit.SliderFacet(
    (typeof containerElmt !== "undefined" && containerElmt !== null) ?
            containerElmt :
            configElmt,
    thisUIContext
    );

    //fills facet with configuration information
    Exhibit.SettingsUtilities.collectSettingsFromDOM(configElmt, facet.getSettingSpecs(), facet._settings);

    try {
        expressionString = Exhibit.getAttribute(configElmt, "expression");
        if (typeof expressionString !== "undefined" && expressionString !== null && expressionString.length > 0) {
            facet.setExpression(Exhibit.ExpressionParser.parse(expressionString));
        facet.setExpressionString(expressionString);
        }

        showMissing = Exhibit.getAttribute(configElmt, "showMissing");

        if (showMissing !== null && showMissing.length > 0) {
            facet._showMissing = (showMissing == "true");
        }
        else {
            facet._showMissing=true;
        }

    if ("selection" in facet._settings) {
        selection = facet._settings.selection;
        facet._range = {min: selection[0], max: selection[1]};
    }

    } catch (e) {
        Exhibit.Debug.exception(e, Exhibit._("%facets.error.configuration", "SliderFacet"));
    }

    Exhibit.SliderFacet._configure(facet, configuration);
    facet._initializeUI();
    thisUIContext.getCollection().addFacet(facet);
    facet.register();

    return facet;
};

/**
 * @static
 * @private
 * @param {Exhibit.SliderFacet} facet
 * @param {Object} configuration
 */
Exhibit.SliderFacet._configure = function(facet, configuration) {
    var selection, segment, property;
    Exhibit.SettingsUtilities.collectSettings(configuration, facet.getSettingSpecs(), facet._settings);

    if (typeof configuration.expression !== "undefined") {
        facet.setExpressionString(configuration.expression);
        facet.setExpression(Exhibit.ExpressionParser.parse(configuration.expression));
    }
    if (typeof configuration.selection !== "undefined") {
        selection = configuration.selection;
        facet._range = {min: selection[0], max: selection[1]};
    }
    if (typeof configuration.showMissing !== "undefined") {
        facet._showMissing = configuration.showMissing;
    }

    if (typeof facet._settings.facetLabel === "undefined") {
        if (facet.getExpression() !== null && facet.getExpression().isPath()) {
            segment = facet.getExpression().getPath().getLastSegment();
            property = facet.getUIContext().getDatabase().getProperty(segment.property);
            if (typeof property !== "undefined" && property !== null) {
                facet._settings.facetLabel = segment.forward ? property.getLabel() : property.getReverseLabel();
            }
        }
    }

    facet._cache = new Exhibit.FacetUtilities.Cache(
        facet.getUIContext().getDatabase(),
        facet.getUIContext().getCollection(),
        facet.getExpression()
    );

    facet._maxRange = facet._getMaxRange();
};

/**
 *
 */
Exhibit.SliderFacet.prototype._dispose = function() {
    this._cache.dispose();
    this._cache = null;
//  this._selection = null;
    this._range = null; //currently selected range
    this._maxRange = null; //total range of slider
};

/**
 * @returns {Boolean}
 */
Exhibit.SliderFacet.prototype.hasRestrictions = function() {
    return (this._range.min && this._range.min != this._maxRange.min) ||
           (this._range.max && this._range.max != this._maxRange.max);
};

/**
 *
 */
Exhibit.SliderFacet.prototype.clearAllRestrictions = function() {
    Exhibit.jQuery(this.getContainer()).trigger("onBeforeFacetReset.exhibit");
    this._range = this._maxRange;
    this._notifyCollection();
};

/**
 * @param {Exhibit.Set} items
 * @returns {Exhibit.Set}
 */
Exhibit.SliderFacet.prototype.restrict = function(items) {
    if (!this.hasRestrictions()) {
        return items;
    }

    var set = new Exhibit.Set();

    if (this.getExpression().isPath()){
        var path = this.getExpression().getPath();
        var database = this.getUIContext().getDatabase();
        set=path.rangeBackward(this._range.min, this._range.max, false, items, database).values;
    }
    else {
        this._buildRangeIndex();
        var rangeIndex=this._rangeIndex;
        set=rangeIndex.getSubjectsInRange(this._range.min, this._range.max, false, null, items);
    }

    if (this._showMissing){
        this._cache.getItemsMissingValue(items, set);
    }

    return set;
};

/**
 * @param {Exhibit.Set} items
 */
Exhibit.SliderFacet.prototype.update = function(items) {
    if (this._settings.histogram) {
        var data = [];
        var n = 75; //number of bars on histogram
        var range = (this._maxRange.max - this._maxRange.min)/n; //range represented by each bar
        var missingCount = 0;
        var database = this.getUIContext().getDatabase();

        if (this._selectMissing){
            missingCount = this._cache.getItemsMissingValue(items).size();
        }

        if (this.getExpression().isPath()){
            var path = this.getExpression().getPath();

            for (var i=0; i<n; i++) {
                data[i] = path.rangeBackward(this._maxRange.min+i*range, this._maxRange.min+(i+1)*range, (i+1) === n, items,database).values.size()+missingCount;
            }
        }

        else {
            this._buildRangeIndex();
            var rangeIndex=this._rangeIndex;

            for (var i=0; i<n; i++){
                data[i] = rangeIndex.getSubjectsInRange(this._maxRange.min+i*range, this._maxRange.min+(i+1)*range, (i+1) === n, null, items).size()+missingCount;
            }

        }
        this._slider.updateHistogram(data);
    }
    this._slider._setMin(this._range.min);
    this._slider._setMax(this._range.max);
};

/**
 * @private
 */
Exhibit.SliderFacet.prototype._initializeUI = function() {
    Exhibit.jQuery(this.getContainer()).empty();
    Exhibit.jQuery(this.getContainer()).addClass("exhibit-cloudFacet");

    var dom = Exhibit.jQuery.simileDOM(
        "string",
        this.getContainer(),
        ((typeof this._settings.facetLabel !== "undefined") ?
         (   "
" +
             "" + this.getLabel() + "" +
             "
"
         ) :
         ""
        ) +
            '

'
    );

    this._dom = dom;

    this._slider = new Exhibit.SliderFacet.slider(this._dom.slider, this, this._settings.precision, this._settings.horizontal);
};

/**
 * @private
 * @returns {Object}
 */
//gets maximum range? need to construct a range index for this...
Exhibit.SliderFacet.prototype._getMaxRange = function() {
    var rangeIndex;
    if (this.getExpression().isPath()){
        var path = this.getExpression().getPath();
        var database = this.getUIContext().getDatabase();
        var propertyID = path.getLastSegment().property;
        var property = database.getProperty(propertyID);
        rangeIndex = property.getRangeIndex();
    }
    else {
        this._buildRangeIndex();
        rangeIndex = this._rangeIndex;
    }

    return {min: rangeIndex.getMin(), max: rangeIndex.getMax()};
};

/**
 * @private
 */
Exhibit.SliderFacet.prototype._buildRangeIndex = function() {
    if (typeof this._rangeIndex === "undefined") {
        var expression = this.getExpression();
        var database = this.getUIContext().getDatabase();
        var getter = function(item, f) {
            expression.evaluateOnItem(item, database).values.visit(function(value) {
                if (typeof value != "number") {
                    value = parseFloat(value);
                }
                if (!isNaN(value)) {
                    f(value);
                }
            });
        };

        this._rangeIndex = new Exhibit.Database.RangeIndex(
            this.getUIContext().getCollection().getAllItems(),
            getter
        );
    }
};

/**
 * Used by the actual slider to set the facet values
 */
Exhibit.SliderFacet.prototype.changeRange = function(range) {
    Exhibit.History.pushComponentState(
        this,
        Exhibit.Facet.getRegistryKey(),
        range,
        Exhibit._("%facets.numeric.rangeShort", range.min, range.max),
        true
    );
};

//clear
Exhibit.SliderFacet.prototype._notifyCollection = function() {
    this.getUIContext().getCollection().onFacetUpdated(this);
};

/**
 * @returns {Object}
 */
Exhibit.SliderFacet.prototype.exportEmptyState = function() {
    return {};
};

/**
 * @returns {Object}
 */
Exhibit.SliderFacet.prototype.exportState = function() {
    return this._range;
};

/**
 * @param {Object} state
 */
Exhibit.SliderFacet.prototype.importState = function(state) {
    if (this.stateDiffers(state)) {
        if (typeof state.min === 'undefined' || state.min === null) {
            this._range.min = this._maxRange.min;
        }
        else {
            this._range.min = state.min;
        }
        this._slider._setMin(this._range.min);
        if (typeof state.max === 'undefined' || state.max === null) {
            this._range.max = this._maxRange.max;
        }
        else {
            this._range.max = state.max;
        }
        this._slider._setMax(this._range.max);
    }
    this._notifyCollection();
};

/**
 * @param {Object} state
 */
Exhibit.SliderFacet.prototype.stateDiffers = function(state) {
    if (typeof state.min === 'undefined') {
        if (this._range.min && this._range.min != this._maxRange.min) {
            return true;
        }
    }
    else {
        if (this._range.min !== state.min) {
            return true;
        }
    }
    if (typeof state.max === 'undefined') {
        if (this._range.max && this._range.max != this._maxRange.max) {
            return true;
        }
    }
    else {
        if (this._range.max !== state.min) {
            return true;
        }
    }
    return false;
};
<|endoftext|>


<commit_before>import React, { PropTypes, Component } from 'react';
import Box from 'grommet/components/Box';
import Image from 'grommet/components/Image';
import Tiles from 'grommet/components/Tiles';
import Tile from 'grommet/components/Tile';

export default class ImageGallery extends Component {
  render() {
    const {
      images,
      currentIndex,
      imageSize,
    } = this.props;
    const size = imageSize.toLowerCase();
    return (
      <Box align="center" justify="center" direction="column">
        <Box
          size={{ height: size, width: size }}
          align="center"
          justify="center"
        >
          <Image size={size} src={images[currentIndex].path} />
        </Box>
        <Tiles pad="none" flush={false}>
          {images && images.map((image, i) =>
            <Tile
              onClick={() => this.handleClick(i)} key={i}
              style={{ border: i === currentIndex ? '.2em solid #01a982' : '' }}
            >
              <Image size="thumb" src={image.path} />
            </Tile>,
          )}
        </Tiles>
      </Box>
    );
  }
}

ImageGallery.propTypes = {
  images: PropTypes.arrayOf(
    PropTypes.shape({
      path: PropTypes.string,
    }),
  ),
  currentIndex: PropTypes.number.isRequired,
  imageSize: PropTypes.oneOf(['small' | 'medium' | 'large' | 'xlarge']),
  onClickItem: PropTypes.func.isRequired,
};
<commit_msg>Fix: remove elementwise operator from image gallery proptypes<commit_after>import React, { PropTypes, Component } from 'react';
import Box from 'grommet/components/Box';
import Image from 'grommet/components/Image';
import Tiles from 'grommet/components/Tiles';
import Tile from 'grommet/components/Tile';

export default class ImageGallery extends Component {
  render() {
    const {
      images,
      currentIndex,
      imageSize,
    } = this.props;
    const size = imageSize.toLowerCase();
    return (
      <Box align="center" justify="center" direction="column">
        <Box
          size={{ height: size, width: size }}
          align="center"
          justify="center"
        >
          <Image size={size} src={images[currentIndex].path} />
        </Box>
        <Tiles pad="none" flush={false}>
          {images && images.map((image, i) =>
            <Tile
              onClick={() => this.handleClick(i)} key={i}
              style={{ border: i === currentIndex ? '.2em solid #01a982' : '' }}
            >
              <Image size="thumb" src={image.path} />
            </Tile>,
          )}
        </Tiles>
      </Box>
    );
  }
}

ImageGallery.propTypes = {
  images: PropTypes.arrayOf(
    PropTypes.shape({
      path: PropTypes.string,
    }),
  ),
  currentIndex: PropTypes.number.isRequired,
  imageSize: PropTypes.oneOf(['small', 'medium', 'large', 'xlarge']),
};
<|endoftext|>


<commit_before>// @flow

//
// INTEL CONFIDENTIAL
//
// Copyright 2013-2016 Intel Corporation All Rights Reserved.
//
// The source code contained or described herein and all documents related
// to the source code ("Material") are owned by Intel Corporation or its
// suppliers or licensors. Title to the Material remains with Intel Corporation
// or its suppliers and licensors. The Material contains trade secrets and
// proprietary and confidential information of Intel or its suppliers and
// licensors. The Material is protected by worldwide copyright and trade secret
// laws and treaty provisions. No part of the Material may be used, copied,
// reproduced, modified, published, uploaded, posted, transmitted, distributed,
// or disclosed in any way without Intel's prior express written permission.
//
// No license under any patent, copyright, trade secret or other intellectual
// property right is granted to or conferred upon you by disclosure or delivery
// of the Materials, either expressly, by implication, inducement, estoppel or
// otherwise. Any license under such intellectual property rights must be
// express and approved by Intel in writing.

import store from '../store/get-store.js';

import {
  setDuration,
  setSort
} from './job-stats-actions.js';

import type {
  HighlandStreamT
} from 'highland';

import type {
  $scopeT
} from 'angular';

import type {
  StateServiceT
} from 'angular-ui-router';

import type {
  localApplyT
} from '../extend-scope-module.js';

type jobStatsConfigT = {
  duration:number,
  orderBy:string,
  desc:boolean
};

export default {
  bindings: {
    stats$: '<'
  },
  controller: function ($state:StateServiceT, $stateParams:{id?:number}, $scope:$scopeT, localApply:localApplyT) {
    'ngInject';

    type T = (jobStatsConfigT & {
      noId:boolean,
      setDuration:(d:number) => void,
      shouldShow:(n:string, isDesc:boolean) => boolean,
      getClass:(n:string) => string,
      sortProp:(n:string) => void,
      $onDestroy:() => void,
      stats$:HighlandStreamT<any>
    });

    const that:T = this;

    Object.assign(that, {
      noId: $stateParams.id == null,
      setDuration (duration:number) {
        store
          .dispatch(
            setDuration(duration)
          );

        $state.reload('app.jobstats');
      },
      shouldShow (name:string, isDesc:boolean) {
        return that.orderBy === name && that.desc === isDesc;
      },
      getClass (name:string):string {
        if (name !== that.orderBy)
          return '';
        else if (that.desc)
          return 'fa-sort-desc';
        else
          return 'fa-sort-asc';
      },
      sortProp (name:string) {
        if (name === that.orderBy)
          store
            .dispatch(
              setSort(name, !that.desc)
            );
        else
          store
            .dispatch(
              setSort(name, true)
            );
      },
      $onDestroy () {
        that.stats$.destroy();
        config$.destroy();
      }
    });

    const config$:HighlandStreamT<jobStatsConfigT> = store
      .select('jobStatsConfig');

    config$
      .each(c => {
        Object.assign(that, c);
        localApply($scope);
      });
  },
  template: `

          Jobstats not found.

          Please ensure you have enabled jobstats.
          Refer to this help page
          for more information.

 0">

Top Jobs

        <form>

            Select Duration

              1 minute
              5 minutes
              10 minutes

        </form>

                  Job

                  read MB

                  write MB

                  Read IOPS

                Write IOPS

                {{x.id}}

                {{ x.read_bytes | throughput }}

                {{ x.write_bytes | throughput }}

                {{ x.read_iops | round:3 }}

                {{ x.write_iops | round:3 }}

  `
};
<commit_msg>fixup job-stats title<commit_after>// @flow

//
// INTEL CONFIDENTIAL
//
// Copyright 2013-2016 Intel Corporation All Rights Reserved.
//
// The source code contained or described herein and all documents related
// to the source code ("Material") are owned by Intel Corporation or its
// suppliers or licensors. Title to the Material remains with Intel Corporation
// or its suppliers and licensors. The Material contains trade secrets and
// proprietary and confidential information of Intel or its suppliers and
// licensors. The Material is protected by worldwide copyright and trade secret
// laws and treaty provisions. No part of the Material may be used, copied,
// reproduced, modified, published, uploaded, posted, transmitted, distributed,
// or disclosed in any way without Intel's prior express written permission.
//
// No license under any patent, copyright, trade secret or other intellectual
// property right is granted to or conferred upon you by disclosure or delivery
// of the Materials, either expressly, by implication, inducement, estoppel or
// otherwise. Any license under such intellectual property rights must be
// express and approved by Intel in writing.

import store from '../store/get-store.js';

import {
  setDuration,
  setSort
} from './job-stats-actions.js';

import type {
  HighlandStreamT
} from 'highland';

import type {
  $scopeT
} from 'angular';

import type {
  StateServiceT
} from 'angular-ui-router';

import type {
  localApplyT
} from '../extend-scope-module.js';

type jobStatsConfigT = {
  duration:number,
  orderBy:string,
  desc:boolean
};

export default {
  bindings: {
    stats$: '<'
  },
  controller: function ($state:StateServiceT, $stateParams:{id?:number}, $scope:$scopeT, localApply:localApplyT) {
    'ngInject';

    type T = (jobStatsConfigT & {
      noId:boolean,
      setDuration:(d:number) => void,
      shouldShow:(n:string, isDesc:boolean) => boolean,
      getClass:(n:string) => string,
      sortProp:(n:string) => void,
      $onDestroy:() => void,
      stats$:HighlandStreamT<any>
    });

    const that:T = this;

    Object.assign(that, {
      noId: $stateParams.id == null,
      setDuration (duration:number) {
        store
          .dispatch(
            setDuration(duration)
          );

        $state.reload('app.jobstats');
      },
      shouldShow (name:string, isDesc:boolean) {
        return that.orderBy === name && that.desc === isDesc;
      },
      getClass (name:string):string {
        if (name !== that.orderBy)
          return '';
        else if (that.desc)
          return 'fa-sort-desc';
        else
          return 'fa-sort-asc';
      },
      sortProp (name:string) {
        if (name === that.orderBy)
          store
            .dispatch(
              setSort(name, !that.desc)
            );
        else
          store
            .dispatch(
              setSort(name, true)
            );
      },
      $onDestroy () {
        that.stats$.destroy();
        config$.destroy();
      }
    });

    const config$:HighlandStreamT<jobStatsConfigT> = store
      .select('jobStatsConfig');

    config$
      .each(c => {
        Object.assign(that, c);
        localApply($scope);
      });
  },
  template: `

          Jobstats not found.

          Please ensure you have enabled jobstats.
          Refer to this help page
          for more information.

 0">

Top Jobs

        <form>

            Select Duration

              1 minute
              5 minutes
              10 minutes

        </form>

                  Job

                  read Bandwidth

                  write Bandwidth

                  Read IOPS

                Write IOPS

                {{x.id}}

                {{ x.read_bytes | throughput }}

                {{ x.write_bytes | throughput }}

                {{ x.read_iops | round:3 }}

                {{ x.write_iops | round:3 }}

  `
};
<|endoftext|>