<commit_before>const objPrototype = Object.prototype;
const {hasOwnProperty} = objPrototype;

export function hasOwn(obj, key) {
    return hasOwnProperty.call(obj, key);
}

const hyphenateCache = {};
const hyphenateRe = /([a-z\d])([A-Z])/g;

export function hyphenate(str) {

    if (!(str in hyphenateCache)) {
        hyphenateCache[str] = str
            .replace(hyphenateRe, '$1-$2')
            .toLowerCase();
    }

    return hyphenateCache[str];
}

const camelizeRe = /-(\w)/g;

export function camelize(str) {
    return str.replace(camelizeRe, toUpper);
}

function toUpper(_, c) {
    return c ? c.toUpperCase() : '';
}

export function ucfirst(str) {
    return str.length ? toUpper(null, str.charAt(0)) + str.slice(1) : '';
}

const strPrototype = String.prototype;
const startsWithFn = strPrototype.startsWith || function (search) { return this.lastIndexOf(search, 0) === 0; };

export function startsWith(str, search) {
    return startsWithFn.call(str, search);
}

const endsWithFn = strPrototype.endsWith || function (search) { return this.substr(-search.length) === search; };

export function endsWith(str, search) {
    return endsWithFn.call(str, search);
}

const arrPrototype = Array.prototype;

const includesFn = function (search, i) { return !!~this.indexOf(search, i); };
const includesStr = strPrototype.includes || includesFn;
const includesArray = arrPrototype.includes || includesFn;

export function includes(obj, search) {
    return obj && (isString(obj) ? includesStr : includesArray).call(obj, search);
}

const findIndexFn = arrPrototype.findIndex || function (predicate) {
    for (let i = 0; i < this.length; i++) {
        if (predicate.call(arguments[1], this[i], i, this)) {
            return i;
        }
    }
    return -1;
};

export function findIndex(array, predicate) {
    return findIndexFn.call(array, predicate);
}

export const {isArray} = Array;

export function isFunction(obj) {
    return typeof obj === 'function';
}

export function isObject(obj) {
    return obj !== null && typeof obj === 'object';
}

const {toString} = objPrototype;
export function isPlainObject(obj) {
    return toString.call(obj) === '[object Object]';
}

export function isWindow(obj) {
    return isObject(obj) && obj === obj.window;
}

export function isDocument(obj) {
    return isObject(obj) && obj.nodeType === 9;
}

export function isNode(obj) {
    return isObject(obj) && obj.nodeType >= 1;
}

export function isElement(obj) {
    return isObject(obj) && obj.nodeType === 1;
}

export function isBoolean(value) {
    return typeof value === 'boolean';
}

export function isString(value) {
    return typeof value === 'string';
}

export function isNumber(value) {
    return typeof value === 'number';
}

export function isNumeric(value) {
    return isNumber(value) || isString(value) && !isNaN(value - parseFloat(value));
}

export function isEmpty(obj) {
    return !(isArray(obj)
        ? obj.length
        : isObject(obj)
            ? Object.keys(obj).length
            : false
    );
}

export function isUndefined(value) {
    return value === void 0;
}

export function toBoolean(value) {
    return isBoolean(value)
        ? value
        : value === 'true' || value === '1' || value === ''
            ? true
            : value === 'false' || value === '0'
                ? false
                : value;
}

export function toNumber(value) {
    const number = Number(value);
    return !isNaN(number) ? number : false;
}

export function toFloat(value) {
    return parseFloat(value) || 0;
}

export const toArray = Array.from || (value => arrPrototype.slice.call(value));

export function toNode(element) {
    return toNodes(element)[0];
}

export function toNodes(element) {
    return element && (isNode(element) ? [element] : toArray(element).filter(isNode)) || [];
}

export function toWindow(element) {
    if (isWindow(element)) {
        return element;
    }

    element = toNode(element);

    return element
        ? (isDocument(element)
            ? element
            : element.ownerDocument
        ).defaultView
        : window;
}

export function toMs(time) {
    return !time
        ? 0
        : endsWith(time, 'ms')
            ? toFloat(time)
            : toFloat(time) * 1000;
}

export function isEqual(value, other) {
    return value === other
        || isObject(value)
        && isObject(other)
        && Object.keys(value).length === Object.keys(other).length
        && each(value, (val, key) => val === other[key]);
}

export function swap(value, a, b) {
    return value.replace(
        new RegExp(`${a}|${b}`, 'g'),
        match => match === a ? b : a
    );
}

export const assign = Object.assign || function (target, ...args) {
    target = Object(target);
    for (let i = 0; i < args.length; i++) {
        const source = args[i];
        if (source !== null) {
            for (const key in source) {
                if (hasOwn(source, key)) {
                    target[key] = source[key];
                }
            }
        }
    }
    return target;
};

export function last(array) {
    return array[array.length - 1];
}

export function each(obj, cb) {
    for (const key in obj) {
        if (false === cb(obj[key], key)) {
            return false;
        }
    }
    return true;
}

export function sortBy(array, prop) {
    return array.slice().sort(({[prop]: propA = 0}, {[prop]: propB = 0}) =>
        propA > propB
            ? 1
            : propB > propA
                ? -1
                : 0
    );
}

export function uniqueBy(array, prop) {
    const seen = new Set();
    return array.filter(({[prop]: check}) => seen.has(check)
        ? false
        : seen.add(check) || true // IE 11 does not return the Set object
    );
}

export function clamp(number, min = 0, max = 1) {
    return Math.min(Math.max(toNumber(number) || 0, min), max);
}

export function noop() {}

export function intersectRect(...rects) {
    return [['bottom', 'top'], ['right', 'left']].every(([minProp, maxProp]) =>
        Math.min(...rects.map(({[minProp]: min}) => min)) - Math.max(...rects.map(({[maxProp]: max}) => max)) > 0
    );
}

export function pointInRect(point, rect) {
    return point.x <= rect.right &&
        point.x >= rect.left &&
        point.y <= rect.bottom &&
        point.y >= rect.top;
}

export const Dimensions = {

    ratio(dimensions, prop, value) {

        const aProp = prop === 'width' ? 'height' : 'width';

        return {
            [aProp]: dimensions[prop] ? Math.round(value * dimensions[aProp] / dimensions[prop]) : dimensions[aProp],
            [prop]: value
        };
    },

    contain(dimensions, maxDimensions) {
        dimensions = assign({}, dimensions);

        each(dimensions, (_, prop) => dimensions = dimensions[prop] > maxDimensions[prop]
            ? this.ratio(dimensions, prop, maxDimensions[prop])
            : dimensions
        );

        return dimensions;
    },

    cover(dimensions, maxDimensions) {
        dimensions = this.contain(dimensions, maxDimensions);

        each(dimensions, (_, prop) => dimensions = dimensions[prop] < maxDimensions[prop]
            ? this.ratio(dimensions, prop, maxDimensions[prop])
            : dimensions
        );

        return dimensions;
    }

};
<commit_msg>fix: ensure obj ist `global` object e.g. calling Array.from(window) creates [global]<commit_after>const objPrototype = Object.prototype;
const {hasOwnProperty} = objPrototype;

export function hasOwn(obj, key) {
    return hasOwnProperty.call(obj, key);
}

const hyphenateCache = {};
const hyphenateRe = /([a-z\d])([A-Z])/g;

export function hyphenate(str) {

    if (!(str in hyphenateCache)) {
        hyphenateCache[str] = str
            .replace(hyphenateRe, '$1-$2')
            .toLowerCase();
    }

    return hyphenateCache[str];
}

const camelizeRe = /-(\w)/g;

export function camelize(str) {
    return str.replace(camelizeRe, toUpper);
}

function toUpper(_, c) {
    return c ? c.toUpperCase() : '';
}

export function ucfirst(str) {
    return str.length ? toUpper(null, str.charAt(0)) + str.slice(1) : '';
}

const strPrototype = String.prototype;
const startsWithFn = strPrototype.startsWith || function (search) { return this.lastIndexOf(search, 0) === 0; };

export function startsWith(str, search) {
    return startsWithFn.call(str, search);
}

const endsWithFn = strPrototype.endsWith || function (search) { return this.substr(-search.length) === search; };

export function endsWith(str, search) {
    return endsWithFn.call(str, search);
}

const arrPrototype = Array.prototype;

const includesFn = function (search, i) { return !!~this.indexOf(search, i); };
const includesStr = strPrototype.includes || includesFn;
const includesArray = arrPrototype.includes || includesFn;

export function includes(obj, search) {
    return obj && (isString(obj) ? includesStr : includesArray).call(obj, search);
}

const findIndexFn = arrPrototype.findIndex || function (predicate) {
    for (let i = 0; i < this.length; i++) {
        if (predicate.call(arguments[1], this[i], i, this)) {
            return i;
        }
    }
    return -1;
};

export function findIndex(array, predicate) {
    return findIndexFn.call(array, predicate);
}

export const {isArray} = Array;

export function isFunction(obj) {
    return typeof obj === 'function';
}

export function isObject(obj) {
    return obj !== null && typeof obj === 'object';
}

const {toString} = objPrototype;
export function isPlainObject(obj) {
    return toString.call(obj) === '[object Object]';
}

export function isWindow(obj) {
    return isObject(obj) && obj === obj.window;
}

export function isDocument(obj) {
    return nodeType(obj) === 9;
}

export function isNode(obj) {
    return nodeType(obj) >= 1;
}

export function isElement(obj) {
    return nodeType(obj) === 1;
}

function nodeType(obj) {
    return !isWindow(obj) && isObject(obj) && obj.nodeType;
}

export function isBoolean(value) {
    return typeof value === 'boolean';
}

export function isString(value) {
    return typeof value === 'string';
}

export function isNumber(value) {
    return typeof value === 'number';
}

export function isNumeric(value) {
    return isNumber(value) || isString(value) && !isNaN(value - parseFloat(value));
}

export function isEmpty(obj) {
    return !(isArray(obj)
        ? obj.length
        : isObject(obj)
            ? Object.keys(obj).length
            : false
    );
}

export function isUndefined(value) {
    return value === void 0;
}

export function toBoolean(value) {
    return isBoolean(value)
        ? value
        : value === 'true' || value === '1' || value === ''
            ? true
            : value === 'false' || value === '0'
                ? false
                : value;
}

export function toNumber(value) {
    const number = Number(value);
    return !isNaN(number) ? number : false;
}

export function toFloat(value) {
    return parseFloat(value) || 0;
}

export const toArray = Array.from || (value => arrPrototype.slice.call(value));

export function toNode(element) {
    return toNodes(element)[0];
}

export function toNodes(element) {
    return element && (isNode(element) ? [element] : toArray(element).filter(isNode)) || [];
}

export function toWindow(element) {
    if (isWindow(element)) {
        return element;
    }

    element = toNode(element);

    return element
        ? (isDocument(element)
            ? element
            : element.ownerDocument
        ).defaultView
        : window;
}

export function toMs(time) {
    return !time
        ? 0
        : endsWith(time, 'ms')
            ? toFloat(time)
            : toFloat(time) * 1000;
}

export function isEqual(value, other) {
    return value === other
        || isObject(value)
        && isObject(other)
        && Object.keys(value).length === Object.keys(other).length
        && each(value, (val, key) => val === other[key]);
}

export function swap(value, a, b) {
    return value.replace(
        new RegExp(`${a}|${b}`, 'g'),
        match => match === a ? b : a
    );
}

export const assign = Object.assign || function (target, ...args) {
    target = Object(target);
    for (let i = 0; i < args.length; i++) {
        const source = args[i];
        if (source !== null) {
            for (const key in source) {
                if (hasOwn(source, key)) {
                    target[key] = source[key];
                }
            }
        }
    }
    return target;
};

export function last(array) {
    return array[array.length - 1];
}

export function each(obj, cb) {
    for (const key in obj) {
        if (false === cb(obj[key], key)) {
            return false;
        }
    }
    return true;
}

export function sortBy(array, prop) {
    return array.slice().sort(({[prop]: propA = 0}, {[prop]: propB = 0}) =>
        propA > propB
            ? 1
            : propB > propA
                ? -1
                : 0
    );
}

export function uniqueBy(array, prop) {
    const seen = new Set();
    return array.filter(({[prop]: check}) => seen.has(check)
        ? false
        : seen.add(check) || true // IE 11 does not return the Set object
    );
}

export function clamp(number, min = 0, max = 1) {
    return Math.min(Math.max(toNumber(number) || 0, min), max);
}

export function noop() {}

export function intersectRect(...rects) {
    return [['bottom', 'top'], ['right', 'left']].every(([minProp, maxProp]) =>
        Math.min(...rects.map(({[minProp]: min}) => min)) - Math.max(...rects.map(({[maxProp]: max}) => max)) > 0
    );
}

export function pointInRect(point, rect) {
    return point.x <= rect.right &&
        point.x >= rect.left &&
        point.y <= rect.bottom &&
        point.y >= rect.top;
}

export const Dimensions = {

    ratio(dimensions, prop, value) {

        const aProp = prop === 'width' ? 'height' : 'width';

        return {
            [aProp]: dimensions[prop] ? Math.round(value * dimensions[aProp] / dimensions[prop]) : dimensions[aProp],
            [prop]: value
        };
    },

    contain(dimensions, maxDimensions) {
        dimensions = assign({}, dimensions);

        each(dimensions, (_, prop) => dimensions = dimensions[prop] > maxDimensions[prop]
            ? this.ratio(dimensions, prop, maxDimensions[prop])
            : dimensions
        );

        return dimensions;
    },

    cover(dimensions, maxDimensions) {
        dimensions = this.contain(dimensions, maxDimensions);

        each(dimensions, (_, prop) => dimensions = dimensions[prop] < maxDimensions[prop]
            ? this.ratio(dimensions, prop, maxDimensions[prop])
            : dimensions
        );

        return dimensions;
    }

};
<|endoftext|>


<commit_before>'use strict'
module.exports = filenameize

function filenameize (str) {
  return str.replace(/\W/g, '-').replace(/--+/g, '-').replace(/^-|-$/, '').toLowerCase()
}
<commit_msg>Ooops, remove all the supurfluous dashes<commit_after>'use strict'
module.exports = filenameize

function filenameize (str) {
  return str.replace(/\W/g, '-').replace(/--+/g, '-').replace(/^-|-$/g, '').toLowerCase()
}
<|endoftext|>


<commit_before>/**
 * Trim a string, removing leading and trailing whitespace
 * @param  {string} input
 * @return {string} trimmed string
 */
PolymerExpressions.prototype.trim = function(input){
	return input.replace(/^\s*|\s*$/g, '');
}<commit_msg>Add check to ensure trim does not error<commit_after>/**
 * Trim a string, removing leading and trailing whitespace
 * @param  {string} input
 * @return {string} trimmed string
 */
PolymerExpressions.prototype.trim = function(input){
  return input && input.replace(/^\s*|\s*$/g, '');
}
<|endoftext|>


<commit_before>import React, { PropTypes, Component } from 'react'
import { Text, View, StyleSheet, Animated, Easing, PanResponder } from 'react-native'

import Icon from 'react-native-vector-icons/MaterialIcons'

// import shallowCompare from 'react-addons-shallow-compare';
// import styleEqual from 'style-equal'

const TRACK_SIZE = 4
const THUMB_SIZE = 20

var DEFAULT_ANIMATION_CONFIGS = {
  spring : {
    friction : 7,
    tension  : 100
  },
  timing : {
    duration : 150,
    easing   : Easing.inOut(Easing.ease),
    delay    : 0
  },
}

function Rect(x, y, width, height) {
  this.x = x;
  this.y = y;
  this.width = width;
  this.height = height;
}

Rect.prototype.containsPoint = function(x, y) {
  return (x >= this.x
    && y >= this.y
    && x <= this.x + this.width
    && y <= this.y + this.height)
}

export default class Slider extends Component {
  constructor () {
    super()
    this.state = {
      containerSize: {width: 0, height: 0},
      trackSize: {width: 0, height: 0},
      thumbSize: {width: 0, height: 0},
      allMeasured: false,
      value: new Animated.Value(0.2),
    }
  }

  componentWillMount() {
    this.panResponder = PanResponder.create({
      onStartShouldSetPanResponder: this.handleStartShouldSetPanResponder.bind(this),
      onMoveShouldSetPanResponder: this.handleMoveShouldSetPanResponder.bind(this),
      onPanResponderGrant: this.handlePanResponderGrant.bind(this),
      onPanResponderMove: this.handlePanResponderMove.bind(this),
      onPanResponderRelease: this.handlePanResponderEnd.bind(this),
      onPanResponderTerminationRequest: this.handlePanResponderRequestEnd.bind(this),
      onPanResponderTerminate: this.handlePanResponderEnd.bind(this),
    });
  }

  componentWillReceiveProps(nextProps) {
    var newValue = nextProps.value;

    if (this.props.value !== newValue) {
      if (this.props.animateTransitions) {
        this.setCurrentValueAnimated(newValue);
      }
      else {
        this.setCurrentValue(newValue);
      }
    }
  }

  // shouldComponentUpdate(nextProps, nextState) {
  //   // We don't want to re-render in the following cases:
  //   // - when only the 'value' prop changes as it's already handled with the Animated.Value
  //   // - when the event handlers change (rendering doesn't depend on them)
  //   // - when the style props haven't actually change
  //
  //   return shallowCompare(
  //     { props: this._getPropsForComponentUpdate(this.props), state: this.state },
  //     this._getPropsForComponentUpdate(nextProps),
  //     nextState
  //   ) || !styleEqual(this.props.style, nextProps.style)
  //     || !styleEqual(this.props.trackStyle, nextProps.trackStyle)
  //     || !styleEqual(this.props.thumbStyle, nextProps.thumbStyle);
  // }
  //
  // _getPropsForComponentUpdate(props) {
  //   var {
  //     value,
  //     onValueChange,
  //     onSlidingStart,
  //     onSlidingComplete,
  //     style,
  //     trackStyle,
  //     thumbStyle,
  //     ...otherProps,
  //   } = props;
  //
  //   return otherProps;
  // }

  setCurrentValue(value) {
    this.state.value.setValue(value);
  }

  setCurrentValueAnimated(value) {
    var animationType = this.props.animationType;
    var animationConfig = Object.assign( {},
      DEFAULT_ANIMATION_CONFIGS[animationType],
      this.props.animationConfig,
      {
        toValue : value
      }
    );

    Animated[animationType](this.state.value, animationConfig).start();
  }

  handleMoveShouldSetPanResponder(/*e: Object, gestureState: Object*/){
    // Should we become active when the user moves a touch over the thumb?
    return false;
  }

  handlePanResponderGrant(/*e: Object, gestureState: Object*/) {
    this._previousLeft = this.getThumbLeft(this.getCurrentValue());
    this.fireChangeEvent('onSlidingStart');
  }

  handlePanResponderMove(e, gestureState) {
    if (this.props.disabled) {
      return;
    }

    this.setCurrentValue(this.getValue(gestureState));
    this.fireChangeEvent('onValueChange');
  }

  handlePanResponderRequestEnd(e, gestureState) {
    // Should we allow another component to take over this pan?
    return false;
  }

  handlePanResponderEnd(e, gestureState) {
    if (this.props.disabled) {
      return;
    }

    this.setCurrentValue(this.getValue(gestureState));
    this.fireChangeEvent('onSlidingComplete');
  }

  thumbHitTest(e) {
    var nativeEvent = e.nativeEvent;
    var thumbTouchRect = this.getThumbTouchRect();
    return thumbTouchRect.containsPoint(nativeEvent.locationX, nativeEvent.locationY);
  }

  handleStartShouldSetPanResponder(e, /*gestureState: Object*/) {
    // Should we become active when the user presses down on the thumb?
    return this.thumbHitTest(e);
  }

  fireChangeEvent(event) {
    if (this.props[event]) {
      this.props[event](this.getCurrentValue());
    }
  }

  getTouchOverflowSize() {
    var state = this.state;
    var props = this.props;

    var size = {};
    if (state.allMeasured === true) {
      size.width = Math.max(0, props.thumbTouchSize.width - state.thumbSize.width);
      size.height = Math.max(0, props.thumbTouchSize.height - state.containerSize.height);
    }

    return size;
  }

  getTouchOverflowStyle() {
    var { width, height } = this.getTouchOverflowSize();

    var touchOverflowStyle = {};
    if (width !== undefined && height !== undefined) {
      var verticalMargin = -height / 2;
      touchOverflowStyle.marginTop = verticalMargin;
      touchOverflowStyle.marginBottom = verticalMargin;

      var horizontalMargin = -width / 2;
      touchOverflowStyle.marginLeft = horizontalMargin;
      touchOverflowStyle.marginRight = horizontalMargin;
    }

    if (this.props.debugTouchArea === true) {
      touchOverflowStyle.backgroundColor = 'orange';
      touchOverflowStyle.opacity = 0.5;
    }

    return touchOverflowStyle;
  }

  handleMeasure(name, x) {
    var { width, height } = x.nativeEvent.layout;
    var size = {width: width, height: height};

    var storeName = `_${name}`;
    var currentSize = this[storeName];
    if (currentSize && width === currentSize.width && height === currentSize.height) {
      return;
    }
    this[storeName] = size;

    if (this._containerSize && this._trackSize && this._thumbSize) {
      this.setState({
        containerSize: this._containerSize,
        trackSize: this._trackSize,
        thumbSize: this._thumbSize,
        allMeasured: true,
      })
    }
  }

  measureContainer(x) {
    this.handleMeasure('containerSize', x);
  }

  measureTrack(x) {
    this.handleMeasure('trackSize', x);
  }

  measureThumb(x) {
    this.handleMeasure('thumbSize', x);
  }

  getValue(gestureState) {
    var length = this.state.containerSize.width - this.state.thumbSize.width;
    var thumbLeft = this._previousLeft + gestureState.dx;

    var ratio = thumbLeft / length;

    if (this.props.step) {
      return Math.max(this.props.minimumValue,
        Math.min(this.props.maximumValue,
          this.props.minimumValue + Math.round(ratio * (this.props.maximumValue - this.props.minimumValue) / this.props.step) * this.props.step
        )
      );
    } else {
      return Math.max(this.props.minimumValue,
        Math.min(this.props.maximumValue,
          ratio * (this.props.maximumValue - this.props.minimumValue) + this.props.minimumValue
        )
      );
    }
  }

  getCurrentValue() {
    return this.state.value.__getValue();
  }

  setCurrentValue(value) {
    this.state.value.setValue(value);
  }

  getRatio(value) {
    return (value - this.props.minimumValue) / (this.props.maximumValue - this.props.minimumValue);
  }

  getThumbLeft(value) {
    var ratio = this.getRatio(value);
    return ratio * (this.state.containerSize.width - this.state.thumbSize.width);
  }

  getThumbTouchRect() {
    var state = this.state;
    var props = this.props;
    var touchOverflowSize = this.getTouchOverflowSize();

    return new Rect(
      touchOverflowSize.width / 2 + this.getThumbLeft(this.getCurrentValue()) + (state.thumbSize.width - props.thumbTouchSize.width) / 2,
      touchOverflowSize.height / 2 + (state.containerSize.height - props.thumbTouchSize.height) / 2,
      props.thumbTouchSize.width,
      props.thumbTouchSize.height
    );
  }

  renderDebugThumbTouchRect(thumbLeft) {
    var thumbTouchRect = this.getThumbTouchRect();
    var positionStyle = {
      left: thumbLeft,
      top: thumbTouchRect.y,
      width: thumbTouchRect.width,
      height: thumbTouchRect.height,
    };

    return (
      <Animated.View
        style={[defaultStyles.debugThumbTouchArea, positionStyle]}
        pointerEvents='none'
      />
    );
  }

  render () {
    const {
      minimumValue,
      maximumValue,
      minimumTrackTintColor,
      maximumTrackTintColor,
      thumbTintColor,
      containerStyle,
      style,
      trackStyle,
      thumbStyle,
      debugTouchArea,
      ...other
    } = this.props

    var { value, containerSize, trackSize, thumbSize, allMeasured} = this.state

    var mainStyles = containerStyle || styles
    var thumbLeft = value.interpolate({
        inputRange: [minimumValue, maximumValue],
        outputRange: [0, containerSize.width - thumbSize.width],
        //extrapolate: 'clamp',
      })

    var valueVisibleStyle = {}
    if (!allMeasured) {
      valueVisibleStyle.opacity = 0;
    }

    var minimumTrackStyle = {
      position: 'absolute',
      width: Animated.add(thumbLeft, thumbSize.width / 2),
      marginTop: -trackSize.height,
      backgroundColor: minimumTrackTintColor,
      ...valueVisibleStyle
    }

    var touchOverflowStyle = this.getTouchOverflowStyle();

    return (
      <View {...other} style={[mainStyles.container, style]} onLayout={this.measureContainer.bind(this)}>
        <View
          style={[{backgroundColor: maximumTrackTintColor,}, mainStyles.track, trackStyle]}
          onLayout={this.measureTrack.bind(this)} />
        <Animated.View style={[mainStyles.track, trackStyle, minimumTrackStyle]} />
        <Animated.View
          onLayout={this.measureThumb.bind(this)}
          style={[
            {backgroundColor: thumbTintColor},
            mainStyles.thumb, thumbStyle,
            {
              transform: [
                { translateX: thumbLeft },
                { translateY: -(trackSize.height + thumbSize.height) / 2 }
              ],
              ...valueVisibleStyle
            }
          ]}
        />
        <View
          style={[styles.touchArea, touchOverflowStyle]}
          {...this.panResponder.panHandlers}>
          {debugTouchArea === true && this.renderDebugThumbTouchRect(thumbLeft)}
        </View>
      </View>
    )
  }
}

Slider.propTypes = {
  /**
   * Initial value of the slider. The value should be between minimumValue
   * and maximumValue, which default to 0 and 1 respectively.
   * Default value is 0.
   *
   * *This is not a controlled component*, e.g. if you don't update
   * the value, the component won't be reset to its inital value.
   */
  value: PropTypes.number,

  /**
   * If true the user won't be able to move the slider.
   * Default value is false.
   */
  disabled: PropTypes.bool,

  /**
   * Initial minimum value of the slider. Default value is 0.
   */
  minimumValue: PropTypes.number,

  /**
   * Initial maximum value of the slider. Default value is 1.
   */
  maximumValue: PropTypes.number,

  /**
   * Step value of the slider. The value should be between 0 and
   * (maximumValue - minimumValue). Default value is 0.
   */
  step: PropTypes.number,

  /**
   * The color used for the track to the left of the button. Overrides the
   * default blue gradient image.
   */
  minimumTrackTintColor: PropTypes.string,

  /**
   * The color used for the track to the right of the button. Overrides the
   * default blue gradient image.
   */
  maximumTrackTintColor: PropTypes.string,

  /**
   * The color used for the thumb.
   */
  thumbTintColor: PropTypes.string,

  /**
   * The size of the touch area that allows moving the thumb.
   * The touch area has the same center has the visible thumb.
   * This allows to have a visually small thumb while still allowing the user
   * to move it easily.
   * The default is {width: 40, height: 40}.
   */
  thumbTouchSize: PropTypes.shape(
    {width: PropTypes.number, height: PropTypes.number}
  ),

  /**
   * Callback continuously called while the user is dragging the slider.
   */
  onValueChange: PropTypes.func,

  /**
   * Callback called when the user starts changing the value (e.g. when
   * the slider is pressed).
   */
  onSlidingStart: PropTypes.func,

  /**
   * Callback called when the user finishes changing the value (e.g. when
   * the slider is released).
   */
  onSlidingComplete: PropTypes.func,

  /**
   * The style applied to the slider container.
   */
  style: View.propTypes.style,

  /**
   * The style applied to the track.
   */
  trackStyle: View.propTypes.style,

  /**
   * The style applied to the thumb.
   */
  thumbStyle: View.propTypes.style,

  /**
   * Set this to true to visually see the thumb touch rect in green.
   */
  debugTouchArea: PropTypes.bool,

  /**
  * Set to true to animate values with default 'timing' animation type
  */
  animateTransitions : PropTypes.bool,

  /**
  * Custom Animation type. 'spring' or 'timing'.
  */
  animationType : PropTypes.oneOf(['spring', 'timing']),

  /**
  * Used to configure the animation parameters.  These are the same parameters in the Animated library.
  */
  animationConfig : PropTypes.object,
}

Slider.defaultProps = {
  value: 0,
  minimumValue: 0,
  maximumValue: 1,
  step: 0,
  minimumTrackTintColor: '#3f3f3f',
  maximumTrackTintColor: '#b3b3b3',
  thumbTintColor: 'red',
  thumbTouchSize: { width: 40, height: 40 },
  debugTouchArea: false,
  animationType: 'timing'
}

const styles = StyleSheet.create({
  container: {
    height: 40,
    justifyContent: 'center',
  },
  track: {
    height: TRACK_SIZE,
    borderRadius: TRACK_SIZE / 2,
    marginTop: -4
  },
  thumb: {
    position: 'absolute',
    width: THUMB_SIZE,
    height: THUMB_SIZE,
    borderRadius: THUMB_SIZE / 2,
  },
  touchArea: {
    position: 'absolute',
    backgroundColor: 'transparent',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
  },
  debugThumbTouchArea: {
    position: 'absolute',
    backgroundColor: 'green',
    opacity: 0.5,
  }
})
<commit_msg>Fixed Slider's value is not initialized to 0<commit_after>import React, { PropTypes, Component } from 'react'
import { Text, View, StyleSheet, Animated, Easing, PanResponder } from 'react-native'

import Icon from 'react-native-vector-icons/MaterialIcons'

// import shallowCompare from 'react-addons-shallow-compare';
// import styleEqual from 'style-equal'

const TRACK_SIZE = 4
const THUMB_SIZE = 20

var DEFAULT_ANIMATION_CONFIGS = {
  spring : {
    friction : 7,
    tension  : 100
  },
  timing : {
    duration : 150,
    easing   : Easing.inOut(Easing.ease),
    delay    : 0
  },
}

function Rect(x, y, width, height) {
  this.x = x;
  this.y = y;
  this.width = width;
  this.height = height;
}

Rect.prototype.containsPoint = function(x, y) {
  return (x >= this.x
    && y >= this.y
    && x <= this.x + this.width
    && y <= this.y + this.height)
}

export default class Slider extends Component {
  constructor () {
    super()
    this.state = {
      containerSize: {width: 0, height: 0},
      trackSize: {width: 0, height: 0},
      thumbSize: {width: 0, height: 0},
      allMeasured: false,
      value: new Animated.Value(0),
    }
  }

  componentWillMount() {
    this.panResponder = PanResponder.create({
      onStartShouldSetPanResponder: this.handleStartShouldSetPanResponder.bind(this),
      onMoveShouldSetPanResponder: this.handleMoveShouldSetPanResponder.bind(this),
      onPanResponderGrant: this.handlePanResponderGrant.bind(this),
      onPanResponderMove: this.handlePanResponderMove.bind(this),
      onPanResponderRelease: this.handlePanResponderEnd.bind(this),
      onPanResponderTerminationRequest: this.handlePanResponderRequestEnd.bind(this),
      onPanResponderTerminate: this.handlePanResponderEnd.bind(this),
    });
  }

  componentWillReceiveProps(nextProps) {
    var newValue = nextProps.value;

    if (this.props.value !== newValue) {
      if (this.props.animateTransitions) {
        this.setCurrentValueAnimated(newValue);
      }
      else {
        this.setCurrentValue(newValue);
      }
    }
  }

  // shouldComponentUpdate(nextProps, nextState) {
  //   // We don't want to re-render in the following cases:
  //   // - when only the 'value' prop changes as it's already handled with the Animated.Value
  //   // - when the event handlers change (rendering doesn't depend on them)
  //   // - when the style props haven't actually change
  //
  //   return shallowCompare(
  //     { props: this._getPropsForComponentUpdate(this.props), state: this.state },
  //     this._getPropsForComponentUpdate(nextProps),
  //     nextState
  //   ) || !styleEqual(this.props.style, nextProps.style)
  //     || !styleEqual(this.props.trackStyle, nextProps.trackStyle)
  //     || !styleEqual(this.props.thumbStyle, nextProps.thumbStyle);
  // }
  //
  // _getPropsForComponentUpdate(props) {
  //   var {
  //     value,
  //     onValueChange,
  //     onSlidingStart,
  //     onSlidingComplete,
  //     style,
  //     trackStyle,
  //     thumbStyle,
  //     ...otherProps,
  //   } = props;
  //
  //   return otherProps;
  // }

  setCurrentValue(value) {
    this.state.value.setValue(value);
  }

  setCurrentValueAnimated(value) {
    var animationType = this.props.animationType;
    var animationConfig = Object.assign( {},
      DEFAULT_ANIMATION_CONFIGS[animationType],
      this.props.animationConfig,
      {
        toValue : value
      }
    );

    Animated[animationType](this.state.value, animationConfig).start();
  }

  handleMoveShouldSetPanResponder(/*e: Object, gestureState: Object*/){
    // Should we become active when the user moves a touch over the thumb?
    return false;
  }

  handlePanResponderGrant(/*e: Object, gestureState: Object*/) {
    this._previousLeft = this.getThumbLeft(this.getCurrentValue());
    this.fireChangeEvent('onSlidingStart');
  }

  handlePanResponderMove(e, gestureState) {
    if (this.props.disabled) {
      return;
    }

    this.setCurrentValue(this.getValue(gestureState));
    this.fireChangeEvent('onValueChange');
  }

  handlePanResponderRequestEnd(e, gestureState) {
    // Should we allow another component to take over this pan?
    return false;
  }

  handlePanResponderEnd(e, gestureState) {
    if (this.props.disabled) {
      return;
    }

    this.setCurrentValue(this.getValue(gestureState));
    this.fireChangeEvent('onSlidingComplete');
  }

  thumbHitTest(e) {
    var nativeEvent = e.nativeEvent;
    var thumbTouchRect = this.getThumbTouchRect();
    return thumbTouchRect.containsPoint(nativeEvent.locationX, nativeEvent.locationY);
  }

  handleStartShouldSetPanResponder(e, /*gestureState: Object*/) {
    // Should we become active when the user presses down on the thumb?
    return this.thumbHitTest(e);
  }

  fireChangeEvent(event) {
    if (this.props[event]) {
      this.props[event](this.getCurrentValue());
    }
  }

  getTouchOverflowSize() {
    var state = this.state;
    var props = this.props;

    var size = {};
    if (state.allMeasured === true) {
      size.width = Math.max(0, props.thumbTouchSize.width - state.thumbSize.width);
      size.height = Math.max(0, props.thumbTouchSize.height - state.containerSize.height);
    }

    return size;
  }

  getTouchOverflowStyle() {
    var { width, height } = this.getTouchOverflowSize();

    var touchOverflowStyle = {};
    if (width !== undefined && height !== undefined) {
      var verticalMargin = -height / 2;
      touchOverflowStyle.marginTop = verticalMargin;
      touchOverflowStyle.marginBottom = verticalMargin;

      var horizontalMargin = -width / 2;
      touchOverflowStyle.marginLeft = horizontalMargin;
      touchOverflowStyle.marginRight = horizontalMargin;
    }

    if (this.props.debugTouchArea === true) {
      touchOverflowStyle.backgroundColor = 'orange';
      touchOverflowStyle.opacity = 0.5;
    }

    return touchOverflowStyle;
  }

  handleMeasure(name, x) {
    var { width, height } = x.nativeEvent.layout;
    var size = {width: width, height: height};

    var storeName = `_${name}`;
    var currentSize = this[storeName];
    if (currentSize && width === currentSize.width && height === currentSize.height) {
      return;
    }
    this[storeName] = size;

    if (this._containerSize && this._trackSize && this._thumbSize) {
      this.setState({
        containerSize: this._containerSize,
        trackSize: this._trackSize,
        thumbSize: this._thumbSize,
        allMeasured: true,
      })
    }
  }

  measureContainer(x) {
    this.handleMeasure('containerSize', x);
  }

  measureTrack(x) {
    this.handleMeasure('trackSize', x);
  }

  measureThumb(x) {
    this.handleMeasure('thumbSize', x);
  }

  getValue(gestureState) {
    var length = this.state.containerSize.width - this.state.thumbSize.width;
    var thumbLeft = this._previousLeft + gestureState.dx;

    var ratio = thumbLeft / length;

    if (this.props.step) {
      return Math.max(this.props.minimumValue,
        Math.min(this.props.maximumValue,
          this.props.minimumValue + Math.round(ratio * (this.props.maximumValue - this.props.minimumValue) / this.props.step) * this.props.step
        )
      );
    } else {
      return Math.max(this.props.minimumValue,
        Math.min(this.props.maximumValue,
          ratio * (this.props.maximumValue - this.props.minimumValue) + this.props.minimumValue
        )
      );
    }
  }

  getCurrentValue() {
    return this.state.value.__getValue();
  }

  setCurrentValue(value) {
    this.state.value.setValue(value);
  }

  getRatio(value) {
    return (value - this.props.minimumValue) / (this.props.maximumValue - this.props.minimumValue);
  }

  getThumbLeft(value) {
    var ratio = this.getRatio(value);
    return ratio * (this.state.containerSize.width - this.state.thumbSize.width);
  }

  getThumbTouchRect() {
    var state = this.state;
    var props = this.props;
    var touchOverflowSize = this.getTouchOverflowSize();

    return new Rect(
      touchOverflowSize.width / 2 + this.getThumbLeft(this.getCurrentValue()) + (state.thumbSize.width - props.thumbTouchSize.width) / 2,
      touchOverflowSize.height / 2 + (state.containerSize.height - props.thumbTouchSize.height) / 2,
      props.thumbTouchSize.width,
      props.thumbTouchSize.height
    );
  }

  renderDebugThumbTouchRect(thumbLeft) {
    var thumbTouchRect = this.getThumbTouchRect();
    var positionStyle = {
      left: thumbLeft,
      top: thumbTouchRect.y,
      width: thumbTouchRect.width,
      height: thumbTouchRect.height,
    };

    return (
      <Animated.View
        style={[defaultStyles.debugThumbTouchArea, positionStyle]}
        pointerEvents='none'
      />
    );
  }

  render () {
    const {
      minimumValue,
      maximumValue,
      minimumTrackTintColor,
      maximumTrackTintColor,
      thumbTintColor,
      containerStyle,
      style,
      trackStyle,
      thumbStyle,
      debugTouchArea,
      ...other
    } = this.props

    var { value, containerSize, trackSize, thumbSize, allMeasured} = this.state

    var mainStyles = containerStyle || styles
    var thumbLeft = value.interpolate({
        inputRange: [minimumValue, maximumValue],
        outputRange: [0, containerSize.width - thumbSize.width],
        //extrapolate: 'clamp',
      })

    var valueVisibleStyle = {}
    if (!allMeasured) {
      valueVisibleStyle.opacity = 0;
    }

    var minimumTrackStyle = {
      position: 'absolute',
      width: Animated.add(thumbLeft, thumbSize.width / 2),
      marginTop: -trackSize.height,
      backgroundColor: minimumTrackTintColor,
      ...valueVisibleStyle
    }

    var touchOverflowStyle = this.getTouchOverflowStyle();

    return (
      <View {...other} style={[mainStyles.container, style]} onLayout={this.measureContainer.bind(this)}>
        <View
          style={[{backgroundColor: maximumTrackTintColor,}, mainStyles.track, trackStyle]}
          onLayout={this.measureTrack.bind(this)} />
        <Animated.View style={[mainStyles.track, trackStyle, minimumTrackStyle]} />
        <Animated.View
          onLayout={this.measureThumb.bind(this)}
          style={[
            {backgroundColor: thumbTintColor},
            mainStyles.thumb, thumbStyle,
            {
              transform: [
                { translateX: thumbLeft },
                { translateY: -(trackSize.height + thumbSize.height) / 2 }
              ],
              ...valueVisibleStyle
            }
          ]}
        />
        <View
          style={[styles.touchArea, touchOverflowStyle]}
          {...this.panResponder.panHandlers}>
          {debugTouchArea === true && this.renderDebugThumbTouchRect(thumbLeft)}
        </View>
      </View>
    )
  }
}

Slider.propTypes = {
  /**
   * Initial value of the slider. The value should be between minimumValue
   * and maximumValue, which default to 0 and 1 respectively.
   * Default value is 0.
   *
   * *This is not a controlled component*, e.g. if you don't update
   * the value, the component won't be reset to its inital value.
   */
  value: PropTypes.number,

  /**
   * If true the user won't be able to move the slider.
   * Default value is false.
   */
  disabled: PropTypes.bool,

  /**
   * Initial minimum value of the slider. Default value is 0.
   */
  minimumValue: PropTypes.number,

  /**
   * Initial maximum value of the slider. Default value is 1.
   */
  maximumValue: PropTypes.number,

  /**
   * Step value of the slider. The value should be between 0 and
   * (maximumValue - minimumValue). Default value is 0.
   */
  step: PropTypes.number,

  /**
   * The color used for the track to the left of the button. Overrides the
   * default blue gradient image.
   */
  minimumTrackTintColor: PropTypes.string,

  /**
   * The color used for the track to the right of the button. Overrides the
   * default blue gradient image.
   */
  maximumTrackTintColor: PropTypes.string,

  /**
   * The color used for the thumb.
   */
  thumbTintColor: PropTypes.string,

  /**
   * The size of the touch area that allows moving the thumb.
   * The touch area has the same center has the visible thumb.
   * This allows to have a visually small thumb while still allowing the user
   * to move it easily.
   * The default is {width: 40, height: 40}.
   */
  thumbTouchSize: PropTypes.shape(
    {width: PropTypes.number, height: PropTypes.number}
  ),

  /**
   * Callback continuously called while the user is dragging the slider.
   */
  onValueChange: PropTypes.func,

  /**
   * Callback called when the user starts changing the value (e.g. when
   * the slider is pressed).
   */
  onSlidingStart: PropTypes.func,

  /**
   * Callback called when the user finishes changing the value (e.g. when
   * the slider is released).
   */
  onSlidingComplete: PropTypes.func,

  /**
   * The style applied to the slider container.
   */
  style: View.propTypes.style,

  /**
   * The style applied to the track.
   */
  trackStyle: View.propTypes.style,

  /**
   * The style applied to the thumb.
   */
  thumbStyle: View.propTypes.style,

  /**
   * Set this to true to visually see the thumb touch rect in green.
   */
  debugTouchArea: PropTypes.bool,

  /**
  * Set to true to animate values with default 'timing' animation type
  */
  animateTransitions : PropTypes.bool,

  /**
  * Custom Animation type. 'spring' or 'timing'.
  */
  animationType : PropTypes.oneOf(['spring', 'timing']),

  /**
  * Used to configure the animation parameters.  These are the same parameters in the Animated library.
  */
  animationConfig : PropTypes.object,
}

Slider.defaultProps = {
  value: 0,
  minimumValue: 0,
  maximumValue: 1,
  step: 0,
  minimumTrackTintColor: '#3f3f3f',
  maximumTrackTintColor: '#b3b3b3',
  thumbTintColor: 'red',
  thumbTouchSize: { width: 40, height: 40 },
  debugTouchArea: false,
  animationType: 'timing'
}

const styles = StyleSheet.create({
  container: {
    height: 40,
    justifyContent: 'center',
  },
  track: {
    height: TRACK_SIZE,
    borderRadius: TRACK_SIZE / 2,
    marginTop: -4
  },
  thumb: {
    position: 'absolute',
    width: THUMB_SIZE,
    height: THUMB_SIZE,
    borderRadius: THUMB_SIZE / 2,
  },
  touchArea: {
    position: 'absolute',
    backgroundColor: 'transparent',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
  },
  debugThumbTouchArea: {
    position: 'absolute',
    backgroundColor: 'green',
    opacity: 0.5,
  }
})
<|endoftext|>


<commit_before>document.addEventListener("touchstart",on_touch);
document.addEventListener("mousedown",on_touch);

var recognition = new webkitSpeechRecognition();
recognition.lang = 'en-US';

function on_touch()
{
	recognition.start();

}
function onend()
{
	recognition.stop();
}
recognition.onend = onend();
recognition.onsoundend = onend();
recognition.onspeechend = onend();
recognition.onresult = function (e)
{
	document.getElementById("text").innerHTML = e.results[0][0].transcript + e.results[0][0].confidence ;
}<commit_msg>add more results<commit_after>document.addEventListener("touchstart",on_touch);
document.addEventListener("mousedown",on_touch);

var recognition = new webkitSpeechRecognition();
recognition.lang = 'en-US';
recognition.maxAlternatives =5;

function on_touch()
{
	if(recognition.start){
		recognition.start();
		recognition_started = true;
	}

}
function onend()
{
	recognition.stop();
	recognition_started = false;
}
recognition.onend = onend;
recognition.onsoundend = onend;
recognition.onspeechend = onend;
recognition.onresult =on_results;

function on_results(e)
{
	var alternatives = e.results[0];
	for (var i=0; i<alternatives.length; i++)
	document.getElementById("text").innerHTML += alternatives[i].transcript + alternatives[i].confidence + "<br>" ;
}<|endoftext|>


<commit_before>/*
--------------
freezeframe.js
--------------
v1.1.0

Licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License
http://creativecommons.org/licenses/by-sa/3.0/deed.en_US

2012 Chris Antonellis
http://www.chrisantonellis.com
https://github.com/chrisantonellis/freezeframe
Documentation: http://freezeframe.chrisantonellis.com

---------
Changelog
---------
12/07/2012 v1.1.0 Many new features, including:
	- Created more specific variables for loading background style
	- Added icon to denote animation and supporting variables
	- Added support for touch devices (click to toggle, animation duration, etc)
	- Added false functionality to loading and animation icons to disable
11/30/2012 v1.0.2 Fixed filename and version syntax
11/28/2012 v1.0.1 Fixed image positioning bug
11/25/2012 v1.0.0 Initial Release

todo:
write image attribution text file
update READEME.md on website
create separate documentation html
*/

FreezeFrame = (function()
{
	var _ff;
	var canvas;
	var context;

	var trigger_event;
	var support_touch_devices;
	var animation_play_duration;

	var loading_background_color;
	var loading_background_image;
	var loading_background_position;
	var loading_fade_in_speed;

	var animation_icon_image;
	var animation_icon_position;
	var animation_fade_out_speed;

	var is_touch_device;
	var freezeframe_count;

	function FreezeFrame(_options)
	{
		_ff = this;

		_options == null ? _options = {} : null;

		_options.debug == null ?
			this.debug = false :
			this.debug = _options.debug;

		_options.trigger_event == null ?
			this.trigger_event = "hover" :
			this.trigger_event = _options.trigger_event;

		_options.support_touch_devices == null ?
			this.support_touch_devices = true :
			this.support_touch_devuces = _options.support_touch_devices;

		_options.animation_play_duration == null ?
			this.animation_play_duration = 10000 :
			this.animation_play_duration = parseInt(_options.animation_play_duration);

		_options.loading_background_color == null ?
			this.loading_background_color = "#666" :
			this.loading_background_color = _options.loading_background_color;

		_options.loading_background_image == null ?
			this.loading_background_image = "data:image/gif;base64,R0lGODlhEAAQAPIAAGZmZv///4mJidbW1v///8PDw7CwsKampiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" :
			this.loading_background_image = _options.loading_background_image;

		_options.loading_background_position == null ?
			this.loading_background_position = "center center" :
			this.loading_background_position = _options.loading_background_position;

		_options.animation_icon_image == null ?
			this.animation_icon_image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAl9JREFUeNrs2s2K2lAUAGATb3TE2Cr+oaJQNFOh1MVsxK0OuJbSdX2V9gG67GqW3RbaB7B9gy7qgKJF8G/EarHVWGMyJj230EXLLITm6q05F44/IVw5X3JPjiGCZVkuJw/R5fCBAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAjwjyMej79MpVKP/hcAwe6boul0+p3P5/vmdruv4evbVqvVdRRALpd7HQqFpn6/XxUEwdI07UZV1ffNZvMzjwDE7gk9Hs8mGAwuYCl8hTNB32630nw+f1IqlRY8QtgOQAjRZVleJxKJ77AcVLptOBwup9PpPR4hbAcQRdGUJOk2HA5riqKokUjEgKK4GY/HKo8QhMGcv4oKIJg0+Xw+r8H7bSaT0XiEICwnhyLoCgQCptfrNSgCjxDkED8ChdGiwSMEOaQ2jxDkGOtuH4jJZHJ/Nps9LRaLi+Vy2WDVUB0FYB+IXq+36ff7P0ajURj2eQbF9EO73W6cFMBdENA8mXQbNFDier0mhULhQaVSeZzNZj+d3Bnwe+i6LkDCAqx9QmMwGJwlk8nzarV6Cf3EDHZ5DvHx5ADuSjwWiz0sl8uX8H9izjLxowLskfgL1okfBYCnxA8KwGPiBwGg9xpWq5XIY+IsAQT6stvt6BGX4Nrt4jFxZgCmaYqGYRDo4nzdbncny3KGx8SZAcCRl6CH9yuKcl6r1S6i0egXHhP/Y53aGfV6/U2n02nA5yuIC7vntzsEBo/KXkG84vaI/12w8Flhhw8EQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEcNr4KcAABsB8S2vxAV8AAAAASUVORK5CYII=" :
			this.animation_icon_image = _options.animation_icon_image;

		_options.animation_icon_position == null ?
			this.animation_icon_position = "top left" :
			this.animation_icon_position = _options.animation_icon_position;

		_options.loading_fade_in_speed == null ?
			this.loading_fade_in_speed = 500 :
			this.loading_fade_in_speed = parseInt(_options.loading_fade_in_speed);

		_options.animation_fade_out_speed == null ?
			this.animation_fade_out_speed = 300 :
			this.animation_fade_out_speed = parseInt(_options.animation_fade_out_speed);

		this.is_touch_device = "ontouchstart" in document.documentElement;

		this.freezeframe_count = 0;

		$(document).ready(function()
		{
			_ff.setup();
			_ff.run();
		});
	};

	FreezeFrame.prototype.setup = function()
	{
		$("<canvas>", { id:"freezeframe-canvas" })
			.css("display", "none")
			.prependTo($("body"));

		this.canvas		= $("canvas#freezeframe-canvas");
		this.context	= this.canvas[0].getContext('2d');
	};

	FreezeFrame.prototype.run = function()
	{
		var images = [];
		var ext;

		var figure_background = _ff.loading_background_color;
		if(_ff.loading_background_image !== false)
		{
			figure_background += " url('" + _ff.loading_background_image + "') "
												+ _ff.loading_background_position
												+ " no-repeat";
		}

		images = $('img[freezeframe]')
			.not('[freezeframe="true"]')
			.not('[src^="http"]');

		$(images).each(function(index)
		{
			$(this).attr("freezeframe", "true");

			ext = $(this)[0].src.split(".");
			ext = ext[ext.length - 1].toLowerCase();

			if(ext !== "gif")
			{
				images.splice(index, 1);
			}
			else
			{
				var freezeframe_figure = $("<figure />")
					.attr("class", "freezeframe-container " + _ff.freezeframe_count)
					.css({
						"display": "inline-block",
						"overflow": "hidden",
						"background": figure_background
				});
				$(this)
					.css({
					"opacity": 0,
					"display": "block"
				}).wrap(freezeframe_figure);
				freezeframe_figure = $(this).parent();

				if(_ff.animation_icon_image !== false)
				{
					var animation_icon = $("<div />")
						.attr("class", "freezeframe-animation-icon")
						.css({
							"display": "block",
							"position": "absolute",
							"background": "transparent "
														+ "url('" + _ff.animation_icon_image + "') "
														+ _ff.animation_icon_position
														+ " no-repeat",
							"pointer-events": "none",
							"z-index": 100,
							"opacity": 0
						});
					$(freezeframe_figure).prepend(animation_icon);
					animation_icon = $(this).siblings($(".freezeframe-animation-icon"));
				}

				_ff.freezeframe_count++;

				$(this).load(function()
				{
					$(this).off("load");

					_ff.canvas[0].width = $(this)[0].width;
					_ff.canvas[0].height = $(this)[0].height;

					$(this)
						.attr("animated", $(this).attr("src"))
						.attr("src", $(this).attr("src"));

					_ff.context.drawImage(this, 0, 0);

					$(this).attr("src", _ff.canvas[0].toDataURL());

					if(_ff.animation_icon_image !== false)
					{
						$(animation_icon)
							.css({
								"width": parseInt($(this)[0].width),
								"height": parseInt($(this)[0].height)
							}).animate({"opacity": 1}, _ff.loading_fade_in_speed);
					}

					$(this).animate({"opacity": 1}, _ff.loading_fade_in_speed, function(){

						$(freezeframe_figure)
							.css("background", "url('" + $(this).attr("src") + "')");

						$(this)
							.css("opacity", 0)
							.attr("src", $(this).attr("animated"));

						if((_ff.support_touch_devices && _ff.is_touch_device) ||
						   _ff.trigger_event.toLowerCase() == "click")
						{
							var animating = false;
							var image = this;

							var stop_animation;

							$(this).click(function()
							{
								if(!animating)
								{
									$(this)
										.attr("src", $(this).attr("src"))
										.css("opacity", 1);

									if(_ff.animation_icon_image !== false)
									{
										$(animation_icon)
											.css("opacity", 0);
									}

									stop_animation = setInterval(function()
									{
										clearInterval(stop_animation);
										$(image).animate({"opacity": 0}, _ff.animation_fade_out_speed);
										if(_ff.animation_icon_image !== false)
										{
											$(animation_icon).animate({"opacity": 1}, _ff.animation_fade_out_speed);
										}
										animating = false;

									}, _ff.animation_play_duration);
									animating = true;
								}
								else
								{
									clearInterval(stop_animation);

									$(this).animate({"opacity": 0}, _ff.animation_fade_out_speed);
									if(_ff.animation_icon_image !== false)
									{
										$(animation_icon).animate({"opacity": 1}, _ff.animation_fade_out_speed);
									}

									animating = false;
								}
							});
						}
						else
						{

							$(this).mouseenter(function(){
								$(this)
									.attr("src", $(this).attr("src"))
									.css("opacity", 1);
								if(_ff.animation_icon_image !== false)
								{
									$(animation_icon).css("opacity", 0);
								}
							}).mouseleave(function(){
								$(this).animate({"opacity": 0}, _ff.animation_fade_out_speed);
								if(_ff.animation_icon_image !== false)
								{
									$(animation_icon).animate({"opacity": 1}, _ff.animation_fade_out_speed);
								}
							});
						}
					});
				});
			}
		});
	};

	return FreezeFrame;
})();<commit_msg>v1.1.0 removed unnecessary comments<commit_after>/*
--------------
freezeframe.js
--------------
v1.1.0

Licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License
http://creativecommons.org/licenses/by-sa/3.0/deed.en_US

2012 Chris Antonellis
http://www.chrisantonellis.com
https://github.com/chrisantonellis/freezeframe
Documentation: http://freezeframe.chrisantonellis.com

---------
Changelog
---------
12/07/2012 v1.1.0 Many new features, including:
	- Created more specific variables for loading background style
	- Added icon to denote animation and supporting variables
	- Added support for touch devices (click to toggle, animation duration, etc)
	- Added false functionality to loading and animation icons to disable
11/30/2012 v1.0.2 Fixed filename and version syntax
11/28/2012 v1.0.1 Fixed image positioning bug
11/25/2012 v1.0.0 Initial Release
*/

FreezeFrame = (function()
{
	var _ff;
	var canvas;
	var context;

	var trigger_event;
	var support_touch_devices;
	var animation_play_duration;

	var loading_background_color;
	var loading_background_image;
	var loading_background_position;
	var loading_fade_in_speed;

	var animation_icon_image;
	var animation_icon_position;
	var animation_fade_out_speed;

	var is_touch_device;
	var freezeframe_count;

	function FreezeFrame(_options)
	{
		_ff = this;

		_options == null ? _options = {} : null;

		_options.debug == null ?
			this.debug = false :
			this.debug = _options.debug;

		_options.trigger_event == null ?
			this.trigger_event = "hover" :
			this.trigger_event = _options.trigger_event;

		_options.support_touch_devices == null ?
			this.support_touch_devices = true :
			this.support_touch_devuces = _options.support_touch_devices;

		_options.animation_play_duration == null ?
			this.animation_play_duration = 10000 :
			this.animation_play_duration = parseInt(_options.animation_play_duration);

		_options.loading_background_color == null ?
			this.loading_background_color = "#666" :
			this.loading_background_color = _options.loading_background_color;

		_options.loading_background_image == null ?
			this.loading_background_image = "data:image/gif;base64,R0lGODlhEAAQAPIAAGZmZv///4mJidbW1v///8PDw7CwsKampiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" :
			this.loading_background_image = _options.loading_background_image;

		_options.loading_background_position == null ?
			this.loading_background_position = "center center" :
			this.loading_background_position = _options.loading_background_position;

		_options.animation_icon_image == null ?
			this.animation_icon_image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAl9JREFUeNrs2s2K2lAUAGATb3TE2Cr+oaJQNFOh1MVsxK0OuJbSdX2V9gG67GqW3RbaB7B9gy7qgKJF8G/EarHVWGMyJj230EXLLITm6q05F44/IVw5X3JPjiGCZVkuJw/R5fCBAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAjwjyMej79MpVKP/hcAwe6boul0+p3P5/vmdruv4evbVqvVdRRALpd7HQqFpn6/XxUEwdI07UZV1ffNZvMzjwDE7gk9Hs8mGAwuYCl8hTNB32630nw+f1IqlRY8QtgOQAjRZVleJxKJ77AcVLptOBwup9PpPR4hbAcQRdGUJOk2HA5riqKokUjEgKK4GY/HKo8QhMGcv4oKIJg0+Xw+r8H7bSaT0XiEICwnhyLoCgQCptfrNSgCjxDkED8ChdGiwSMEOaQ2jxDkGOtuH4jJZHJ/Nps9LRaLi+Vy2WDVUB0FYB+IXq+36ff7P0ajURj2eQbF9EO73W6cFMBdENA8mXQbNFDier0mhULhQaVSeZzNZj+d3Bnwe+i6LkDCAqx9QmMwGJwlk8nzarV6Cf3EDHZ5DvHx5ADuSjwWiz0sl8uX8H9izjLxowLskfgL1okfBYCnxA8KwGPiBwGg9xpWq5XIY+IsAQT6stvt6BGX4Nrt4jFxZgCmaYqGYRDo4nzdbncny3KGx8SZAcCRl6CH9yuKcl6r1S6i0egXHhP/Y53aGfV6/U2n02nA5yuIC7vntzsEBo/KXkG84vaI/12w8Flhhw8EQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEcNr4KcAABsB8S2vxAV8AAAAASUVORK5CYII=" :
			this.animation_icon_image = _options.animation_icon_image;

		_options.animation_icon_position == null ?
			this.animation_icon_position = "top left" :
			this.animation_icon_position = _options.animation_icon_position;

		_options.loading_fade_in_speed == null ?
			this.loading_fade_in_speed = 500 :
			this.loading_fade_in_speed = parseInt(_options.loading_fade_in_speed);

		_options.animation_fade_out_speed == null ?
			this.animation_fade_out_speed = 300 :
			this.animation_fade_out_speed = parseInt(_options.animation_fade_out_speed);

		this.is_touch_device = "ontouchstart" in document.documentElement;

		this.freezeframe_count = 0;

		$(document).ready(function()
		{
			_ff.setup();
			_ff.run();
		});
	};

	FreezeFrame.prototype.setup = function()
	{
		$("<canvas>", { id:"freezeframe-canvas" })
			.css("display", "none")
			.prependTo($("body"));

		this.canvas		= $("canvas#freezeframe-canvas");
		this.context	= this.canvas[0].getContext('2d');
	};

	FreezeFrame.prototype.run = function()
	{
		var images = [];
		var ext;

		var figure_background = _ff.loading_background_color;
		if(_ff.loading_background_image !== false)
		{
			figure_background += " url('" + _ff.loading_background_image + "') "
												+ _ff.loading_background_position
												+ " no-repeat";
		}

		images = $('img[freezeframe]')
			.not('[freezeframe="true"]')
			.not('[src^="http"]');

		$(images).each(function(index)
		{
			$(this).attr("freezeframe", "true");

			ext = $(this)[0].src.split(".");
			ext = ext[ext.length - 1].toLowerCase();

			if(ext !== "gif")
			{
				images.splice(index, 1);
			}
			else
			{
				var freezeframe_figure = $("<figure />")
					.attr("class", "freezeframe-container " + _ff.freezeframe_count)
					.css({
						"display": "inline-block",
						"overflow": "hidden",
						"background": figure_background
				});
				$(this)
					.css({
					"opacity": 0,
					"display": "block"
				}).wrap(freezeframe_figure);
				freezeframe_figure = $(this).parent();

				if(_ff.animation_icon_image !== false)
				{
					var animation_icon = $("<div />")
						.attr("class", "freezeframe-animation-icon")
						.css({
							"display": "block",
							"position": "absolute",
							"background": "transparent "
														+ "url('" + _ff.animation_icon_image + "') "
														+ _ff.animation_icon_position
														+ " no-repeat",
							"pointer-events": "none",
							"z-index": 100,
							"opacity": 0
						});
					$(freezeframe_figure).prepend(animation_icon);
					animation_icon = $(this).siblings($(".freezeframe-animation-icon"));
				}

				_ff.freezeframe_count++;

				$(this).load(function()
				{
					$(this).off("load");

					_ff.canvas[0].width = $(this)[0].width;
					_ff.canvas[0].height = $(this)[0].height;

					$(this)
						.attr("animated", $(this).attr("src"))
						.attr("src", $(this).attr("src"));

					_ff.context.drawImage(this, 0, 0);

					$(this).attr("src", _ff.canvas[0].toDataURL());

					if(_ff.animation_icon_image !== false)
					{
						$(animation_icon)
							.css({
								"width": parseInt($(this)[0].width),
								"height": parseInt($(this)[0].height)
							}).animate({"opacity": 1}, _ff.loading_fade_in_speed);
					}

					$(this).animate({"opacity": 1}, _ff.loading_fade_in_speed, function(){

						$(freezeframe_figure)
							.css("background", "url('" + $(this).attr("src") + "')");

						$(this)
							.css("opacity", 0)
							.attr("src", $(this).attr("animated"));

						if((_ff.support_touch_devices && _ff.is_touch_device) ||
						   _ff.trigger_event.toLowerCase() == "click")
						{
							var animating = false;
							var image = this;

							var stop_animation;

							$(this).click(function()
							{
								if(!animating)
								{
									$(this)
										.attr("src", $(this).attr("src"))
										.css("opacity", 1);

									if(_ff.animation_icon_image !== false)
									{
										$(animation_icon)
											.css("opacity", 0);
									}

									stop_animation = setInterval(function()
									{
										clearInterval(stop_animation);
										$(image).animate({"opacity": 0}, _ff.animation_fade_out_speed);
										if(_ff.animation_icon_image !== false)
										{
											$(animation_icon).animate({"opacity": 1}, _ff.animation_fade_out_speed);
										}
										animating = false;

									}, _ff.animation_play_duration);
									animating = true;
								}
								else
								{
									clearInterval(stop_animation);

									$(this).animate({"opacity": 0}, _ff.animation_fade_out_speed);
									if(_ff.animation_icon_image !== false)
									{
										$(animation_icon).animate({"opacity": 1}, _ff.animation_fade_out_speed);
									}

									animating = false;
								}
							});
						}
						else
						{

							$(this).mouseenter(function(){
								$(this)
									.attr("src", $(this).attr("src"))
									.css("opacity", 1);
								if(_ff.animation_icon_image !== false)
								{
									$(animation_icon).css("opacity", 0);
								}
							}).mouseleave(function(){
								$(this).animate({"opacity": 0}, _ff.animation_fade_out_speed);
								if(_ff.animation_icon_image !== false)
								{
									$(animation_icon).animate({"opacity": 1}, _ff.animation_fade_out_speed);
								}
							});
						}
					});
				});
			}
		});
	};

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


<commit_before>dagre.layout.order = function() {
  var config = {
    iterations: 24, // max number of iterations
    debugLevel: 0
  };

  var timer = createTimer();

  var self = {};

  self.iterations = propertyAccessor(self, config, "iterations");

  self.debugLevel = propertyAccessor(self, config, "debugLevel", function(x) {
    timer.enabled(x);
  });

  self.run = timer.wrap("Order Phase", run);

  return self;

  function run(g) {
    var layering = initOrder(g);
    var bestLayering = copyLayering(layering);
    var bestCC = crossCount(g, layering);

    if (config.debugLevel >= 2) {
      console.log("Order phase start cross count: " + bestCC);
    }

    var cc, i, lastBest;
    for (i = 0, lastBest = 0; lastBest < 4 && i < config.iterations; ++i, ++lastBest) {
      cc = sweep(g, i, layering);
      if (cc < bestCC) {
        bestLayering = copyLayering(layering);
        bestCC = cc;
        lastBest = 0;
      }
      if (config.debugLevel >= 3) {
        console.log("Order phase iter " + i + " cross count: " + bestCC);
      }
    }

    bestLayering.forEach(function(layer) {
      layer.forEach(function(u, i) {
        g.node(u).order = i;
      });
    });

    if (config.debugLevel >= 2) {
      console.log("Order iterations: " + i);
      console.log("Order phase best cross count: " + bestCC);
    }

    return bestLayering;
  }

  function initOrder(g) {
    var layering = [];
    g.eachNode(function(n, a) {
      var layer = layering[a.rank] || (layering[a.rank] = []);
      layer.push(n);
    });
    return layering;
  }

  function sweep(g, iter, layering) {
    var cc = 0,
        i;
    if (iter % 2 === 0) {
      for (i = 1; i < layering.length; ++i) {
        cc += barycenterLayer(g, layering[i - 1], layering[i], "inEdges");
      }
    } else {
      for (i = layering.length - 2; i >= 0; --i) {
        cc += barycenterLayer(g, layering[i + 1], layering[i], "outEdges");
      }
    }
    return cc;
  }

  /*
   * Given a fixed layer and a movable layer in a graph this function will
   * attempt to find an improved ordering for the movable layer such that
   * edge crossings may be reduced.
   *
   * This algorithm is based on the barycenter method.
   */
  function barycenterLayer(g, fixed, movable, neighbors) {
    var weights = rankWeights(g, fixed, movable, neighbors);

    var toSort = [];

    movable.forEach(function(u, i) {
      var weight = weights[u];
      if (weight !== -1) {
        toSort.push({node: u, weight: weight, pos: i});
      }
    });

    toSort.sort(function(x, y) {
      var d = x.weight - y.weight;
      if (d === 0) {
        return x.pos - y.pos;
      }
      return d;
    });

    var toSortIndex = 0;
    for (var i = 0; i < movable.length; ++i) {
      var u = movable[i];
      var weight = weights[u];
      if (weight !== -1) {
        movable[i] = toSort[toSortIndex++].node;
      }
    }

    return neighbors === "inEdges"
      ? bilayerCrossCount(g, fixed, movable)
      : bilayerCrossCount(g, movable, fixed);
  }

  /*
   * Given a fixed layer and a movable layer in a graph, this function will
   * return weights for the movable layer that can be used to reorder the layer
   * for potentially reduced edge crossings.
   */
  function rankWeights(g, fixed, movable, neighbors) {
    var fixedPos = {};
    fixed.forEach(function(u, i) { fixedPos[u] = i; });

    var weights = {};
    movable.forEach(function(u) {
      var weight = -1;
      var edges = g[neighbors](u);
      if (edges.length > 0) {
        weight = 0;
        edges.forEach(function(e) {
          var source = g.source(e);
          var neighborId = g.source(e) === u ? g.target(e) : source;
          weight += fixedPos[neighborId];
        });
        weight = weight / edges.length;
      }
      weights[u] = weight;
    });

    return weights;
  }

  function copyLayering(layering) {
    return layering.map(function(l) { return l.slice(0); });
  }
}

var crossCount = dagre.layout.order.crossCount = function(g, layering) {
  var cc = 0;
  var prevLayer;
  layering.forEach(function(layer) {
    if (prevLayer) {
      cc += bilayerCrossCount(g, prevLayer, layer);
    }
    prevLayer = layer;
  });
  return cc;
}

/*
 * This function searches through a ranked and ordered graph and counts the
 * number of edges that cross. This algorithm is derived from:
 *
 *    W. Barth et al., Bilayer Cross Counting, JGAA, 8(2) 179–194 (2004)
 */
var bilayerCrossCount = dagre.layout.order.bilayerCrossCount = function(g, layer1, layer2) {
  var layer2Pos = {};
  layer2.forEach(function(u, i) { layer2Pos[u] = i; });

  var indices = [];
  layer1.forEach(function(u) {
    var nodeIndices = [];
    g.outEdges(u).forEach(function(e) { nodeIndices.push(layer2Pos[g.target(e)]); });
    nodeIndices.sort(function(x, y) { return x - y; });
    indices = indices.concat(nodeIndices);
  });

  var firstIndex = 1;
  while (firstIndex < layer2.length) firstIndex <<= 1;

  var treeSize = 2 * firstIndex - 1;
  firstIndex -= 1;

  var tree = [];
  for (var i = 0; i < treeSize; ++i) { tree[i] = 0; }

  var cc = 0;
  indices.forEach(function(i) {
    var treeIndex = i + firstIndex;
    ++tree[treeIndex];
    var weightSum = 0;
    while (treeIndex > 0) {
      if (treeIndex % 2) {
        cc += tree[treeIndex + 1];
      }
      treeIndex = (treeIndex - 1) >> 1;
      ++tree[treeIndex];
    }
  });

  return cc;
}
<commit_msg>Some simplification to the layering phase<commit_after>dagre.layout.order = function() {
  var config = {
    iterations: 24, // max number of iterations
    debugLevel: 0
  };

  var timer = createTimer();

  var self = {};

  self.iterations = propertyAccessor(self, config, "iterations");

  self.debugLevel = propertyAccessor(self, config, "debugLevel", function(x) {
    timer.enabled(x);
  });

  self.run = timer.wrap("Order Phase", run);

  return self;

  function run(g) {
    var layering = initOrder(g);
    var bestLayering = copyLayering(layering);
    var bestCC = crossCount(g, layering);

    if (config.debugLevel >= 2) {
      console.log("Order phase start cross count: " + bestCC);
    }

    var cc, i, lastBest;
    for (i = 0, lastBest = 0; lastBest < 4 && i < config.iterations; ++i, ++lastBest) {
      cc = sweep(g, i, layering);
      if (cc < bestCC) {
        bestLayering = copyLayering(layering);
        bestCC = cc;
        lastBest = 0;
      }
      if (config.debugLevel >= 3) {
        console.log("Order phase iter " + i + " cross count: " + bestCC);
      }
    }

    bestLayering.forEach(function(layer) {
      layer.forEach(function(u, i) {
        g.node(u).order = i;
      });
    });

    if (config.debugLevel >= 2) {
      console.log("Order iterations: " + i);
      console.log("Order phase best cross count: " + bestCC);
    }

    return bestLayering;
  }

  function initOrder(g) {
    var layering = [];
    g.eachNode(function(n, a) {
      var layer = layering[a.rank] || (layering[a.rank] = []);
      layer.push(n);
    });
    return layering;
  }

  function sweep(g, iter, layering) {
    var cc = 0,
        i;
    if (iter % 2 === 0) {
      for (i = 1; i < layering.length; ++i) {
        barycenterLayer(g, layering[i - 1], layering[i], "inEdges");
        cc += bilayerCrossCount(g, layering[i-1], layering[i]);
      }
    } else {
      for (i = layering.length - 2; i >= 0; --i) {
        barycenterLayer(g, layering[i + 1], layering[i], "outEdges");
        cc += bilayerCrossCount(g, layering[i], layering[i+1]);
      }
    }
    return cc;
  }

  /*
   * Given a fixed layer and a movable layer in a graph this function will
   * attempt to find an improved ordering for the movable layer such that
   * edge crossings may be reduced.
   *
   * This algorithm is based on the barycenter method.
   */
  function barycenterLayer(g, fixed, movable, neighbors) {
    var pos = layerPos(movable);
    var bs = barycenters(g, fixed, movable, neighbors);

    var toSort = movable.slice(0).sort(function(x, y) {
      return bs[x] - bs[y] || pos[x] - pos[y];
    });

    for (var i = movable.length - 1; i >= 0; --i) {
      if (bs[movable[i]] !== -1) {
        movable[i] = toSort.pop();
      }
    }
  }

  /*
   * Given a fixed layer and a movable layer in a graph, this function will
   * return weights for the movable layer that can be used to reorder the layer
   * for potentially reduced edge crossings.
   */
  function barycenters(g, fixed, movable, neighbors) {
    var fixedPos = layerPos(fixed);

    var bs = {};
    movable.forEach(function(u) {
      var b = -1;
      var edges = g[neighbors](u);
      if (edges.length > 0) {
        b = 0;
        edges.forEach(function(e) {
          var source = g.source(e);
          var neighborId = source === u ? g.target(e) : source;
          b += fixedPos[neighborId];
        });
        b = b / edges.length;
      }
      bs[u] = b;
    });

    return bs;
  }

  function copyLayering(layering) {
    return layering.map(function(l) { return l.slice(0); });
  }
}

var crossCount = dagre.layout.order.crossCount = function(g, layering) {
  var cc = 0;
  var prevLayer;
  layering.forEach(function(layer) {
    if (prevLayer) {
      cc += bilayerCrossCount(g, prevLayer, layer);
    }
    prevLayer = layer;
  });
  return cc;
}

/*
 * This function searches through a ranked and ordered graph and counts the
 * number of edges that cross. This algorithm is derived from:
 *
 *    W. Barth et al., Bilayer Cross Counting, JGAA, 8(2) 179–194 (2004)
 */
var bilayerCrossCount = dagre.layout.order.bilayerCrossCount = function(g, layer1, layer2) {
  var layer2Pos = layerPos(layer2);

  var indices = [];
  layer1.forEach(function(u) {
    var nodeIndices = [];
    g.outEdges(u).forEach(function(e) { nodeIndices.push(layer2Pos[g.target(e)]); });
    nodeIndices.sort(function(x, y) { return x - y; });
    indices = indices.concat(nodeIndices);
  });

  var firstIndex = 1;
  while (firstIndex < layer2.length) firstIndex <<= 1;

  var treeSize = 2 * firstIndex - 1;
  firstIndex -= 1;

  var tree = [];
  for (var i = 0; i < treeSize; ++i) { tree[i] = 0; }

  var cc = 0;
  indices.forEach(function(i) {
    var treeIndex = i + firstIndex;
    ++tree[treeIndex];
    var weightSum = 0;
    while (treeIndex > 0) {
      if (treeIndex % 2) {
        cc += tree[treeIndex + 1];
      }
      treeIndex = (treeIndex - 1) >> 1;
      ++tree[treeIndex];
    }
  });

  return cc;
}

function layerPos(layer) {
  var pos = {};
  layer.forEach(function(u, i) { pos[u] = i; });
  return pos;
}
<|endoftext|>


<commit_before>/*  Copyright (c) 2012 Sven "FuzzYspo0N" Bergström, 2013 Robert XD Hawkins

    written by : http://underscorediscovery.com
    written for : http://buildnewgames.com/real-time-multiplayer/

    modified for collective behavior experiments on Amazon Mechanical Turk

    MIT Licensed.
*/

//require('look').start()

    var
        use_db      = false,
        game_server = module.exports = { games : {}, game_count:0, assignment:0},
        UUID        = require('node-uuid'),
        fs          = require('fs');

    if (use_db) {
	    database    = require(__dirname + "/database"),
	    connection  = database.getConnection();
    }

global.window = global.document = global;
require('./game.core.js');

// This is the function where the server parses and acts on messages
// sent from 'clients' aka the browsers of people playing the
// game. For example, if someone clicks on the map, they send a packet
// to the server (check the client_on_click function in game.client.js)
// with the coordinates of the click, which this function reads and
// applies.
game_server.server_onMessage = function(client,message) {
    //Cut the message up into sub components
    var message_parts = message.split('.');

    //The first is always the type of message
    var message_type = message_parts[0];
    //console.log("received message: " + message)
    //Extract important variables
    var target = client.game.gamecore.get_player(client.userid);
    var others = client.game.gamecore.get_others(client.userid);
    if(message_type == 'a') {    // Client is changing angle
        // Set their (server) angle
        target.angle = message_parts[1];
    } else if (message_type == 's') {
        target.speed = message_parts[1];
    } else if (message_type == "h") { // Receive message when browser focus shifts
        target.visible = message_parts[1];
    } else if (message_type == 'pong') {
	var latency = (Date.now() - message_parts[1])/2;
	client.game.gamecore.latencyStream.write(String(client.userid)+","+message_parts[2]+","+latency+"\n",
			   function(err) { if(err) throw err; });
    }
};

/*
   The following functions should not need to be modified for most purposes
*/

// This is the important function that pairs people up into 'rooms'
// all independent of one another.
game_server.findGame = function(player) {
    this.log('looking for a game. We have : ' + this.game_count);
    //if there are any games created, add this player to it!
    if(this.game_count) {
       var joined_a_game = false;
        for (var gameid in this.games) {
            if(!this.games.hasOwnProperty(gameid)) continue;
            var game = this.games[gameid];
            var gamecore = game.gamecore;
            if(game.player_count < gamecore.players_threshold && !game.active) {
               joined_a_game = true;
                // player instances are array of actual client handles
                game.player_instances.push({
                    id: player.userid,
                    player: player
                });
                game.player_count++;
                // players are array of player objects
                game.gamecore.players.push({
                    id: player.userid,
                    player: new game_player(gamecore,player)
                });
                // Attach game to player so server can look at it later
                player.game = game;

                // notify new player that they're joining game
                player.send('s.join.' + gamecore.players.length)

                // notify existing players that someone new is joining
                _.map(gamecore.get_others(player.userid), function(p){p.player.instance.send( 's.add_player.' + player.userid)})
                gamecore.server_send_update();
                gamecore.update();

                if (game.player_count == gamecore.players_threshold) {
                    this.startGame(game)
                }
            }
        }
        if(!joined_a_game) { // if we didn't join a game, we must create one
            this.createGame(player);
        }
    }
    else {
        //no games? create one!
        this.createGame(player);
    }
};

// Will run when first player connects
game_server.createGame = function(player) {
    // Figure out variables
    var game_params = this.param_guide[this.assignment].split(',')
    var par_id = parseInt(game_params[0])
    var players_threshold = parseInt(game_params[1])
    var noise_location = game_params[2]
    this.assignment = (this.assignment + 1) % this.param_guide.length

    var d = new Date();
    var start_time = d.getFullYear() + '-' + d.getMonth() + 1 + '-' + d.getDate() + '-' + d.getHours() + '-' + d.getMinutes() + '-' + d.getMilliseconds()
    var id = par_id + '_' + start_time;

    //Create a new game instance
    var game = {
	//generate a new id for the game
        id : id,
	//store list of players in the game
        player_instances: [{id: player.userid, player: player}],
	//for simple checking of state
        player_count: 1
    };

    //Create a new game core instance (defined in game.core.js)
    game.gamecore = new game_core(game);

    // Tell the game about its own id
    game.gamecore.game_id = id;
    game.gamecore.players_threshold = players_threshold
    game.gamecore.noise_location = noise_location

    // Set up the filesystem variable we'll use later, and write headers
    game.gamecore.fs = fs;
    fs.writeFile("data/games/game_" +id+ ".csv", "pid,tick,active,x_pos,y_pos,velocity,angle,bg_val,total_points\n", function (err) {if(err) throw err;})
    game.gamecore.gameDataStream = fs.createWriteStream("data/games/game_" +id+ ".csv", {'flags' : 'a'});
    fs.writeFile("data/latencies/game_"+id+".csv", "pid,tick,latency\n", function (err) {if(err) throw err;})
    game.gamecore.latencyStream = fs.createWriteStream("data/latencies/game_"+id+".csv", {'flags' : 'a'});

    // When workers are directed to the page, they specify which
    // version of the task they're running.
    game.gamecore.condition = player.condition;

    // tell the player that they have joined a game
    // The client will parse this message in the "client_onMessage" function
    // in game.client.js, which redirects to other functions based on the command
    player.game = game;
    player.send('s.join.' + game.gamecore.players.length)
    this.log('player ' + player.userid + ' created a game with id ' + player.game.id);
    //Start updating the game loop on the server
    game.gamecore.update();

    // add to game collection
    this.games[ game.id ] = game;
    this.game_count++;
    if(game.gamecore.players_threshold == 1) {
	this.startGame(game)
    }

    var game_server = this

    // schedule the game to start to prevent players from waiting too long
    setTimeout(function() {
	    if(!game.active) {
		game_server.startGame(game);
	    }
	}, game.gamecore.waiting_room_limit*60*1000)

    //return it
    return game;
};

// we are requesting to kill a game in progress.
// This gets called if someone disconnects
game_server.endGame = function(gameid, userid) {
    var thegame = this.games [ gameid ];
    if(thegame) {
        //if the game has more than one player, it's fine -- let the others keep playing, but let them know
        var player_metric = (thegame.active
			     ? thegame.gamecore.get_active_players().length
			     : thegame.player_count)
        console.log("removing... game has " + player_metric + " players")
        if(player_metric > 1) {
            var i = _.indexOf(thegame.gamecore.players, _.findWhere(thegame.gamecore.players, {id: userid}))
            thegame.gamecore.players[i].player = null;

            // If the game hasn't started yet, allow more players to fill their place. after it starts, don't.
            if (!thegame.active)
                thegame.player_count--;
        } else {
            // If the game only has one player and they leave, remove it.
            thegame.gamecore.stop_update();
            delete this.games[gameid];
            this.game_count--;
            this.log('game removed. there are now ' + this.game_count + ' games' );
        }
    } else {
        this.log('that game was not found!');
    }
};

// When the threshold is exceeded, this gets called
game_server.startGame = function(game) {
    game.active = true;
    game.gamecore.server_newgame();
};

//A simple wrapper for logging so we can toggle it,
//and augment it for clarity.
game_server.log = function() {
    console.log.apply(this,arguments);
};
<commit_msg>Randomly choose player numbers and noise instead of reading from file<commit_after>/*  Copyright (c) 2012 Sven "FuzzYspo0N" Bergström, 2013 Robert XD Hawkins

    written by : http://underscorediscovery.com
    written for : http://buildnewgames.com/real-time-multiplayer/

    modified for collective behavior experiments on Amazon Mechanical Turk

    MIT Licensed.
*/

//require('look').start()

    var
        use_db      = false,
        game_server = module.exports = { games : {}, game_count:0, assignment:0},
        UUID        = require('node-uuid'),
        fs          = require('fs');

    if (use_db) {
	    database    = require(__dirname + "/database"),
	    connection  = database.getConnection();
    }

global.window = global.document = global;
require('./game.core.js');

// This is the function where the server parses and acts on messages
// sent from 'clients' aka the browsers of people playing the
// game. For example, if someone clicks on the map, they send a packet
// to the server (check the client_on_click function in game.client.js)
// with the coordinates of the click, which this function reads and
// applies.
game_server.server_onMessage = function(client,message) {
    //Cut the message up into sub components
    var message_parts = message.split('.');

    //The first is always the type of message
    var message_type = message_parts[0];
    //console.log("received message: " + message)
    //Extract important variables
    var target = client.game.gamecore.get_player(client.userid);
    var others = client.game.gamecore.get_others(client.userid);
    if(message_type == 'a') {    // Client is changing angle
        // Set their (server) angle
        target.angle = message_parts[1];
    } else if (message_type == 's') {
        target.speed = message_parts[1];
    } else if (message_type == "h") { // Receive message when browser focus shifts
        target.visible = message_parts[1];
    } else if (message_type == 'pong') {
	var latency = (Date.now() - message_parts[1])/2;
	client.game.gamecore.latencyStream.write(String(client.userid)+","+message_parts[2]+","+latency+"\n",
			   function(err) { if(err) throw err; });
    }
};

/*
   The following functions should not need to be modified for most purposes
*/

// This is the important function that pairs people up into 'rooms'
// all independent of one another.
game_server.findGame = function(player) {
    this.log('looking for a game. We have : ' + this.game_count);
    //if there are any games created, add this player to it!
    if(this.game_count) {
       var joined_a_game = false;
        for (var gameid in this.games) {
            if(!this.games.hasOwnProperty(gameid)) continue;
            var game = this.games[gameid];
            var gamecore = game.gamecore;
            if(game.player_count < gamecore.players_threshold && !game.active) {
               joined_a_game = true;
                // player instances are array of actual client handles
                game.player_instances.push({
                    id: player.userid,
                    player: player
                });
                game.player_count++;
                // players are array of player objects
                game.gamecore.players.push({
                    id: player.userid,
                    player: new game_player(gamecore,player)
                });
                // Attach game to player so server can look at it later
                player.game = game;

                // notify new player that they're joining game
                player.send('s.join.' + gamecore.players.length)

                // notify existing players that someone new is joining
                _.map(gamecore.get_others(player.userid), function(p){p.player.instance.send( 's.add_player.' + player.userid)})
                gamecore.server_send_update();
                gamecore.update();

                if (game.player_count == gamecore.players_threshold) {
                    this.startGame(game)
                }
            }
        }
        if(!joined_a_game) { // if we didn't join a game, we must create one
            this.createGame(player);
        }
    }
    else {
        //no games? create one!
        this.createGame(player);
    }
};

// Will run when first player connects
game_server.createGame = function(player) {
    // Figure out variables
    var thresholds = Array(1,1,1,1,1,1,1,1,2,2,2,2,4,4,8);
    var players_threshold = thresholds[Math.floor(Math.random()*thresholds.length)];
    var noise_id = Math.floor(Math.random() * 4) + '-2en01'
    var noise_location = '/home/rxdh/couzin_replication/light-fields/' + noise_id + '/'
    this.assignment = (this.assignment + 1) % this.param_guide.length

    var d = new Date();
    var start_time = d.getFullYear() + '-' + d.getMonth() + 1 + '-' + d.getDate() + '-' + d.getHours() + '-' + d.getMinutes() + '-' + d.getSeconds() + '-' + d.getMilliseconds()
    var id = start_time + '_' + players_threshold + '_' + noise_id + '_' + Math.floor(Math.random() * 1e12);

    //Create a new game instance
    var game = {
	//generate a new id for the game
        id : id,
	//store list of players in the game
        player_instances: [{id: player.userid, player: player}],
	//for simple checking of state
        player_count: 1
    };

    //Create a new game core instance (defined in game.core.js)
    game.gamecore = new game_core(game);

    // Tell the game about its own id
    game.gamecore.game_id = id;
    game.gamecore.players_threshold = players_threshold
    game.gamecore.noise_location = noise_location

    // Set up the filesystem variable we'll use later, and write headers
    game.gamecore.fs = fs;
    fs.writeFile("data/games/game_" +id+ ".csv", "pid,tick,active,x_pos,y_pos,velocity,angle,bg_val,total_points\n", function (err) {if(err) throw err;})
    game.gamecore.gameDataStream = fs.createWriteStream("data/games/game_" +id+ ".csv", {'flags' : 'a'});
    fs.writeFile("data/latencies/game_"+id+".csv", "pid,tick,latency\n", function (err) {if(err) throw err;})
    game.gamecore.latencyStream = fs.createWriteStream("data/latencies/game_"+id+".csv", {'flags' : 'a'});

    // When workers are directed to the page, they specify which
    // version of the task they're running.
    game.gamecore.condition = player.condition;

    // tell the player that they have joined a game
    // The client will parse this message in the "client_onMessage" function
    // in game.client.js, which redirects to other functions based on the command
    player.game = game;
    player.send('s.join.' + game.gamecore.players.length)
    this.log('player ' + player.userid + ' created a game with id ' + player.game.id);
    //Start updating the game loop on the server
    game.gamecore.update();

    // add to game collection
    this.games[ game.id ] = game;
    this.game_count++;
    if(game.gamecore.players_threshold == 1) {
	this.startGame(game)
    }

    var game_server = this

    // schedule the game to start to prevent players from waiting too long
    setTimeout(function() {
	    if(!game.active) {
		game_server.startGame(game);
	    }
	}, game.gamecore.waiting_room_limit*60*1000)

    //return it
    return game;
};

// we are requesting to kill a game in progress.
// This gets called if someone disconnects
game_server.endGame = function(gameid, userid) {
    var thegame = this.games [ gameid ];
    if(thegame) {
        //if the game has more than one player, it's fine -- let the others keep playing, but let them know
        var player_metric = (thegame.active
			     ? thegame.gamecore.get_active_players().length
			     : thegame.player_count)
        console.log("removing... game has " + player_metric + " players")
        if(player_metric > 1) {
            var i = _.indexOf(thegame.gamecore.players, _.findWhere(thegame.gamecore.players, {id: userid}))
            thegame.gamecore.players[i].player = null;

            // If the game hasn't started yet, allow more players to fill their place. after it starts, don't.
            if (!thegame.active)
                thegame.player_count--;
        } else {
            // If the game only has one player and they leave, remove it.
            thegame.gamecore.stop_update();
            delete this.games[gameid];
            this.game_count--;
            this.log('game removed. there are now ' + this.game_count + ' games' );
        }
    } else {
        this.log('that game was not found!');
    }
};

// When the threshold is exceeded, this gets called
game_server.startGame = function(game) {
    game.active = true;
    game.gamecore.server_newgame();
};

//A simple wrapper for logging so we can toggle it,
//and augment it for clarity.
game_server.log = function() {
    console.log.apply(this,arguments);
};
<|endoftext|>