<commit_before>import {Button, ButtonGroup} from 'widget/button'
import {compose} from 'compose'
import {connect} from 'store'
import {msg} from 'translate'
import {selectFrom} from 'stateUtils'
import Keybinding from 'widget/keybinding'
import OverflowDetector from 'widget/overflowDetector'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'

const {Provider, Consumer} = React.createContext()

const mapStateToProps = state => ({
    dimensions: selectFrom(state, 'dimensions') || []
})

class _Pageable extends React.Component {
    state = {
        count: undefined,
        start: 0,
        stop: undefined,
        direction: 1
    }

    componentDidMount() {
        this.updateItemCount()
    }

    componentDidUpdate(prevProps) {
        if (!_.isEqual(prevProps.items, this.props.items)) {
            this.updateItemCount()
        }
        if (!_.isEqual(prevProps.dimensions, this.props.dimensions)) {
            this.refreshOnResize()
        }
    }

    updateItemCount() {
        const {items} = this.props
        const count = items.length
        this.setState({
            count,
            start: 0,
            stop: undefined,
            direction: 1
        })
    }

    refreshOnResize() {
        this.setState({
            stop: undefined,
            direction: 1
        })
    }

    isFirstPage() {
        const {count, start} = this.state
        return !count || start === 0
    }

    isLastPage() {
        const {count, stop} = this.state
        return !count || stop === count
    }

    firstPage() {
        if (!this.isFirstPage()) {
            this.setState({
                start: 0,
                stop: undefined,
                direction: 1
            })
        }
    }

    previousPage() {
        if (!this.isFirstPage()) {
            this.setState(({count, start}) => ({
                start: undefined,
                stop: Math.min(start, count),
                direction: -1
            }))
        }
    }

    nextPage() {
        if (!this.isLastPage()) {
            this.setState(({stop}) => ({
                start: Math.max(stop, 0),
                stop: undefined,
                direction: 1
            }))
        }
    }

    next(overflow) {
        const {direction} = this.state
        if (overflow === null || direction === 0) {
            return
        }

        this.setState(({count, start, stop, direction}) => {
            const offset = overflow ? - 1 : 1

            const isEdge = ({start, stop}) => (direction === -1 && start < 0) || (direction === 1 && stop > count)

            const nextState = ({start, stop}) => ({
                start: Math.max(start, 0),
                stop: Math.min(stop, count),
                direction: overflow
                    ? 0
                    : isEdge({start, stop})
                        ? direction === -1
                            ? direction = 1
                            : 0
                        : direction
            })

            const nextValue = (thisValue, otherValue) =>
                thisValue === undefined
                    ? otherValue
                    : thisValue + offset * direction

            return direction === 1
                ? nextState({
                    start,
                    stop: nextValue(stop, start)
                })
                : nextState({
                    start: nextValue(start, stop),
                    stop
                })
        })
    }

    render() {
        const {count, start, stop, direction} = this.state
        const {items, children} = this.props
        const isFirstPage = this.isFirstPage()
        const isLastPage = this.isLastPage()
        const isSinglePage = isFirstPage && isLastPage
        return (
            <Keybinding keymap={{
                'Ctrl+Shift+ArrowLeft': () => this.firstPage(),
                'Ctrl+ArrowLeft': () => this.previousPage(),
                'Ctrl+ArrowRight': () => this.nextPage()
            }}>
                <Provider value={{
                    items,
                    count,
                    start,
                    stop,
                    direction,
                    isFirstPage,
                    isLastPage,
                    isSinglePage,
                    firstPage: () => this.firstPage(),
                    lastPage: () => this.lastPage(),
                    previousPage: () => this.previousPage(),
                    nextPage: () => this.nextPage(),
                    next: overflow => this.next(overflow)
                }}>
                    {children}
                </Provider>
            </Keybinding>
        )
    }
}

export const Pageable = compose(
    _Pageable,
    connect(mapStateToProps)
)

Pageable.propTypes = {
    children: PropTypes.any.isRequired,
    items: PropTypes.array.isRequired
}

export class PageData extends React.Component {
    ref = React.createRef()
    render() {
        const {itemKey, children} = this.props
        return (
            <Consumer>
                {({items, start, stop, direction, next}) =>
                    <OverflowDetector>
                        {isOverflown =>
                            <PageItems
                                items={items}
                                start={start}
                                stop={stop}
                                direction={direction}
                                next={next}
                                isOverflown={isOverflown}
                                itemKey={itemKey}
                            >
                                {children}
                            </PageItems>
                        }
                    </OverflowDetector>
                }
            </Consumer>
        )
    }
}

PageData.propTypes = {
    children: PropTypes.func.isRequired,
    itemKey: PropTypes.func.isRequired
}

class PageItems extends React.Component {
    render() {
        const {start, stop} = this.props
        return start !== undefined && stop !== undefined
            ? this.renderPage()
            : null
    }

    renderPage() {
        const {items, start, stop} = this.props
        return items.slice(start, stop).map(
            (item, index) => this.renderItem(item, index)
        )
    }

    renderItem(item, index) {
        const {itemKey, children} = this.props
        return (
            <PageItem
                key={itemKey(item) || index}
                item={item}>
                {children}
            </PageItem>
        )
    }

    componentDidUpdate() {
        const {next, isOverflown} = this.props
        next(isOverflown())
    }
}

class PageItem extends React.Component {
    render() {
        const {item, children} = this.props
        return children(item)
    }

    shouldComponentUpdate(nextProps) {
        return nextProps.item !== this.props.item
    }
}

export const PageControls = props => {
    const renderDefaultControls = pageable =>
        <ButtonGroup type='horizontal-nowrap'>
            <Button
                chromeless
                size='large'
                shape='pill'
                icon='fast-backward'
                onClick={() => pageable.firstPage()}
                disabled={pageable.isFirstPage}/>
            <Button
                chromeless
                size='large'
                shape='pill'
                icon='backward'
                onClick={() => pageable.previousPage()}
                disabled={pageable.isFirstPage}/>
            <Button
                chromeless
                size='large'
                shape='pill'
                icon='forward'
                onClick={() => pageable.nextPage()}
                disabled={pageable.isLastPage}/>
        </ButtonGroup>
    const renderCustomControls = pageable =>
        <React.Fragment>
            {props.children({...pageable, renderDefaultControls: () => renderDefaultControls(pageable)})}
        </React.Fragment>

    return (
        <Consumer>
            {pageable => props.children
                ? renderCustomControls(pageable)
                : renderDefaultControls(pageable)
            }
        </Consumer>
    )
}

PageControls.propTypes = {
    children: PropTypes.func
}

export const PageInfo = props => {
    const renderDefaultInfo = ({count, start, stop}) =>

            {msg('pagination.info', {count, start, stop})}

    const renderCustomInfo = ({pageNumber, pageCount, count}) =>
        <React.Fragment>
            {props.children({pageNumber, pageCount, count})}
        </React.Fragment>

    return (
        <Consumer>
            {pageable => props.children
                ? renderCustomInfo(pageable)
                : renderDefaultInfo(pageable)
            }
        </Consumer>
    )
}

PageInfo.propTypes = {
    children: PropTypes.func
}
<commit_msg>Refactored Pageable.<commit_after>import {Button, ButtonGroup} from 'widget/button'
import {compose} from 'compose'
import {connect} from 'store'
import {msg} from 'translate'
import {selectFrom} from 'stateUtils'
import Keybinding from 'widget/keybinding'
import OverflowDetector from 'widget/overflowDetector'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'

const {Provider, Consumer} = React.createContext()

const mapStateToProps = state => ({
    dimensions: selectFrom(state, 'dimensions') || []
})

class _Pageable extends React.Component {
    state = {}

    componentDidMount() {
        this.updateItemCount()
    }

    componentDidUpdate(prevProps) {
        if (!_.isEqual(prevProps.items, this.props.items)) {
            this.updateItemCount()
        }
        if (!_.isEqual(prevProps.dimensions, this.props.dimensions)) {
            this.refreshOnResize()
        }
    }

    updateItemCount() {
        const {items} = this.props
        const count = items.length
        this.setState({
            count,
            start: 0,
            stop: undefined,
            direction: 1
        })
    }

    refreshOnResize() {
        this.setState({
            stop: undefined,
            direction: 1
        })
    }

    isFirstPage() {
        const {count, start} = this.state
        return !count || start === 0
    }

    isLastPage() {
        const {count, stop} = this.state
        return !count || stop === count
    }

    firstPage() {
        if (!this.isFirstPage()) {
            this.setState({
                start: 0,
                stop: undefined,
                direction: 1
            })
        }
    }

    previousPage() {
        if (!this.isFirstPage()) {
            this.setState(({count, start}) => ({
                start: undefined,
                stop: Math.min(start, count),
                direction: -1
            }))
        }
    }

    nextPage() {
        if (!this.isLastPage()) {
            this.setState(({stop}) => ({
                start: Math.max(stop, 0),
                stop: undefined,
                direction: 1
            }))
        }
    }

    next(overflow) {
        const {direction} = this.state
        if (overflow === null || direction === 0) {
            return
        }

        const isEdge = (count, start, stop, direction) =>
            (direction === -1 && start < 0) || (direction === 1 && stop > count)

        const nextDirection = (count, start, stop, direction) =>
            overflow
                ? 0
                : isEdge(count, start, stop, direction)
                    ? direction === -1
                        ? direction = 1
                        : 0
                    : direction

        const nextValue = (thisValue, otherValue, direction) =>
            thisValue === undefined
                ? otherValue
                : thisValue + direction * (overflow ? -1 : 1)

        this.setState(({count, start, stop, direction}) => {
            const next = {
                start: direction === 1 ? start : nextValue(start, stop, direction),
                stop: direction === -1 ? stop : nextValue(stop, start, direction)
            }
            return {
                start: Math.max(next.start, 0),
                stop: Math.min(next.stop, count),
                direction: nextDirection(count, next.start, next.stop, direction)
            }
        })
    }

    render() {
        const {count, start, stop, direction} = this.state
        const {items, children} = this.props
        const isFirstPage = this.isFirstPage()
        const isLastPage = this.isLastPage()
        const isSinglePage = isFirstPage && isLastPage
        return (
            <Keybinding keymap={{
                'Ctrl+Shift+ArrowLeft': () => this.firstPage(),
                'Ctrl+ArrowLeft': () => this.previousPage(),
                'Ctrl+ArrowRight': () => this.nextPage()
            }}>
                <Provider value={{
                    items,
                    count,
                    start,
                    stop,
                    direction,
                    isFirstPage,
                    isLastPage,
                    isSinglePage,
                    firstPage: () => this.firstPage(),
                    lastPage: () => this.lastPage(),
                    previousPage: () => this.previousPage(),
                    nextPage: () => this.nextPage(),
                    next: overflow => this.next(overflow)
                }}>
                    {children}
                </Provider>
            </Keybinding>
        )
    }
}

export const Pageable = compose(
    _Pageable,
    connect(mapStateToProps)
)

Pageable.propTypes = {
    children: PropTypes.any.isRequired,
    items: PropTypes.array.isRequired
}

export class PageData extends React.Component {
    ref = React.createRef()
    render() {
        const {itemKey, children} = this.props
        return (
            <Consumer>
                {({items, start, stop, direction, next}) =>
                    <OverflowDetector>
                        {isOverflown =>
                            <PageItems
                                items={items}
                                start={start}
                                stop={stop}
                                direction={direction}
                                next={next}
                                isOverflown={isOverflown}
                                itemKey={itemKey}
                            >
                                {children}
                            </PageItems>
                        }
                    </OverflowDetector>
                }
            </Consumer>
        )
    }
}

PageData.propTypes = {
    children: PropTypes.func.isRequired,
    itemKey: PropTypes.func.isRequired
}

class PageItems extends React.Component {
    render() {
        const {start, stop} = this.props
        return start !== undefined && stop !== undefined
            ? this.renderPage()
            : null
    }

    renderPage() {
        const {items, start, stop} = this.props
        return items.slice(start, stop).map(
            (item, index) => this.renderItem(item, index)
        )
    }

    renderItem(item, index) {
        const {itemKey, children} = this.props
        return (
            <PageItem
                key={itemKey(item) || index}
                item={item}>
                {children}
            </PageItem>
        )
    }

    componentDidUpdate() {
        const {next, isOverflown} = this.props
        next(isOverflown())
    }
}

class PageItem extends React.Component {
    render() {
        const {item, children} = this.props
        return children(item)
    }

    shouldComponentUpdate(nextProps) {
        return nextProps.item !== this.props.item
    }
}

export const PageControls = props => {
    const renderDefaultControls = pageable =>
        <ButtonGroup type='horizontal-nowrap'>
            <Button
                chromeless
                size='large'
                shape='pill'
                icon='fast-backward'
                onClick={() => pageable.firstPage()}
                disabled={pageable.isFirstPage}/>
            <Button
                chromeless
                size='large'
                shape='pill'
                icon='backward'
                onClick={() => pageable.previousPage()}
                disabled={pageable.isFirstPage}/>
            <Button
                chromeless
                size='large'
                shape='pill'
                icon='forward'
                onClick={() => pageable.nextPage()}
                disabled={pageable.isLastPage}/>
        </ButtonGroup>
    const renderCustomControls = pageable =>
        <React.Fragment>
            {props.children({...pageable, renderDefaultControls: () => renderDefaultControls(pageable)})}
        </React.Fragment>

    return (
        <Consumer>
            {pageable => props.children
                ? renderCustomControls(pageable)
                : renderDefaultControls(pageable)
            }
        </Consumer>
    )
}

PageControls.propTypes = {
    children: PropTypes.func
}

export const PageInfo = props => {
    const renderDefaultInfo = ({count, start, stop}) =>

            {msg('pagination.info', {count, start, stop})}

    const renderCustomInfo = ({pageNumber, pageCount, count}) =>
        <React.Fragment>
            {props.children({pageNumber, pageCount, count})}
        </React.Fragment>

    return (
        <Consumer>
            {pageable => props.children
                ? renderCustomInfo(pageable)
                : renderDefaultInfo(pageable)
            }
        </Consumer>
    )
}

PageInfo.propTypes = {
    children: PropTypes.func
}
<|endoftext|>


<commit_before>import {
  FrontSide,
  BackSide,
  DoubleSide,

  SmoothShading,
  FlatShading,

  NoBlending,
  NormalBlending,
  AdditiveBlending,
  SubtractiveBlending,
  MultiplyBlending,
  CustomBlending,

  NeverDepth,
  AlwaysDepth,
  LessDepth,
  LessEqualDepth,
  GreaterEqualDepth,
  GreaterDepth,
  NotEqualDepth
} from 'three';

const additional = {
  wireframe: {
    wireframe: 'boolean',
    wireframeLinecap: ['butt', 'round', 'square'],
    wireframeLinejoin: ['round', 'bevel', 'miter'],
    wireframeLinewidth: 'number'
  },

  refr: {
    reflectivity: 'number',
    refractionRatio: 'number'
  },

  light: {
    lightMap: 'texture',
    lightMapIntensity: 'number'
  },

  displacement: {
    displacementScale: 'number',
    displacementBias: 'number',
    displacementMap: 'texture'
  },

  emissive: {
    emissive: 'color',
    emissiveMap: 'texture',
    emissiveIntensity: 'number'
  }
}

const add = (origin, ...addv) => {
  console.log(addv.map(value => additional[value]));
  return Object.assign(origin, ...addv.map(value => additional[value]))
}

export default {
  any: add({
    side: {FrontSide, BackSide, DoubleSide},
    shading: {SmoothShading, FlatShading},
    blending: {
      NoBlending, NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending
    },
    depthFunc: {
      NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth
    }
  }, 'wireframe'),

  MeshBasicMaterial: {
    color: 'color',
    lights: 'boolean',
    linewidth: 'number',
    linecap: ['butt', 'round', 'square'],
    linejoin: ['round', 'bevel', 'miter']
  },

  MeshLambertMaterial: add({
    color: 'color'
  }, 'emissive', 'refr', 'light'),

  MeshPhongMaterial: add({

  }, 'displacement', 'emissive'),

  MeshDepthMaterial: {

  }
  // To be continued...
}
<commit_msg>Fix materials section<commit_after>import {
  FrontSide,
  BackSide,
  DoubleSide,

  SmoothShading,
  FlatShading,

  NoBlending,
  NormalBlending,
  AdditiveBlending,
  SubtractiveBlending,
  MultiplyBlending,
  CustomBlending,

  NeverDepth,
  AlwaysDepth,
  LessDepth,
  LessEqualDepth,
  GreaterEqualDepth,
  GreaterDepth,
  NotEqualDepth
} from 'three';

const additional = {
  wireframe: {
    wireframe: 'boolean',
    wireframeLinecap: ['butt', 'round', 'square'],
    wireframeLinejoin: ['round', 'bevel', 'miter'],
    wireframeLinewidth: 'number'
  },

  refr: {
    reflectivity: 'number',
    refractionRatio: 'number'
  },

  light: {
    lightMap: 'texture',
    lightMapIntensity: 'number'
  },

  displacement: {
    displacementScale: 'number',
    displacementBias: 'number',
    displacementMap: 'texture'
  },

  emissive: {
    emissive: 'color',
    emissiveMap: 'texture',
    emissiveIntensity: 'number'
  }
}

const add = (origin, ...addv) => {
  return Object.assign(origin, ...addv.map(value => additional[value]))
}

export default {
  any: add({
    side: {FrontSide, BackSide, DoubleSide},
    shading: {SmoothShading, FlatShading},
    blending: {
      NoBlending, NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending
    },
    depthFunc: {
      NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth
    }
  }, 'wireframe'),

  MeshBasicMaterial: {
    color: 'color',
    lights: 'boolean',
    linewidth: 'number',
    linecap: ['butt', 'round', 'square'],
    linejoin: ['round', 'bevel', 'miter']
  },

  MeshLambertMaterial: add({
    color: 'color'
  }, 'emissive', 'refr', 'light'),

  MeshPhongMaterial: add({
    color: 'color'
  }, 'displacement', 'emissive'),

  MeshDepthMaterial: {

  }
  // To be continued...
}
<|endoftext|>


<commit_before>var sigGen = require('./sigGen.js');
var modulator = require('./modulator.js');
var fft = require('./fft.js');
var windowing = require('fft-windowing');

function getPsd(centerFreq, span, resBw, vidBw, refLvl, scale, sigFreq) {
	var startFreq = centerFreq - span / 2.0;
	var NENBW = 1.5;
	var df = resBw / NENBW;
	var n = Math.ceil(span / df);
	var T = 1 / ( 2 * n * df); // Get sampling interval.

	var fftResult = getFFT(1, T, sigFreq, 0, n, startFreq);

	var psd = {
		refLvl: refLvl,
		scale: scale,
		resBw: resBw,
		vidBw: vidBw,
		freq: fftResult.freq,
		psd: fftResult.psd,
		power: fftResult.power
	};

	return psd;
}

function getFFT(A, T, f, phi, n, startFreq) {
	var t = new Array(n);
	var bins = new Array(n);
	for (var i = 0; i < n; i++) {
		t[i] = i * T;
		bins[i] = i;
	}

	// Generate the signal
	var noise = sigGen.noise(0, A/1000, n);
	var signal = sigGen.sinusoid(A, f, t, phi);
	signal = sigGen.add([signal, noise]);

	// Heterodyne with LO signal to shift the DFT to the specified start frequency
	if(startFreq != 0)
		signal = sigGen.multiply([signal, sigGen.sinusoid(1, startFreq, t, 0)]);

	signal = windowing.hann(signal);
	var NENBW = 1.5; // Hann window normalized equivalent noise bandwidth

	// Subtract DC offset
	var avg = 0;
	for (var i = 0; i < n; i++)
		avg += signal[i];
	avg /= n;

	for (var i = 0; i < n; i++)
		signal[i] -= avg;

	// Compute the FFT in place
	var reals = signal.slice(0);
	var imag = new Array(n);
	for (var i = 0; i < n; i++)
		imag[i] = 0;
	fft.transform(reals, imag);

	// Get the single-sided power spectrum in dB and the corresponding frequencies
	var n2 = (n % 2 == 0) ? (n / 2) + 1 : (n + 1) / 2;
	var df = 1 / (n * T); // Frequency resolution (bin bandwidth)
	var power = new Array(n2);
	var psd = new Array(n2);
	var freq = new Array(n2);

	for (var i = 0; i < n2; i++) {
		var R2 = Math.pow(reals[i], 2);
		var I2 = Math.pow(imag[i], 2);
		var P = 2 * (R2 + I2) / Math.pow(n, 2);
		power[i] = 10 * Math.log(P) / Math.LN10; // Convert to dB
		psd[i] = 10 * Math.log(P / (df * NENBW)) / Math.LN10;
		freq[i] = startFreq + i * df;
	}

	var data = {
		time: t,
		freq: freq,
		bins: bins,
		signal: signal,
		power: power,
		psd: psd,
		reals: reals,
		imag: imag
	};

	return data;
}

exports.getPsd = getPsd;
exports.getFFT = getFFT;<commit_msg>Testing tab/space thing<commit_after>var sigGen = require('./sigGen.js');
var modulator = require('./modulator.js');
var fft = require('./fft.js');
var windowing = require('fft-windowing');

function getPsd(centerFreq, span, resBw, vidBw, refLvl, scale, sigFreq) {
	var startFreq = centerFreq - span / 2.0;
	var NENBW = 1.5;
	var df = resBw / NENBW;
	var n = Math.ceil(span / df);
	var T = 1 / ( 2 * n * df); // Get sampling interval.

	var fftResult = getFFT(1, T, sigFreq, 0, n, startFreq);

	var psd = {
		refLvl: refLvl,
		scale: scale,
		resBw: resBw,
		vidBw: vidBw,
		freq: fftResult.freq,
		psd: fftResult.psd,
		power: fftResult.power
	};

	return psd;
}

function getFFT(A, T, f, phi, n, startFreq) {
    var t = new Array(n);
	var bins = new Array(n);
	for (var i = 0; i < n; i++) {
		t[i] = i * T;
		bins[i] = i;
	}

	// Generate the signal
	var noise = sigGen.noise(0, A/1000, n);
	var signal = sigGen.sinusoid(A, f, t, phi);
	signal = sigGen.add([signal, noise]);

	// Heterodyne with LO signal to shift the DFT to the specified start frequency
	if(startFreq != 0)
		signal = sigGen.multiply([signal, sigGen.sinusoid(1, startFreq, t, 0)]);

	signal = windowing.hann(signal);
	var NENBW = 1.5; // Hann window normalized equivalent noise bandwidth

	// Subtract DC offset
	var avg = 0;
	for (var i = 0; i < n; i++)
		avg += signal[i];
	avg /= n;

	for (var i = 0; i < n; i++)
		signal[i] -= avg;

	// Compute the FFT in place
	var reals = signal.slice(0);
	var imag = new Array(n);
	for (var i = 0; i < n; i++)
		imag[i] = 0;
	fft.transform(reals, imag);

	// Get the single-sided power spectrum in dB and the corresponding frequencies
	var n2 = (n % 2 == 0) ? (n / 2) + 1 : (n + 1) / 2;
	var df = 1 / (n * T); // Frequency resolution (bin bandwidth)
	var power = new Array(n2);
	var psd = new Array(n2);
	var freq = new Array(n2);

	for (var i = 0; i < n2; i++) {
		var R2 = Math.pow(reals[i], 2);
		var I2 = Math.pow(imag[i], 2);
		var P = 2 * (R2 + I2) / Math.pow(n, 2);
		power[i] = 10 * Math.log(P) / Math.LN10; // Convert to dB
		psd[i] = 10 * Math.log(P / (df * NENBW)) / Math.LN10;
		freq[i] = startFreq + i * df;
	}

	var data = {
		time: t,
		freq: freq,
		bins: bins,
		signal: signal,
		power: power,
		psd: psd,
		reals: reals,
		imag: imag
	};

	return data;
}

exports.getPsd = getPsd;
exports.getFFT = getFFT;<|endoftext|>


<commit_before>'use strict';

$(function(){
    $('.oldBio').tooltip();

    $('.bioButtons > .yes').click(function(){
        $('.slider > .setMsg').removeClass('btn-info');
        $('.slider').slideDown();
    });

    $('.slider > .setMsg').click(function(){
        $.ajax({
          url: "manage/",
          type: "POST",
          data: {"action":"msgSet","payload":$('.slider > textarea').val()},
          success: function( data ) {
            $('.slider > .setMsg').addClass('btn-info');
            $('.bioButtons > .yes').addClass('btn-info');
            $('.bioButtons > .no').removeClass('btn-info');
          }
        });
    });

    $('.bioButtons > .no').click(function(){
         $.ajax({
          url: "manage/",
          type: "POST",
          data: {"action":"msgSet","payload":""},
          success: function( data ) {
            $('.bioButtons > .yes').removeClass('btn-info');
            $('.slider > .setMsg').removeClass('btn-info');
            $(this).addClass('btn-info');
            $('.slider').slideUp();
          }
        });
    });

});<commit_msg>Added more ajax<commit_after>'use strict';

$(function(){
    $('.oldBio').click(function(){
        $.ajax({
          url: "manage/",
          type: "POST",
          data: {"action":"revertBio","payload":true},
          success: function( data ) {
            $('.oldBio').removeClass('btn-info').addClass('btn-success');
          }
        });
    }).tooltip();

    $('.deactivate').click(function(){
        $.ajax({
          url: "manage/",
          type: "POST",
          data: {"action":"deactivate","payload":true},
          success: function( data ) {
            console.log('Your account was deactivated. Do something here.');
          }
        });
    }).tooltip();

    $('.bioButtons > .yes').click(function(){
        $('.slider > .setMsg').removeClass('btn-info');
        $('.slider').slideDown();
    });

    $('.slider > .setMsg').click(function(){
        $.ajax({
          url: "manage/",
          type: "POST",
          data: {"action":"msgSet","payload":$('.slider > textarea').val()},
          success: function( data ) {
            $('.slider > .setMsg').addClass('btn-info');
            $('.bioButtons > .yes').addClass('btn-info');
            $('.bioButtons > .no').removeClass('btn-info');
          }
        });
    });

    $('.bioButtons > .no').click(function(){
         $.ajax({
          url: "manage/",
          type: "POST",
          data: {"action":"msgSet","payload":""},
          success: function( data ) {
            $('.bioButtons > .yes').removeClass('btn-info');
            $('.slider > .setMsg').removeClass('btn-info');
            $('.bioButtons > .no').addClass('btn-info');
            $('.slider').slideUp();
          }
        });
    });

});<|endoftext|>


<commit_before>var CACHE_NAME = 'modulr-cache-v1';
var urlsToCache = [
  //'/',
  //'/js/app.js',
  '/css/app.css',
  '/img/icon/favicon-96x96.png',
  '/img/icon/android-chrome-192x192.png',
  '/img/logos/logo-name.svg'
];

self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        // Cache hit - return response
        if (response) {
          return response;
        }
        return fetch(event.request);
      }
    )
  );
});

self.addEventListener('activate', function(event) {

  var cacheWhitelist = [CACHE_NAME];

  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});
<commit_msg>cache add app.js<commit_after>var CACHE_NAME = 'modulr-cache-v1';
var urlsToCache = [
  //'/',
  '/js/app.js',
  '/css/app.css',
  '/img/icon/favicon-96x96.png',
  '/img/icon/android-chrome-192x192.png',
  '/img/logos/logo-name.svg'
];

self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        // Cache hit - return response
        if (response) {
          return response;
        }
        return fetch(event.request);
      }
    )
  );
});

self.addEventListener('activate', function(event) {

  var cacheWhitelist = [CACHE_NAME];

  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});
<|endoftext|>


<commit_before>import _ from 'lodash';
import dateMath from '@elastic/datemath';
import moment from 'moment';
import 'ui/timepicker/quick_ranges';
import 'ui/timepicker/time_units';
import uiModules from 'ui/modules';
const module = uiModules.get('kibana/kibana-time-plugin', ['kibana', 'ktp-ui.bootstrap.carousel', 'BootstrapAddons']);

const SimpleEmitter = require('ui/utils/simple_emitter');
const msearchEmitter = new SimpleEmitter;
module.config(function($httpProvider) {
  $httpProvider.interceptors.push(function() {
    return {
      response: function(resp) {
        if (resp.config.url.includes('_msearch')) {
          msearchEmitter.emit('msearch:response');
        }
        return resp;
      }
    }
  });
});

  module.controller('KbnTimeVisController', function (quickRanges, timeUnits, $scope, $rootScope, Private, $filter, $timeout) {
    const TIMESLIDER_INSTR = "Click and drag to select a time range."
    const DATE_FORMAT = 'MMMM Do YYYY, HH:mm:ss z';
    $rootScope.plugin = {
      timePlugin: {}
    };

    $rootScope.$watchMulti([
      '$$timefilter.time.from',
      '$$timefilter.time.to'
    ], setTime);

    var changeVisOff = $rootScope.$on(
      'change:vis',
      _.debounce(updateTimeslider, 200, false));
    $scope.$on('$destroy', function() {
      changeVisOff();
    });

    var expectedFrom = moment();
    var expectedTo = moment();
    $scope.animationTitle = TIMESLIDER_INSTR;
    $scope.quickLists = quickRanges;
    $scope.units = timeUnits;
    $scope.relativeOptions = [
      {text: 'Seconds ago', value: 's'},
      {text: 'Minutes ago', value: 'm'},
      {text: 'Hours ago', value: 'h'},
      {text: 'Days ago', value: 'd'},
      {text: 'Weeks ago', value: 'w'},
      {text: 'Months ago', value: 'M'},
      {text: 'Years ago', value: 'y'},
    ];
    $scope.relative = {
      count: 1,
      unit: 'm',
      preview: undefined,
      round: false
    };
    $scope.sliderRoundOptions = [
      {text: 'Second', value: 's'},
      {text: 'Minute', value: 'm'},
      {text: 'Hour', value: 'h'},
      {text: 'Day', value: 'd'},
      {text: 'Week', value: 'w'},
      {text: 'Month', value: 'M'},
      {text: 'Year', value: 'y'},
    ];
    $scope.slider = {
      roundUnit: 's',
    };
    $scope.time = {
      from: moment(),
      to: moment()
    };

    //custom playback that waits for kibana msearch response before advancing timeframe
    let nextStep = null;
    $scope.kibanaPlayback = {
      play: function(nextCallback) {
        nextCallback();
        const delay = _.get($scope.vis.params, 'animation_frame_delay', 1) * 1000;
        nextStep = _.debounce(nextCallback, delay);
      },
      pause: function() {
        nextStep = null;
      }
    }
    msearchEmitter.on('msearch:response', function() {
      if (nextStep) {
        nextStep();
      }
    });

    //When timeslider carousel slide is not displayed, it has a width of 0
    //attach click handler to carousel controls to redraw
    $timeout(function() {
      var elems = document.getElementsByClassName('carousel-control');
      for (var i=0; i<elems.length; i++) {
        elems[i].onclick = function() {
          updateTimeslider();
        }
      }
      var elems = document.querySelectorAll('.carousel-indicators li');
      for (var i=0; i<elems.length; i++) {
        elems[i].onclick = function() {
          updateTimeslider();
        }
      }
    }, 0);

    function setTime(rangeA) {
      var from = rangeA[0];
      var to = rangeA[1];
      var ours_ms = {
        from: dateMath.parse(expectedFrom).toDate().getTime(),
        to: dateMath.parse(expectedTo, true).toDate().getTime()
      }
      var theirs_ms = {
        from: dateMath.parse(from).toDate().getTime(),
        to: dateMath.parse(to).toDate().getTime()
      }
      console.log("from, ours: " + ours_ms.from + ", theirs: " + theirs_ms.from);
      console.log("to, ours: " + ours_ms.to + ", theirs: " + theirs_ms.to);

      //setTime is called from watching kibana's timefilter
      //Avoid updating our $scope if the timefilter change is triggered by us
      if(Math.abs(ours_ms.from - theirs_ms.from) > 500
        || Math.abs(ours_ms.to - theirs_ms.to) > 500) {
        console.log("updating KbnTimeVisController.$scope stay in sync with kibana timefilter");
        //clean up old selections
        $scope.activeSlide = {
          absolute: false,
          quick: false,
          relative: false
        };

        //set new selections based on new time
        $scope.time = {
          from: from,
          to: to,
          absolute_from: dateMath.parse(from),
          absolute_to: dateMath.parse(to, true)
        }
        setRelativeParts(to, from);
        if('quick' === $rootScope.$$timefilter.time.mode) {
          $scope.activeSlide.quick = true;
          for(var i=0; i<quickRanges.length; i++) {
            if(quickRanges[i].from === from && quickRanges[i].to === to) {
              $scope.selectedQuick = quickRanges[i];
              break;
            }
          }
        } else if ('relative' === $rootScope.$$timefilter.time.mode) {
          $scope.activeSlide.relative = true;
        } else {
          $scope.activeSlide.absolute = true;
        }
        updateTimeslider();
      }
    }
    setTime([
      $rootScope.$$timefilter.time.from,
      $rootScope.$$timefilter.time.to]);

    $scope.filterByTime = function(start, end) {
      $scope.time.mode = 'absolute';
      expectedFrom = moment(start);
      expectedTo = moment(end);
      $scope.animationTitle = 'Frame: ' + expectedFrom.format(DATE_FORMAT) + ' to ' + expectedTo.format(DATE_FORMAT);
      updateKbnTime();
    }

    $scope.removeTimeFilter = function() {
      $scope.animationTitle = TIMESLIDER_INSTR;
      expectedFrom = $scope.time.from;
      expectedTo = $scope.time.to;
      updateKbnTime();
    }

    $scope.setAbsolute = function() {
      $scope.time.mode = 'absolute';
      $scope.time.from = $scope.time.absolute_from;
      $scope.time.to = $scope.time.absolute_to;
      expectedFrom = $scope.time.from;
      expectedTo = $scope.time.to;
      updateKbnTime();
    };

    $scope.setRelative = function () {
      $scope.time.from = getRelativeString();
      $scope.time.to = 'now';
      $scope.time.mode = 'relative';
      expectedFrom = $scope.time.from;
      expectedTo = $scope.time.to;
      updateKbnTime();
    };

    $scope.setQuick = function (selectedQuick) {
      $scope.time.from = selectedQuick.from;
      $scope.time.to = selectedQuick.to;
      $scope.time.mode = 'quick';
      expectedFrom = $scope.time.from;
      expectedTo = $scope.time.to, true;
      updateKbnTime();
    };

    $scope.snapToNearest = function() {
      $scope.$broadcast('timesliderSnapToNearest', {
        snapToNearest: $scope.slider.roundUnit
      });
    }

    function updateKbnTime() {
      $rootScope.$$timefilter.time.from = expectedFrom;
      $rootScope.$$timefilter.time.to = expectedTo;
      $rootScope.$$timefilter.time.mode = $scope.time.mode;

      //keep other carousel slides in sync with new values
      if($scope.time.mode !== 'absolute') {
        $scope.time.absolute_from = dateMath.parse($scope.time.from);
        $scope.time.absolute_to = dateMath.parse($scope.time.to, true);
      }
      if($scope.time.mode !== 'relative') {
        //wrapped in $timeout to avoid calling $apply while all ready in progress
        $timeout(setRelativeParts($scope.time.to, $scope.time.from), 0);
      }
      updateTimeslider();
    }

    function updateTimeslider() {
      $timeout(function() {
        $scope.$broadcast('timesliderForceRender');
      }, 0);
    }

    //Relative date logic copied from https://github.com/elastic/kibana/blob/4.4/src/ui/public/timepicker/timepicker.js

    //convert to and from into pieces needed for relative inputs
    function setRelativeParts(to, from) {
      var fromParts = from.toString().split('-');
      var relativeParts = [];

      // Try to parse the relative time, if we can't use moment duration to guestimate
      if (to.toString() === 'now' && fromParts[0] === 'now' && fromParts[1]) {
        relativeParts = fromParts[1].match(/([0-9]+)([smhdwMy]).*/);
      }
      if (relativeParts[1] && relativeParts[2]) {
        $scope.relative.count = parseInt(relativeParts[1], 10);
        $scope.relative.unit = relativeParts[2];
      } else {
        var duration = moment.duration(moment().diff(dateMath.parse(from)));
        var units = _.pluck(_.clone($scope.relativeOptions).reverse(), 'value');
        if (from.toString().split('/')[1]) $scope.relative.round = true;
        for (var i = 0; i < units.length; i++) {
          var as = duration.as(units[i]);
          if (as > 1) {
            $scope.relative.count = Math.round(as);
            $scope.relative.unit = units[i];
            break;
          }
        }
      }

      if (from.toString().split('/')[1]) $scope.relative.round = true;
      formatRelative();
    }
    function formatRelative() {
      var parsed = dateMath.parse(getRelativeString());
      $scope.relative.preview =  parsed ? parsed.format($scope.format) : undefined;
      return parsed;
    }
    $scope.formatRelative = formatRelative;

    function getRelativeString() {
      return 'now-' + $scope.relative.count + $scope.relative.unit + ($scope.relative.round ? '/' + $scope.relative.unit : '');
    }
  });
<commit_msg>time animation - cancel debounce function when animation is paused<commit_after>import _ from 'lodash';
import dateMath from '@elastic/datemath';
import moment from 'moment';
import 'ui/timepicker/quick_ranges';
import 'ui/timepicker/time_units';
import uiModules from 'ui/modules';
const module = uiModules.get('kibana/kibana-time-plugin', ['kibana', 'ktp-ui.bootstrap.carousel', 'BootstrapAddons']);

const SimpleEmitter = require('ui/utils/simple_emitter');
const msearchEmitter = new SimpleEmitter();
module.config(function($httpProvider) {
  $httpProvider.interceptors.push(function() {
    return {
      response: function(resp) {
        if (resp.config.url.includes('_msearch')) {
          msearchEmitter.emit('msearch:response');
        }
        return resp;
      }
    }
  });
});

  module.controller('KbnTimeVisController', function (quickRanges, timeUnits, $scope, $rootScope, Private, $filter, $timeout) {
    const TIMESLIDER_INSTR = "Click and drag to select a time range."
    const DATE_FORMAT = 'MMMM Do YYYY, HH:mm:ss z';
    $rootScope.plugin = {
      timePlugin: {}
    };

    $rootScope.$watchMulti([
      '$$timefilter.time.from',
      '$$timefilter.time.to'
    ], setTime);

    var changeVisOff = $rootScope.$on(
      'change:vis',
      _.debounce(updateTimeslider, 200, false));
    $scope.$on('$destroy', function() {
      changeVisOff();
    });

    var expectedFrom = moment();
    var expectedTo = moment();
    $scope.animationTitle = TIMESLIDER_INSTR;
    $scope.quickLists = quickRanges;
    $scope.units = timeUnits;
    $scope.relativeOptions = [
      {text: 'Seconds ago', value: 's'},
      {text: 'Minutes ago', value: 'm'},
      {text: 'Hours ago', value: 'h'},
      {text: 'Days ago', value: 'd'},
      {text: 'Weeks ago', value: 'w'},
      {text: 'Months ago', value: 'M'},
      {text: 'Years ago', value: 'y'},
    ];
    $scope.relative = {
      count: 1,
      unit: 'm',
      preview: undefined,
      round: false
    };
    $scope.sliderRoundOptions = [
      {text: 'Second', value: 's'},
      {text: 'Minute', value: 'm'},
      {text: 'Hour', value: 'h'},
      {text: 'Day', value: 'd'},
      {text: 'Week', value: 'w'},
      {text: 'Month', value: 'M'},
      {text: 'Year', value: 'y'},
    ];
    $scope.slider = {
      roundUnit: 's',
    };
    $scope.time = {
      from: moment(),
      to: moment()
    };

    //custom playback that waits for kibana msearch response before advancing timeframe
    let nextStep = null;
    $scope.kibanaPlayback = {
      play: function(nextCallback) {
        nextCallback();
        const delay = _.get($scope.vis.params, 'animation_frame_delay', 1) * 1000;
        nextStep = _.debounce(nextCallback, delay);
      },
      pause: function() {
        if (nextStep) {
          nextStep.cancel();
          nextStep = null;
        }
      }
    }
    msearchEmitter.on('msearch:response', function() {
      if (nextStep) {
        nextStep();
      }
    });

    //When timeslider carousel slide is not displayed, it has a width of 0
    //attach click handler to carousel controls to redraw
    $timeout(function() {
      var elems = document.getElementsByClassName('carousel-control');
      for (var i=0; i<elems.length; i++) {
        elems[i].onclick = function() {
          updateTimeslider();
        }
      }
      var elems = document.querySelectorAll('.carousel-indicators li');
      for (var i=0; i<elems.length; i++) {
        elems[i].onclick = function() {
          updateTimeslider();
        }
      }
    }, 0);

    function setTime(rangeA) {
      var from = rangeA[0];
      var to = rangeA[1];
      var ours_ms = {
        from: dateMath.parse(expectedFrom).toDate().getTime(),
        to: dateMath.parse(expectedTo, true).toDate().getTime()
      }
      var theirs_ms = {
        from: dateMath.parse(from).toDate().getTime(),
        to: dateMath.parse(to).toDate().getTime()
      }
      console.log("from, ours: " + ours_ms.from + ", theirs: " + theirs_ms.from);
      console.log("to, ours: " + ours_ms.to + ", theirs: " + theirs_ms.to);

      //setTime is called from watching kibana's timefilter
      //Avoid updating our $scope if the timefilter change is triggered by us
      if(Math.abs(ours_ms.from - theirs_ms.from) > 500
        || Math.abs(ours_ms.to - theirs_ms.to) > 500) {
        console.log("updating KbnTimeVisController.$scope stay in sync with kibana timefilter");
        //clean up old selections
        $scope.activeSlide = {
          absolute: false,
          quick: false,
          relative: false
        };

        //set new selections based on new time
        $scope.time = {
          from: from,
          to: to,
          absolute_from: dateMath.parse(from),
          absolute_to: dateMath.parse(to, true)
        }
        setRelativeParts(to, from);
        if('quick' === $rootScope.$$timefilter.time.mode) {
          $scope.activeSlide.quick = true;
          for(var i=0; i<quickRanges.length; i++) {
            if(quickRanges[i].from === from && quickRanges[i].to === to) {
              $scope.selectedQuick = quickRanges[i];
              break;
            }
          }
        } else if ('relative' === $rootScope.$$timefilter.time.mode) {
          $scope.activeSlide.relative = true;
        } else {
          $scope.activeSlide.absolute = true;
        }
        updateTimeslider();
      }
    }
    setTime([
      $rootScope.$$timefilter.time.from,
      $rootScope.$$timefilter.time.to]);

    $scope.filterByTime = function(start, end) {
      $scope.time.mode = 'absolute';
      expectedFrom = moment(start);
      expectedTo = moment(end);
      $scope.animationTitle = 'Frame: ' + expectedFrom.format(DATE_FORMAT) + ' to ' + expectedTo.format(DATE_FORMAT);
      updateKbnTime();
    }

    $scope.removeTimeFilter = function() {
      $scope.animationTitle = TIMESLIDER_INSTR;
      expectedFrom = $scope.time.from;
      expectedTo = $scope.time.to;
      updateKbnTime();
    }

    $scope.setAbsolute = function() {
      $scope.time.mode = 'absolute';
      $scope.time.from = $scope.time.absolute_from;
      $scope.time.to = $scope.time.absolute_to;
      expectedFrom = $scope.time.from;
      expectedTo = $scope.time.to;
      updateKbnTime();
    };

    $scope.setRelative = function () {
      $scope.time.from = getRelativeString();
      $scope.time.to = 'now';
      $scope.time.mode = 'relative';
      expectedFrom = $scope.time.from;
      expectedTo = $scope.time.to;
      updateKbnTime();
    };

    $scope.setQuick = function (selectedQuick) {
      $scope.time.from = selectedQuick.from;
      $scope.time.to = selectedQuick.to;
      $scope.time.mode = 'quick';
      expectedFrom = $scope.time.from;
      expectedTo = $scope.time.to, true;
      updateKbnTime();
    };

    $scope.snapToNearest = function() {
      $scope.$broadcast('timesliderSnapToNearest', {
        snapToNearest: $scope.slider.roundUnit
      });
    }

    function updateKbnTime() {
      $rootScope.$$timefilter.time.from = expectedFrom;
      $rootScope.$$timefilter.time.to = expectedTo;
      $rootScope.$$timefilter.time.mode = $scope.time.mode;

      //keep other carousel slides in sync with new values
      if($scope.time.mode !== 'absolute') {
        $scope.time.absolute_from = dateMath.parse($scope.time.from);
        $scope.time.absolute_to = dateMath.parse($scope.time.to, true);
      }
      if($scope.time.mode !== 'relative') {
        //wrapped in $timeout to avoid calling $apply while all ready in progress
        $timeout(setRelativeParts($scope.time.to, $scope.time.from), 0);
      }
      updateTimeslider();
    }

    function updateTimeslider() {
      $timeout(function() {
        $scope.$broadcast('timesliderForceRender');
      }, 0);
    }

    //Relative date logic copied from https://github.com/elastic/kibana/blob/4.4/src/ui/public/timepicker/timepicker.js

    //convert to and from into pieces needed for relative inputs
    function setRelativeParts(to, from) {
      var fromParts = from.toString().split('-');
      var relativeParts = [];

      // Try to parse the relative time, if we can't use moment duration to guestimate
      if (to.toString() === 'now' && fromParts[0] === 'now' && fromParts[1]) {
        relativeParts = fromParts[1].match(/([0-9]+)([smhdwMy]).*/);
      }
      if (relativeParts[1] && relativeParts[2]) {
        $scope.relative.count = parseInt(relativeParts[1], 10);
        $scope.relative.unit = relativeParts[2];
      } else {
        var duration = moment.duration(moment().diff(dateMath.parse(from)));
        var units = _.pluck(_.clone($scope.relativeOptions).reverse(), 'value');
        if (from.toString().split('/')[1]) $scope.relative.round = true;
        for (var i = 0; i < units.length; i++) {
          var as = duration.as(units[i]);
          if (as > 1) {
            $scope.relative.count = Math.round(as);
            $scope.relative.unit = units[i];
            break;
          }
        }
      }

      if (from.toString().split('/')[1]) $scope.relative.round = true;
      formatRelative();
    }
    function formatRelative() {
      var parsed = dateMath.parse(getRelativeString());
      $scope.relative.preview =  parsed ? parsed.format($scope.format) : undefined;
      return parsed;
    }
    $scope.formatRelative = formatRelative;

    function getRelativeString() {
      return 'now-' + $scope.relative.count + $scope.relative.unit + ($scope.relative.round ? '/' + $scope.relative.unit : '');
    }
  });
<|endoftext|>


<commit_before>define('worker_console', function () {
  var window = this;
  var counter = 0;
  if (window.document === undefined) {
    console = ([
        'log'
      , 'warn'
      , 'error'
      , 'debug'
      , 'group'
      , 'groupEnd'
    ].reduce(
        function (o, func) {
          o[func] = function () {
            try {
              throw new Error
            } catch (e) {
              postMessage({ cmd: 'console', func: func, arguments: arguments, stack: e.stack, count: counter++ });
            }
          };
          return o;
        }
      , {}
    ));
    console.worker = true;
  } else {
    console.wrapWorker = function (worker) {
      worker.addEventListener('message', function (event) {
        if (event.data.cmd !== 'console')
          return true;
        console[event.data.func].bind(console)(event.data.arguments, event.data.stack.split('\n')[2], event.data.count);
        event.stopImmediatePropagation();
      });
      worker.addEventListener('error', function (event) {
        console.error(event);
      });
      return worker;
    }
  }
  return console;
});<commit_msg>We can get the current stack from the browser Error object instead of throwing an exception<commit_after>define('worker_console', function () {
  var window = this;
  var counter = 0;
  if (window.document === undefined) {
    console = ([
        'log'
      , 'warn'
      , 'error'
      , 'debug'
      , 'group'
      , 'groupEnd'
    ].reduce(
        function (o, func) {
          o[func] = function () {
            postMessage({ cmd: 'console', func: func, arguments: arguments, stack: (new Error).stack, count: counter++ });
          };
          return o;
        }
      , {}
    ));
    console.worker = true;
  } else {
    console.wrapWorker = function (worker) {
      worker.addEventListener('message', function (event) {
        if (event.data.cmd !== 'console')
          return true;
        console[event.data.func].bind(console)(event.data.arguments, event.data.stack.split('\n')[2], event.data.count);
        event.stopImmediatePropagation();
      });
      worker.addEventListener('error', function (event) {
        console.error(event);
      });
      return worker;
    }
  }
  return console;
});<|endoftext|>


<commit_before>var path = require('path');
var ApplicationError = require('./lib/application_error');
var l = require('./lib/log')('ravel');
var rest = require('./lib/rest');

module.exports = function() {
  var Ravel = {
    modules: {}
  };

  var moduleFactories = {};
  var serviceFactories = {};
  var knownParameters = {};
  var params = {};
  var injector = require('./lib/injector')(Ravel, moduleFactories, module.parent);

  //Change __dirname to current working directory of the
  //app using the ravel library, so that modules can be
  //loaded with relative paths.
  __dirname = process.cwd();

  /**
   * Register a parameter
   * @param {String} key the key for the parameter
   * @param {Boolean | undefined} required true, iff the parameter is required
   */
  Ravel.registerSimpleParameter = function(key, required) {
    knownParameters[key] = {
      required: required
    }
  };

  /**
   * Get a parameter
   *
   * @param {String} key the key for the parameter
   * @throws ApplicationError.NotFound if the parameter is required and not set
   * @return {? | undefined} the parameter value, or undefined if it is not required and not set
   */
  Ravel.get = function(key) {
    if (!knownParameters[key]) {
      throw new ApplicationError.NotFound('Parameter \'' + name + '\' was requested, but is unknown.');
    } else if (knownParameters[key].required && params[key] === undefined) {
      throw new ApplicationError.NotFound('Known required parameter \'' + key + '\' was requested, but hasn\'t been defined yet.');
    } else if (params[key] === undefined) {
      l.w('Optional parameter \'' + key + '\' was requested, but is not defined.');
      return undefined;
    } else {
      return params[key];
    }
  };

  /**
   * Set a parameter
   *
   * @param {String} key the key for the parameter
   * @param {?} value the value for the parameter
   * @throws ApplicationError.IllegalValueError if key refers to an unregistered parameter
   * @return {?} the parameter value
   */
  Ravel.set = function(key, value) {
    if (knownParameters[key]) {
      params[key] = value;
    } else {
      throw new ApplicationError.IllegalValueError('Parameter \'' + key + '\' is not supported.');
    }
  };

  /**
   * Register a module with Ravel
   *
   * A module is a pure node.js javascript API consisting of functions with no
   * network-related functionality, suitable for unit-testing.
   *
   * Module should use injection to get what it needs
   *
   * @param {String} name The name of the module
   * @param {String} modulePath The path to the module
   *
   */
  Ravel.module = function(name, modulePath) {
    //if a module with this name has already been regsitered, error out
    if (moduleFactories[name]) {
      throw new ApplicationError.DuplicateEntryError('Module with name \'' + name + '\' has already been registered.');
    }

    var module = {};
    var methodBuilder = {
      add: function(methodName, handler) {
        if (module[methodName]) {
          throw new ApplicationError.DuplicateEntryError('Method with name \'' + methodName + '\' has already been registered.');
        }
        var transactionalMethodName = 't' + methodName[0].toUpperCase() + methodName.slice(1,methodName.length);
        module[transactionalMethodName] = handler;
        module[methodName] = Ravel.db.createTransactionEntryPoint(module[transactionalMethodName]);
      }
    };

    //save uninitialized module to Ravel.modules
    //so that it can be injected into other
    //modules and lazily instantiated
    Ravel.modules[name] = module;

    //build module instantiation function
    moduleFactories[name] = function() {
      var moduleInject = require(path.join(__dirname, modulePath));
      injector.inject({
        '$L': require('./lib/log')(name),
        '$MethodBuilder': methodBuilder
      },moduleInject);
    }
  };

  /**
   * Register a service with Ravel
   *
   * A service is a RESTful endpoint for a single Resource
   *
   * @param {String} basePath The base path of the all the Resource's endpoints
   * @param {String} servicePath the path of the service module to require(...)
   *
   */
  Ravel.service = function(basePath, servicePath) {
    //if a service with this name has already been regsitered, error out
    if (serviceFactories[basePath]) {
      throw new ApplicationError.DuplicateEntryError('Service with name \'' + name + '\' has already been registered.');
    }
    var endpointBuilder = {
      _methods: {}
    };
    var addMethod = function(method) {
      endpointBuilder[method] = function(secure, middleware) {
        if (endpointBuilder._methods[method]) {
          throw new ApplicationError.DuplicateEntryError('Method '+method+' has already been registered with service \''+serviceName+'\'');
        }
        endpointBuilder._methods[method] = {
          secure: secure,
          middleware: middleware
        };
        return endpointBuilder;
      }
    };
    addMethod('getAll');
    addMethod('postAll');
    addMethod('putAll');
    addMethod('deleteAll');
    addMethod('get');
    addMethod('post');
    addMethod('put');
    addMethod('delete');

    //build service instantiation function
    serviceFactories[basePath] = function(expressApp) {
      var serviceInject = require(path.join(__dirname, servicePath));
      injector.inject({
        '$L': require('./lib/log')(basePath),
        '$EndpointBuilder': endpointBuilder,
        '$Modules': Ravel.modules,
        '$Rest': rest
      }, serviceInject);
      //process all methods and add to express app
      var buildRoute = function(methodType, methodName) {
        var bp = basePath;
        if (methodName === 'get' || methodName === 'post' || methodName === 'put' || methodName === 'delete') {
          bp = path.join(basePath, '/:id');
        }
        //TODO integrate simple rest, give middleware a callback
        if (endpointBuilder._methods[methodName]) {
          if (endpointBuilder._methods[methodName].secure) {
            l.i('Registering secure service endpoint ' + methodType.toUpperCase() + ' ' + bp);
            expressApp[methodType](bp, Ravel.authorize, function(req, res) {
              endpointBuilder._methods[methodName].middleware(req, res);
            });
          } else {
            l.i('Registering public service endpoint ' + methodType.toUpperCase() + ' ' + bp);
            expressApp[methodType](bp, function(req, res) {
              endpointBuilder._methods[methodName].middleware(req, res);
            });
          }
        } else {
          //l.i('Registering unimplemented service endpoint ' + methodType.toUpperCase() + ' ' + bp);
          expressApp[methodType](bp, function(req, res) {
            res.status(rest.NOT_IMPLEMENTED).end();
          });
        }
      };
      buildRoute('get', 'getAll');
      buildRoute('post', 'postAll');
      buildRoute('put', 'putAll');
      buildRoute('delete', 'deleteAll');
      buildRoute('get', 'get');
      buildRoute('post', 'post');
      buildRoute('put', 'put');
      buildRoute('delete', 'delete');
    }
  };

  /**
   * Start the application
   */
  Ravel.start = function() {
    Ravel.db = require('./lib/database')(Ravel);
    Ravel.kvstore = require('./lib/kvstore')('ravel_prefix', Ravel);

    //App dependencies.
    var express = require('express');
    var session = require('express-session');
    var compression = require('compression');
    var favicon = require('serve-favicon');
    var cookieParser = require('cookie-parser');
    var http = require('http'); //https will be provided by reverse proxy
    var path = require('path');
    var passport = require('passport');
    var Primus = require('primus.io');
    var ExpressRedisStore = require('connect-redis')(session);

    //configure express
    var app = express();
    //configure redis session store
    var sessionStoreArgs = {
      host:Ravel.get('redis host'),
      port:Ravel.get('redis port'),
      db:0 //we stick to 0 because clustered redis doesn't support multiple dbs
    };
    if (Ravel.get('redis password')) {
      sessionStoreArgs.pass = Ravel.get('redis password');
    }
    var expressSessionStore = new ExpressRedisStore(sessionStoreArgs);

    app.set('domain', Ravel.get('node domain'));
    app.set('port', Ravel.get('node port'));
    app.set('app domain', Ravel.get('app domain'));
    app.set('app port', Ravel.get('app port'));
    app.enable('trust proxy');
    //configure views
    app.set('views', path.join(__dirname, Ravel.get('express view directory')));
    app.set('view engine', Ravel.get('express view engine'));
    //app.use(require('morgan')('dev')); //uncomment to see HTTP requests
    app.use(compression());
    if (Ravel.get('express favicon path')) {
      app.use(favicon(__dirname + Ravel.get('express favicon path')));
    }
    app.use(require('body-parser').json());
    app.use(require('method-override')());
    app.use(cookieParser(Ravel.get('express session secret')));
    app.use(session({
      store: expressSessionStore,
      secret:Ravel.get('express session secret'),
      resave:true,
      saveUninitialized:true
    }));
    //cross-site scripting protection, with mobile app support
    app.use(require('./lib/csrf')(Ravel));
    app.use(function(req, res, next){
      if (req.csrfToken) {
        res.locals.token = req.csrfToken();
      }
      next();
    });
    app.use(express.static(path.join(__dirname, Ravel.get('express public directory'))));
    app.use(require('connect-flash')());

    //initialize passport authentication
    app.use(passport.initialize());
    app.use(passport.session());
    require('./lib/passport_init.js')(Ravel, passport);
    Ravel.authorize = require('./lib/authorize_request')(Ravel, true);

    //create registered modules using factories
    for (var moduleName in moduleFactories) {
      moduleFactories[moduleName]();
    }

    //Create ExpressJS server
    var server = http.createServer(app);

    //Pass server to Primus to get it going on the same port
    //Initialize primus.io with room handling, etc.
    var primus = new Primus(server, { transformer: 'websockets', parser: 'JSON' });
    //TODO primus_init produces a configured, cluster-ready broadcasting library
    //var broadcast = require('./lib/primus_init.js')(app, lib, express, expressSessionStore, primus, db, kvstore);

    //create registered services using factories
    for (var serviceName in serviceFactories) {
      serviceFactories[serviceName](app);
    }

    //Start ExpressJS server
    server.listen(Ravel.get('node port'), function(){
      l.i("Application server at " + Ravel.get('node domain') + " listening on port " + Ravel.get('node port'));
    });
  };

  //Register known ravel parameters
  //redis parameters
  Ravel.registerSimpleParameter('redis host', true);
  Ravel.registerSimpleParameter('redis port', true);
  Ravel.registerSimpleParameter('redis password');
  //mysql parameters
  Ravel.registerSimpleParameter('mysql host', true);
  Ravel.registerSimpleParameter('mysql port', true);
  Ravel.registerSimpleParameter('mysql user', true);
  Ravel.registerSimpleParameter('mysql password', true);
  Ravel.registerSimpleParameter('mysql database name', true);
  Ravel.registerSimpleParameter('mysql connection pool size', true);
  //Node/express parameters
  Ravel.registerSimpleParameter('app domain', true);
  Ravel.registerSimpleParameter('app port', true);
  Ravel.registerSimpleParameter('node domain', true);
  Ravel.registerSimpleParameter('node port', true);
  Ravel.registerSimpleParameter('express public directory', true);
  Ravel.registerSimpleParameter('express view directory', true);
  Ravel.registerSimpleParameter('express view engine', true);
  Ravel.registerSimpleParameter('express favicon path');
  Ravel.registerSimpleParameter('express session secret', true);
  //Google OAuth parameters
  Ravel.registerSimpleParameter('google oauth2 web client id', true);
  Ravel.registerSimpleParameter('google oauth2 web client secret', true);
  Ravel.registerSimpleParameter('google oauth2 android client id');
  Ravel.registerSimpleParameter('google oauth2 ios client id');
  Ravel.registerSimpleParameter('google oauth2 ios client secret');
  //Passport parameters
  Ravel.registerSimpleParameter('get user function', true);
  Ravel.registerSimpleParameter('get or create user function', true);

  return Ravel;
};
<commit_msg>Making redis available to modules and services via injection as $KV<commit_after>var path = require('path');
var ApplicationError = require('./lib/application_error');
var l = require('./lib/log')('ravel');
var rest = require('./lib/rest');

module.exports = function() {
  var Ravel = {
    modules: {}
  };

  var moduleFactories = {};
  var serviceFactories = {};
  var knownParameters = {};
  var params = {};
  var injector = require('./lib/injector')(Ravel, moduleFactories, module.parent);

  //Change __dirname to current working directory of the
  //app using the ravel library, so that modules can be
  //loaded with relative paths.
  __dirname = process.cwd();

  /**
   * Register a parameter
   * @param {String} key the key for the parameter
   * @param {Boolean | undefined} required true, iff the parameter is required
   */
  Ravel.registerSimpleParameter = function(key, required) {
    knownParameters[key] = {
      required: required
    }
  };

  /**
   * Get a parameter
   *
   * @param {String} key the key for the parameter
   * @throws ApplicationError.NotFound if the parameter is required and not set
   * @return {? | undefined} the parameter value, or undefined if it is not required and not set
   */
  Ravel.get = function(key) {
    if (!knownParameters[key]) {
      throw new ApplicationError.NotFound('Parameter \'' + name + '\' was requested, but is unknown.');
    } else if (knownParameters[key].required && params[key] === undefined) {
      throw new ApplicationError.NotFound('Known required parameter \'' + key + '\' was requested, but hasn\'t been defined yet.');
    } else if (params[key] === undefined) {
      l.w('Optional parameter \'' + key + '\' was requested, but is not defined.');
      return undefined;
    } else {
      return params[key];
    }
  };

  /**
   * Set a parameter
   *
   * @param {String} key the key for the parameter
   * @param {?} value the value for the parameter
   * @throws ApplicationError.IllegalValueError if key refers to an unregistered parameter
   * @return {?} the parameter value
   */
  Ravel.set = function(key, value) {
    if (knownParameters[key]) {
      params[key] = value;
    } else {
      throw new ApplicationError.IllegalValueError('Parameter \'' + key + '\' is not supported.');
    }
  };

  /**
   * Register a module with Ravel
   *
   * A module is a pure node.js javascript API consisting of functions with no
   * network-related functionality, suitable for unit-testing.
   *
   * Module should use injection to get what it needs
   *
   * @param {String} name The name of the module
   * @param {String} modulePath The path to the module
   *
   */
  Ravel.module = function(name, modulePath) {
    //if a module with this name has already been regsitered, error out
    if (moduleFactories[name]) {
      throw new ApplicationError.DuplicateEntryError('Module with name \'' + name + '\' has already been registered.');
    }

    var module = {};
    var methodBuilder = {
      add: function(methodName, handler) {
        if (module[methodName]) {
          throw new ApplicationError.DuplicateEntryError('Method with name \'' + methodName + '\' has already been registered.');
        }
        var transactionalMethodName = 't' + methodName[0].toUpperCase() + methodName.slice(1,methodName.length);
        module[transactionalMethodName] = handler;
        module[methodName] = Ravel.db.createTransactionEntryPoint(module[transactionalMethodName]);
      }
    };

    //save uninitialized module to Ravel.modules
    //so that it can be injected into other
    //modules and lazily instantiated
    Ravel.modules[name] = module;

    //build module instantiation function
    moduleFactories[name] = function() {
      var moduleInject = require(path.join(__dirname, modulePath));
      injector.inject({
        '$L': require('./lib/log')(name),
        '$MethodBuilder': methodBuilder,
        '$KV': Ravel.kvstore
      },moduleInject);
    }
  };

  /**
   * Register a service with Ravel
   *
   * A service is a RESTful endpoint for a single Resource
   *
   * @param {String} basePath The base path of the all the Resource's endpoints
   * @param {String} servicePath the path of the service module to require(...)
   *
   */
  Ravel.service = function(basePath, servicePath) {
    //if a service with this name has already been regsitered, error out
    if (serviceFactories[basePath]) {
      throw new ApplicationError.DuplicateEntryError('Service with name \'' + name + '\' has already been registered.');
    }
    var endpointBuilder = {
      _methods: {}
    };
    var addMethod = function(method) {
      endpointBuilder[method] = function(secure, middleware) {
        if (endpointBuilder._methods[method]) {
          throw new ApplicationError.DuplicateEntryError('Method '+method+' has already been registered with service \''+serviceName+'\'');
        }
        endpointBuilder._methods[method] = {
          secure: secure,
          middleware: middleware
        };
        return endpointBuilder;
      }
    };
    addMethod('getAll');
    addMethod('postAll');
    addMethod('putAll');
    addMethod('deleteAll');
    addMethod('get');
    addMethod('post');
    addMethod('put');
    addMethod('delete');

    //build service instantiation function
    serviceFactories[basePath] = function(expressApp) {
      var serviceInject = require(path.join(__dirname, servicePath));
      injector.inject({
        '$L': require('./lib/log')(basePath),
        '$EndpointBuilder': endpointBuilder,
        '$Rest': rest,
        '$KV': Ravel.kvstore
      }, serviceInject);
      //process all methods and add to express app
      var buildRoute = function(methodType, methodName) {
        var bp = basePath;
        if (methodName === 'get' || methodName === 'post' || methodName === 'put' || methodName === 'delete') {
          bp = path.join(basePath, '/:id');
        }
        //TODO integrate simple rest, give middleware a callback
        if (endpointBuilder._methods[methodName]) {
          if (endpointBuilder._methods[methodName].secure) {
            l.i('Registering secure service endpoint ' + methodType.toUpperCase() + ' ' + bp);
            expressApp[methodType](bp, Ravel.authorize, function(req, res) {
              endpointBuilder._methods[methodName].middleware(req, res);
            });
          } else {
            l.i('Registering public service endpoint ' + methodType.toUpperCase() + ' ' + bp);
            expressApp[methodType](bp, function(req, res) {
              endpointBuilder._methods[methodName].middleware(req, res);
            });
          }
        } else {
          //l.i('Registering unimplemented service endpoint ' + methodType.toUpperCase() + ' ' + bp);
          expressApp[methodType](bp, function(req, res) {
            res.status(rest.NOT_IMPLEMENTED).end();
          });
        }
      };
      buildRoute('get', 'getAll');
      buildRoute('post', 'postAll');
      buildRoute('put', 'putAll');
      buildRoute('delete', 'deleteAll');
      buildRoute('get', 'get');
      buildRoute('post', 'post');
      buildRoute('put', 'put');
      buildRoute('delete', 'delete');
    }
  };

  /**
   * Start the application
   */
  Ravel.start = function() {
    Ravel.db = require('./lib/database')(Ravel);
    Ravel.kvstore = require('./lib/kvstore')('ravel_prefix', Ravel);

    //App dependencies.
    var express = require('express');
    var session = require('express-session');
    var compression = require('compression');
    var favicon = require('serve-favicon');
    var cookieParser = require('cookie-parser');
    var http = require('http'); //https will be provided by reverse proxy
    var path = require('path');
    var passport = require('passport');
    var Primus = require('primus.io');
    var ExpressRedisStore = require('connect-redis')(session);

    //configure express
    var app = express();
    //configure redis session store
    var sessionStoreArgs = {
      host:Ravel.get('redis host'),
      port:Ravel.get('redis port'),
      db:0 //we stick to 0 because clustered redis doesn't support multiple dbs
    };
    if (Ravel.get('redis password')) {
      sessionStoreArgs.pass = Ravel.get('redis password');
    }
    var expressSessionStore = new ExpressRedisStore(sessionStoreArgs);

    app.set('domain', Ravel.get('node domain'));
    app.set('port', Ravel.get('node port'));
    app.set('app domain', Ravel.get('app domain'));
    app.set('app port', Ravel.get('app port'));
    app.enable('trust proxy');
    //configure views
    app.set('views', path.join(__dirname, Ravel.get('express view directory')));
    app.set('view engine', Ravel.get('express view engine'));
    //app.use(require('morgan')('dev')); //uncomment to see HTTP requests
    app.use(compression());
    if (Ravel.get('express favicon path')) {
      app.use(favicon(__dirname + Ravel.get('express favicon path')));
    }
    app.use(require('body-parser').json());
    app.use(require('method-override')());
    app.use(cookieParser(Ravel.get('express session secret')));
    app.use(session({
      store: expressSessionStore,
      secret:Ravel.get('express session secret'),
      resave:true,
      saveUninitialized:true
    }));
    //cross-site scripting protection, with mobile app support
    app.use(require('./lib/csrf')(Ravel));
    app.use(function(req, res, next){
      if (req.csrfToken) {
        res.locals.token = req.csrfToken();
      }
      next();
    });
    app.use(express.static(path.join(__dirname, Ravel.get('express public directory'))));
    app.use(require('connect-flash')());

    //initialize passport authentication
    app.use(passport.initialize());
    app.use(passport.session());
    require('./lib/passport_init.js')(Ravel, passport);
    Ravel.authorize = require('./lib/authorize_request')(Ravel, true);

    //create registered modules using factories
    for (var moduleName in moduleFactories) {
      moduleFactories[moduleName]();
    }

    //Create ExpressJS server
    var server = http.createServer(app);

    //Pass server to Primus to get it going on the same port
    //Initialize primus.io with room handling, etc.
    var primus = new Primus(server, { transformer: 'websockets', parser: 'JSON' });
    //TODO primus_init produces a configured, cluster-ready broadcasting library
    //var broadcast = require('./lib/primus_init.js')(app, lib, express, expressSessionStore, primus, db, kvstore);

    //create registered services using factories
    for (var serviceName in serviceFactories) {
      serviceFactories[serviceName](app);
    }

    //Start ExpressJS server
    server.listen(Ravel.get('node port'), function(){
      l.i("Application server at " + Ravel.get('node domain') + " listening on port " + Ravel.get('node port'));
    });
  };

  //Register known ravel parameters
  //redis parameters
  Ravel.registerSimpleParameter('redis host', true);
  Ravel.registerSimpleParameter('redis port', true);
  Ravel.registerSimpleParameter('redis password');
  //mysql parameters
  Ravel.registerSimpleParameter('mysql host', true);
  Ravel.registerSimpleParameter('mysql port', true);
  Ravel.registerSimpleParameter('mysql user', true);
  Ravel.registerSimpleParameter('mysql password', true);
  Ravel.registerSimpleParameter('mysql database name', true);
  Ravel.registerSimpleParameter('mysql connection pool size', true);
  //Node/express parameters
  Ravel.registerSimpleParameter('app domain', true);
  Ravel.registerSimpleParameter('app port', true);
  Ravel.registerSimpleParameter('node domain', true);
  Ravel.registerSimpleParameter('node port', true);
  Ravel.registerSimpleParameter('express public directory', true);
  Ravel.registerSimpleParameter('express view directory', true);
  Ravel.registerSimpleParameter('express view engine', true);
  Ravel.registerSimpleParameter('express favicon path');
  Ravel.registerSimpleParameter('express session secret', true);
  //Google OAuth parameters
  Ravel.registerSimpleParameter('google oauth2 web client id', true);
  Ravel.registerSimpleParameter('google oauth2 web client secret', true);
  Ravel.registerSimpleParameter('google oauth2 android client id');
  Ravel.registerSimpleParameter('google oauth2 ios client id');
  Ravel.registerSimpleParameter('google oauth2 ios client secret');
  //Passport parameters
  Ravel.registerSimpleParameter('get user function', true);
  Ravel.registerSimpleParameter('get or create user function', true);

  return Ravel;
};
<|endoftext|>