<commit_before>var debug = require('debug')('rascal:Subscription')
var _ = require('lodash').mixin({ 'defaultsDeep': require('merge-defaults') })
var async = require('async')
var safeParse = require("safe-json-parse/callback")
var SubscriberSession = require('./SubscriberSession')

module.exports = {
    create: function(vhost, config, next) {
        return new Subscription(vhost, config).init(next)
    }
}

function Subscription(vhost, config) {

    var self = this

    this.init = function(next) {
        debug('Initialising subscription: %s', config.name)
        return next(null, self)
    }

    this.subscribe = function(overrides, next) {
        _subscribe(new SubscriberSession(), _.defaultsDeep(overrides, config), next)
    }

    function _subscribe(session, config, next) {
        debug('Subscribing to queue: %s', config.queue)
        vhost.getChannel(function(err, channel) {
            if (err) return next(err)
            if (config.prefetch) channel.prefetch(config.prefetch)

            channel.once('error', handleChannelError.bind(null, session, config))
            channel.connection.once('error', handleChannelError.bind(null, session, config))

            channel.consume(config.source, function(message) {
                if (!message) return // consume is called with a null message when the channel is torn down
                debug('Received message: %s from queue: %s', message.properties.messageId, config.queue)
                getContent(message, config, function(err, content) {
                    err ? session.emit('error', err)
                        : session.emit('message', message, content, ackOrNack.bind(null, channel, message))
                })
            }, config.options, function(err, response) {
                if (err) return next(err)
                session.open(channel, response.consumerTag)
                next(null, session)
            })
        })
    }

    function getContent(message, config, next) {
        var contentType = config.contentType || message.properties.contentType
        if (!contentType) return next(null, message.content)
        if (contentType === 'text/plain') return next(null, message.content.toString())
        if (contentType === 'application/json') return safeParse(new String(message.content), next)
    }

    function ackOrNack(channel, message, err, options) {
        if (arguments.length === 3) return ackOrNack(channel, message, err, {})
        if (err) return nack(channel, message, options)
        ack(channel, message)
    }

    function ack(channel, message) {
        debug('Acknowledging message: %s', message.properties.messageId)
        channel.ack(message)
    }

    function nack(channel, message, options) {
        debug('Not acknowledging message: %s with options:', message.properties.messageId, options)
        if (options.requeue && options.defer) return setTimeout(nack.bind(null, channel, message, { requeue: true }), options.defer).unref()
        channel.nack(message, false, !!options.requeue)
    }

    function handleChannelError(session, config, err) {
        debug('Handling channel error: %s from %s', err.message, config.name)
        session.emit('error', err)
        config.retry && _subscribe(session, config, function(err) {
            if (err) return setTimeout(handleChannelError.bind(null, session, config, err), config.retry.delay)
        })
    }
}

<commit_msg>Reintroducing setImmediate<commit_after>var debug = require('debug')('rascal:Subscription')
var _ = require('lodash').mixin({ 'defaultsDeep': require('merge-defaults') })
var async = require('async')
var safeParse = require("safe-json-parse/callback")
var SubscriberSession = require('./SubscriberSession')

module.exports = {
    create: function(vhost, config, next) {
        return new Subscription(vhost, config).init(next)
    }
}

function Subscription(vhost, config) {

    var self = this

    this.init = function(next) {
        debug('Initialising subscription: %s', config.name)
        return next(null, self)
    }

    this.subscribe = function(overrides, next) {
        _subscribe(new SubscriberSession(), _.defaultsDeep(overrides, config), next)
    }

    function _subscribe(session, config, next) {
        debug('Subscribing to queue: %s', config.queue)
        vhost.getChannel(function(err, channel) {
            if (err) return next(err)
            if (config.prefetch) channel.prefetch(config.prefetch)

            channel.once('error', handleChannelError.bind(null, session, config))
            channel.connection.once('error', handleChannelError.bind(null, session, config))

            channel.consume(config.source, function(message) {
                if (!message) return // consume is called with a null message when the channel is torn down
                debug('Received message: %s from queue: %s', message.properties.messageId, config.queue)
                getContent(message, config, function(err, content) {
                    setImmediate(function() {
                        err ? session.emit('error', err)
                            : session.emit('message', message, content, ackOrNack.bind(null, channel, message))
                    })
                })
            }, config.options, function(err, response) {
                if (err) return next(err)
                session.open(channel, response.consumerTag)
                next(null, session)
            })
        })
    }

    function getContent(message, config, next) {
        var contentType = config.contentType || message.properties.contentType
        if (!contentType) return next(null, message.content)
        if (contentType === 'text/plain') return next(null, message.content.toString())
        if (contentType === 'application/json') return safeParse(new String(message.content), next)
    }

    function ackOrNack(channel, message, err, options) {
        if (arguments.length === 3) return ackOrNack(channel, message, err, {})
        if (err) return nack(channel, message, options)
        ack(channel, message)
    }

    function ack(channel, message) {
        debug('Acknowledging message: %s', message.properties.messageId)
        channel.ack(message)
    }

    function nack(channel, message, options) {
        debug('Not acknowledging message: %s with options:', message.properties.messageId, options)
        if (options.requeue && options.defer) return setTimeout(nack.bind(null, channel, message, { requeue: true }), options.defer).unref()
        channel.nack(message, false, !!options.requeue)
    }

    function handleChannelError(session, config, err) {
        debug('Handling channel error: %s from %s', err.message, config.name)
        session.emit('error', err)
        config.retry && _subscribe(session, config, function(err) {
            if (err) return setTimeout(handleChannelError.bind(null, session, config, err), config.retry.delay)
        })
    }
}

<|endoftext|>


<commit_before>function createGraph1(chartData){
  var svg = d3.select('#graphs').append('svg').attr('width',500).attr('height',500);
  var chart = nv.models.lineChart()
                .margin({left: 100})  //Adjust chart margins to give the x-axis some breathing room.
                .useInteractiveGuideline(true)  //We want nice looking tooltips and a guideline!
                .showLegend(true)       //Show the legend, allowing users to turn on/off line series.
                .showYAxis(true)        //Show the y-axis
                .showXAxis(true)        //Show the x-axis
                .width(500)
                .height(500)
                .xDomain([chartData['x axis'].start,chartData['x axis'].end])
                //.yDomain([chartData['y axis'].start,chartData['y axis'].end])
  ;
  chart.xAxis     //Chart x-axis settings
      .axisLabel(chartData['x axis'].label);

  chart.yAxis     //Chart y-axis settings
      .axisLabel(chartData['y axis'].label);

  console.log(chartData);

  var lineData = chartData.data.map(function (d){return {values:d.data, key:d['line id']}}).sort(function(a,b){return a.key -b.key});
  console.log(lineData);
  svg
    .datum(lineData)
    .call(chart);

  //Update the chart when window resizes.
  nv.utils.windowResize(function() { chart.update() });
  return chart;
}<commit_msg>using specificed y axis max<commit_after>function createGraph1(chartData){
  var svg = d3.select('#graphs').append('svg').attr('width',500).attr('height',500);
  var chart = nv.models.lineChart()
                .margin({left: 100})  //Adjust chart margins to give the x-axis some breathing room.
                .useInteractiveGuideline(true)  //We want nice looking tooltips and a guideline!
                .showLegend(true)       //Show the legend, allowing users to turn on/off line series.
                .showYAxis(true)        //Show the y-axis
                .showXAxis(true)        //Show the x-axis
                .width(500)
                .height(500)
                .xDomain([chartData['x axis'].start,chartData['x axis'].end])
                .yDomain([chartData['y axis'].start,chartData['y axis'].end])
  ;
  chart.xAxis     //Chart x-axis settings
      .axisLabel(chartData['x axis'].label);

  chart.yAxis     //Chart y-axis settings
      .axisLabel(chartData['y axis'].label);

  console.log(chartData);

  var lineData = chartData.data.map(function (d){return {values:d.data, key:d['line id']}}).sort(function(a,b){return a.key -b.key});
  console.log(lineData);
  svg
    .datum(lineData)
    .call(chart);

  //Update the chart when window resizes.
  nv.utils.windowResize(function() { chart.update() });
  return chart;
}<|endoftext|>


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

/**
 * Internal dependencies
 */
import {
  findMatchingColor,
  findMatchingStylePreset,
  getShapePresets,
  getTextPresets,
  presetHasOpacity,
} from '../utils';
import { BACKGROUND_TEXT_MODE } from '../../../../constants';
import objectWithout from '../../../../utils/objectWithout';
import { TEXT_ELEMENT_DEFAULT_FONT } from '../../../../app/font/defaultFonts';

describe('Panels/StylePreset/utils', () => {
  const TEST_COLOR = {
    color: {
      r: 1,
      g: 1,
      b: 1,
    },
  };
  const TEST_COLOR_2 = {
    color: {
      r: 2,
      g: 2,
      b: 2,
    },
  };
  const STYLE_PRESET = {
    color: TEST_COLOR_2,
    backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,
    backgroundColor: TEST_COLOR,
    font: TEXT_ELEMENT_DEFAULT_FONT,
  };
  it('should return matching color object', () => {
    const stylePresets = {
      colors: [
        TEST_COLOR,
        {
          color: {
            r: 2,
            g: 2,
            b: 1,
          },
        },
      ],
    };
    const color = {
      color: {
        r: 1,
        g: 1,
        b: 1,
      },
    };
    expect(findMatchingColor(color, stylePresets, true)).toStrictEqual(color);
  });

  it('should return undefined when not finding matching color', () => {
    const stylePresets = {
      colors: [
        {
          color: {
            r: 1,
            g: 2,
            b: 3,
          },
        },
        {
          color: {
            r: 2,
            g: 2,
            b: 1,
          },
        },
      ],
    };
    expect(findMatchingColor(TEST_COLOR, stylePresets, true)).not.toBeDefined();
  });

  it('should return matching text style preset', () => {
    const stylePresets = {
      textStyles: [STYLE_PRESET],
    };
    const stylePreset = {
      color: {
        color: {
          r: 2,
          g: 2,
          b: 2,
        },
      },
      backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,
      backgroundColor: {
        color: {
          r: 1,
          g: 1,
          b: 1,
        },
      },
      font: TEXT_ELEMENT_DEFAULT_FONT,
    };
    expect(findMatchingStylePreset(stylePreset, stylePresets)).toStrictEqual(
      stylePreset
    );
  });

  it('should return not return non-matching text style preset', () => {
    const stylePresets = {
      textStyles: [STYLE_PRESET],
    };
    const stylePreset = {
      color: {
        color: {
          r: 1,
          g: 2,
          b: 2,
        },
      },
      backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,
      backgroundColor: {
        color: {
          r: 1,
          g: 1,
          b: 1,
        },
      },
      font: TEXT_ELEMENT_DEFAULT_FONT,
    };
    expect(
      findMatchingStylePreset(stylePreset, stylePresets)
    ).not.toBeDefined();
  });

  it('should get correct text style presets from selected elements', () => {
    const stylePreset = {
      ...STYLE_PRESET,
      font: {
        family: 'Foo',
        fallbacks: ['Bar'],
      },
    };
    const elements = [
      {
        type: 'text',
        backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,
        font: TEXT_ELEMENT_DEFAULT_FONT,
        foo: 'bar',
        padding: {
          vertical: 0,
          horizontal: 0,
        },
        content: 'Content',
      },
      {
        type: 'text',
        x: 30,
        content:
          'Content',
        ...objectWithout(stylePreset, ['color']),
      },
    ];
    const stylePresets = {
      textStyles: [],
      colors: [],
    };
    const expected = {
      colors: [],
      textStyles: [
        {
          backgroundTextMode: 'NONE',
          color: TEST_COLOR,
          font: TEXT_ELEMENT_DEFAULT_FONT,
          fontWeight: 400,
          isItalic: false,
          isUnderline: false,
          letterSpacing: 0,
          padding: {
            horizontal: 0,
            vertical: 0,
          },
        },
        {
          backgroundColor: TEST_COLOR,
          backgroundTextMode: 'FILL',
          color: TEST_COLOR_2,
          font: {
            fallbacks: ['Bar'],
            family: 'Foo',
          },
          fontWeight: 700,
          isItalic: true,
          isUnderline: false,
          letterSpacing: 0,
        },
      ],
    };
    const presets = getTextPresets(elements, stylePresets, 'style');
    expect(presets).toStrictEqual(expected);
  });

  it('should ignore text color presets for multi-color text fields', () => {
    const elements = [
      {
        type: 'text',
        backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,
        font: TEXT_ELEMENT_DEFAULT_FONT,
        content:
          'OK',
      },
    ];
    const stylePresets = {
      textStyles: [],
      colors: [],
    };
    const expected = {
      colors: [],
      textStyles: [],
    };
    const presets = getTextPresets(elements, stylePresets, 'color');
    expect(presets).toStrictEqual(expected);
  });

  it('should use black color when adding text style preset for multi-color text fields', () => {
    const stylePreset = {
      ...STYLE_PRESET,
      fontWeight: 400,
      isItalic: false,
      isUnderline: false,
      letterSpacing: 0,
      font: {
        family: 'Foo',
        fallbacks: ['Bar'],
      },
    };
    const elements = [
      {
        type: 'text',
        x: 30,
        content:
          'OK',
        ...objectWithout(stylePreset, ['color']),
      },
    ];
    const stylePresets = {
      textStyles: [],
      fillColors: [],
    };
    const expected = {
      colors: [],
      textStyles: [
        {
          ...stylePreset,
          color: { color: { r: 0, g: 0, b: 0 } },
        },
      ],
    };
    const presets = getTextPresets(elements, stylePresets, 'style');
    expect(presets).toStrictEqual(expected);
  });

  it('should get corect font weight for text preset', () => {
    const elements = [
      {
        type: 'text',
        backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,
        font: TEXT_ELEMENT_DEFAULT_FONT,
        content: 'Semi-bold',
      },
    ];
    const stylePresets = {
      textStyles: [],
      colors: [],
    };
    const expected = {
      colors: [],
      textStyles: [
        {
          backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,
          font: TEXT_ELEMENT_DEFAULT_FONT,
          color: { color: { r: 0, g: 0, b: 0 } },
          fontWeight: 600,
          isItalic: false,
          isUnderline: false,
          letterSpacing: 0,
        },
      ],
    };
    const presets = getTextPresets(elements, stylePresets, 'style');
    expect(presets).toStrictEqual(expected);
  });

  it('should default to null/false when adding text style preset for mixed inline styles', () => {
    const stylePreset = {
      ...STYLE_PRESET,
      fontWeight: null,
      isItalic: false,
      isUnderline: false,
      letterSpacing: null,
      font: {
        family: 'Foo',
        fallbacks: ['Bar'],
      },
    };
    const elements = [
      {
        type: 'text',
        x: 30,
        content:
          'OK',
        ...objectWithout(stylePreset, ['color']),
      },
    ];
    const stylePresets = {
      textStyles: [],
      fillColors: [],
    };
    const expected = {
      colors: [],
      textStyles: [
        {
          ...stylePreset,
          color: { color: { r: 0, g: 0, b: 0 } },
        },
      ],
    };
    const presets = getTextPresets(elements, stylePresets, 'style');
    expect(presets).toStrictEqual(expected);
  });

  it('should not consider existing presets as new', () => {
    const stylePreset = {
      ...STYLE_PRESET,
      font: {
        family: 'Foo',
        fallbacks: ['Bar'],
      },
    };
    const elements = [
      {
        type: 'text',
        backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,
        font: TEXT_ELEMENT_DEFAULT_FONT,
        foo: 'bar',
        content: 'Content',
        padding: {
          vertical: 0,
          horizontal: 0,
        },
      },
      {
        type: 'text',
        x: 30,
        content: 'Content',
        ...objectWithout(stylePreset, ['color']),
      },
    ];
    const colorPresets = {
      colors: [TEST_COLOR, TEST_COLOR_2],
    };
    const expected = {
      colors: [],
      textStyles: [],
    };
    const presets = getTextPresets(elements, colorPresets, 'color');
    expect(presets).toStrictEqual(expected);
  });

  it('should get correct shape presets from selected elements', () => {
    const elements = [
      {
        type: 'shape',
        backgroundColor: TEST_COLOR,
      },
      {
        type: 'shape',
        backgroundColor: TEST_COLOR_2,
      },
    ];
    const stylePresets = {
      textStyles: [],
      colors: [],
    };
    const expected = {
      colors: [TEST_COLOR, TEST_COLOR_2],
    };
    const presets = getShapePresets(elements, stylePresets);
    expect(presets).toStrictEqual(expected);
  });

  it('should detect opacity in preset correctly', () => {
    expect(presetHasOpacity(TEST_COLOR)).toBeFalse();
    const preset1 = {
      color: {
        r: 1,
        g: 1,
        b: 1,
        a: 0.5,
      },
    };
    expect(presetHasOpacity(preset1)).toBeTrue();

    const preset2 = {
      type: 'linear',
      stops: [TEST_COLOR, preset1],
    };
    expect(presetHasOpacity(preset2)).toBeTrue();

    const preset3 = {
      type: 'linear',
      stops: [TEST_COLOR, TEST_COLOR_2],
    };
    expect(presetHasOpacity(preset3)).toBeFalse();
  });
});
<commit_msg>Fixed typo<commit_after>/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Internal dependencies
 */
import {
  findMatchingColor,
  findMatchingStylePreset,
  getShapePresets,
  getTextPresets,
  presetHasOpacity,
} from '../utils';
import { BACKGROUND_TEXT_MODE } from '../../../../constants';
import objectWithout from '../../../../utils/objectWithout';
import { TEXT_ELEMENT_DEFAULT_FONT } from '../../../../app/font/defaultFonts';

describe('Panels/StylePreset/utils', () => {
  const TEST_COLOR = {
    color: {
      r: 1,
      g: 1,
      b: 1,
    },
  };
  const TEST_COLOR_2 = {
    color: {
      r: 2,
      g: 2,
      b: 2,
    },
  };
  const STYLE_PRESET = {
    color: TEST_COLOR_2,
    backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,
    backgroundColor: TEST_COLOR,
    font: TEXT_ELEMENT_DEFAULT_FONT,
  };
  it('should return matching color object', () => {
    const stylePresets = {
      colors: [
        TEST_COLOR,
        {
          color: {
            r: 2,
            g: 2,
            b: 1,
          },
        },
      ],
    };
    const color = {
      color: {
        r: 1,
        g: 1,
        b: 1,
      },
    };
    expect(findMatchingColor(color, stylePresets, true)).toStrictEqual(color);
  });

  it('should return undefined when not finding matching color', () => {
    const stylePresets = {
      colors: [
        {
          color: {
            r: 1,
            g: 2,
            b: 3,
          },
        },
        {
          color: {
            r: 2,
            g: 2,
            b: 1,
          },
        },
      ],
    };
    expect(findMatchingColor(TEST_COLOR, stylePresets, true)).not.toBeDefined();
  });

  it('should return matching text style preset', () => {
    const stylePresets = {
      textStyles: [STYLE_PRESET],
    };
    const stylePreset = {
      color: {
        color: {
          r: 2,
          g: 2,
          b: 2,
        },
      },
      backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,
      backgroundColor: {
        color: {
          r: 1,
          g: 1,
          b: 1,
        },
      },
      font: TEXT_ELEMENT_DEFAULT_FONT,
    };
    expect(findMatchingStylePreset(stylePreset, stylePresets)).toStrictEqual(
      stylePreset
    );
  });

  it('should return not return non-matching text style preset', () => {
    const stylePresets = {
      textStyles: [STYLE_PRESET],
    };
    const stylePreset = {
      color: {
        color: {
          r: 1,
          g: 2,
          b: 2,
        },
      },
      backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,
      backgroundColor: {
        color: {
          r: 1,
          g: 1,
          b: 1,
        },
      },
      font: TEXT_ELEMENT_DEFAULT_FONT,
    };
    expect(
      findMatchingStylePreset(stylePreset, stylePresets)
    ).not.toBeDefined();
  });

  it('should get correct text style presets from selected elements', () => {
    const stylePreset = {
      ...STYLE_PRESET,
      font: {
        family: 'Foo',
        fallbacks: ['Bar'],
      },
    };
    const elements = [
      {
        type: 'text',
        backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,
        font: TEXT_ELEMENT_DEFAULT_FONT,
        foo: 'bar',
        padding: {
          vertical: 0,
          horizontal: 0,
        },
        content: 'Content',
      },
      {
        type: 'text',
        x: 30,
        content:
          'Content',
        ...objectWithout(stylePreset, ['color']),
      },
    ];
    const stylePresets = {
      textStyles: [],
      colors: [],
    };
    const expected = {
      colors: [],
      textStyles: [
        {
          backgroundTextMode: 'NONE',
          color: TEST_COLOR,
          font: TEXT_ELEMENT_DEFAULT_FONT,
          fontWeight: 400,
          isItalic: false,
          isUnderline: false,
          letterSpacing: 0,
          padding: {
            horizontal: 0,
            vertical: 0,
          },
        },
        {
          backgroundColor: TEST_COLOR,
          backgroundTextMode: 'FILL',
          color: TEST_COLOR_2,
          font: {
            fallbacks: ['Bar'],
            family: 'Foo',
          },
          fontWeight: 700,
          isItalic: true,
          isUnderline: false,
          letterSpacing: 0,
        },
      ],
    };
    const presets = getTextPresets(elements, stylePresets, 'style');
    expect(presets).toStrictEqual(expected);
  });

  it('should ignore text color presets for multi-color text fields', () => {
    const elements = [
      {
        type: 'text',
        backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,
        font: TEXT_ELEMENT_DEFAULT_FONT,
        content:
          'OK',
      },
    ];
    const stylePresets = {
      textStyles: [],
      colors: [],
    };
    const expected = {
      colors: [],
      textStyles: [],
    };
    const presets = getTextPresets(elements, stylePresets, 'color');
    expect(presets).toStrictEqual(expected);
  });

  it('should use black color when adding text style preset for multi-color text fields', () => {
    const stylePreset = {
      ...STYLE_PRESET,
      fontWeight: 400,
      isItalic: false,
      isUnderline: false,
      letterSpacing: 0,
      font: {
        family: 'Foo',
        fallbacks: ['Bar'],
      },
    };
    const elements = [
      {
        type: 'text',
        x: 30,
        content:
          'OK',
        ...objectWithout(stylePreset, ['color']),
      },
    ];
    const stylePresets = {
      textStyles: [],
      fillColors: [],
    };
    const expected = {
      colors: [],
      textStyles: [
        {
          ...stylePreset,
          color: { color: { r: 0, g: 0, b: 0 } },
        },
      ],
    };
    const presets = getTextPresets(elements, stylePresets, 'style');
    expect(presets).toStrictEqual(expected);
  });

  it('should get correct font weight for text preset', () => {
    const elements = [
      {
        type: 'text',
        backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,
        font: TEXT_ELEMENT_DEFAULT_FONT,
        content: 'Semi-bold',
      },
    ];
    const stylePresets = {
      textStyles: [],
      colors: [],
    };
    const expected = {
      colors: [],
      textStyles: [
        {
          backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,
          font: TEXT_ELEMENT_DEFAULT_FONT,
          color: { color: { r: 0, g: 0, b: 0 } },
          fontWeight: 600,
          isItalic: false,
          isUnderline: false,
          letterSpacing: 0,
        },
      ],
    };
    const presets = getTextPresets(elements, stylePresets, 'style');
    expect(presets).toStrictEqual(expected);
  });

  it('should default to null/false when adding text style preset for mixed inline styles', () => {
    const stylePreset = {
      ...STYLE_PRESET,
      fontWeight: null,
      isItalic: false,
      isUnderline: false,
      letterSpacing: null,
      font: {
        family: 'Foo',
        fallbacks: ['Bar'],
      },
    };
    const elements = [
      {
        type: 'text',
        x: 30,
        content:
          'OK',
        ...objectWithout(stylePreset, ['color']),
      },
    ];
    const stylePresets = {
      textStyles: [],
      fillColors: [],
    };
    const expected = {
      colors: [],
      textStyles: [
        {
          ...stylePreset,
          color: { color: { r: 0, g: 0, b: 0 } },
        },
      ],
    };
    const presets = getTextPresets(elements, stylePresets, 'style');
    expect(presets).toStrictEqual(expected);
  });

  it('should not consider existing presets as new', () => {
    const stylePreset = {
      ...STYLE_PRESET,
      font: {
        family: 'Foo',
        fallbacks: ['Bar'],
      },
    };
    const elements = [
      {
        type: 'text',
        backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,
        font: TEXT_ELEMENT_DEFAULT_FONT,
        foo: 'bar',
        content: 'Content',
        padding: {
          vertical: 0,
          horizontal: 0,
        },
      },
      {
        type: 'text',
        x: 30,
        content: 'Content',
        ...objectWithout(stylePreset, ['color']),
      },
    ];
    const colorPresets = {
      colors: [TEST_COLOR, TEST_COLOR_2],
    };
    const expected = {
      colors: [],
      textStyles: [],
    };
    const presets = getTextPresets(elements, colorPresets, 'color');
    expect(presets).toStrictEqual(expected);
  });

  it('should get correct shape presets from selected elements', () => {
    const elements = [
      {
        type: 'shape',
        backgroundColor: TEST_COLOR,
      },
      {
        type: 'shape',
        backgroundColor: TEST_COLOR_2,
      },
    ];
    const stylePresets = {
      textStyles: [],
      colors: [],
    };
    const expected = {
      colors: [TEST_COLOR, TEST_COLOR_2],
    };
    const presets = getShapePresets(elements, stylePresets);
    expect(presets).toStrictEqual(expected);
  });

  it('should detect opacity in preset correctly', () => {
    expect(presetHasOpacity(TEST_COLOR)).toBeFalse();
    const preset1 = {
      color: {
        r: 1,
        g: 1,
        b: 1,
        a: 0.5,
      },
    };
    expect(presetHasOpacity(preset1)).toBeTrue();

    const preset2 = {
      type: 'linear',
      stops: [TEST_COLOR, preset1],
    };
    expect(presetHasOpacity(preset2)).toBeTrue();

    const preset3 = {
      type: 'linear',
      stops: [TEST_COLOR, TEST_COLOR_2],
    };
    expect(presetHasOpacity(preset3)).toBeFalse();
  });
});
<|endoftext|>


<commit_before>var models = require('./../../app/models')
  , redis = require('redis')
  , async = require('async')
  , configLocal = require('./../../conf/envLocal.js')
  , fs = require("fs")
  , ejs = require("ejs")
  , mailer = require('./email-identification-mailer.js');

exports.listen = function() {
  var conf = configLocal.getMailerConfig();

  fs.readFile('app/scripts/views/mailer/index.ejs', 'utf8', function (err, template) {
    if (err)
      return console.log(err);

    var htmlTemplate = template
    var sub = redis.createClient();

    sub.subscribe('newPost', 'newComment', 'newLike')

    sub.on('message', function(channel, msg) {
      switch(channel) {
      case 'newPost':
        var data = JSON.parse(msg);
        models.Post.findById(data.postId, function(err, post) {
          if (!post)
            return

          models.Timeline.findById(data.timelineId, {}, function(err, timeline) {
            if (!timeline || timeline.name !== 'River of news')
              return

            models.User.findById(timeline.userId, function(err, user) {
              models.User.findById(post.userId, function(err, owner) {
                if (!user || user.type === 'group' ||
                    !user.info || user.info.receiveEmails !== '0' ||
                    !user.info.email || user.id === post.userId) return

                html = ejs.render(htmlTemplate, {
                  screenName: owner.info.screenName,
                  username: owner.username,
                  post: post.body,
                  conf: conf,
                  post_id: post.id,
                  likes: [],
                  comments: []
                })

                var messageToSend = {
                  to: user.info.screenName + ' <' + user.info.email + '>',
                  subject: post.body.truncate(50),
                  html: html
                };
                mailer.sendMailToUser(conf, messageToSend)
              })
            })
          })
        })
        break

      case 'newComment':
        var data = JSON.parse(msg);
        if (data.inRiverOfNews !== 1 || !data.timelineId) return

        models.Comment.findById(data.commentId, function(err, comment) {
          if (!comment) return

          models.Post.findById(comment.postId, function(err, post) {
            if (!post) return

            models.Timeline.findById(data.timelineId, {}, function(err, timeline) {
              if (!timeline || !timeline.userId ||
                  timeline.name !== 'River of news') return

              models.User.findById(timeline.userId, function(err, user) {
                models.User.findById(post.userId, function(err, owner) {
                  if (!user || user.id === post.userId ||
                      user.type === 'group' ||
                      user.info === null || user.info.receiveEmails !== '0' ||
                      !user.info.email) return

                  post.getComments(function(err, comments) {
                    html = ejs.render(htmlTemplate, {
                      screenName: owner.info.screenName,
                      username: owner.username,
                      post: post.body,
                      conf: conf,
                      post_id: post.id,
                      comments: comments
                    })

                    var messageToSend = {
                      to: user.info.screenName + ' <' + user.info.email + '>',
                      subject: post.body.truncate(50),
                      html: html
                    };
                    mailer.sendMailToUser(conf, messageToSend)
                  })
                })
              })
            })
          })
        })

        break

      case 'newLike':
        var data = JSON.parse(msg);
        if (data.inRiverOfNews !== 1 || !data.timelineId)
          return

        models.Post.findById(data.postId, function(err, post) {
          if (!post) return

          models.Timeline.findById(data.timelineId, {}, function(err, timeline) {
            if (!timeline || !timeline.userId || timeline.name !== 'River of news')
              return

            models.User.findById(timeline.userId, function(err, user) {
              models.User.findById(post.userId, function(err, owner) {
                if (!user || user.id === post.userId || user.type === 'group' ||
                    !user.info || user.info.receiveEmails !== '0') return

                post.getComments(function(err, comments) {
                  html = ejs.render(htmlTemplate, {
                    screenName: owner.info.screenName,
                    username: owner.username,
                    post: post.body,
                    conf: conf,
                    post_id: post.id,
                    comments: post.comments
                  })

                  var messageToSend = {
                    to: user.info.screenName + ' <' + user.info.email + '>',
                    subject: post.body.truncate(50),
                    html: htmlTemplate
                  };
                  mailer.sendMailToUser(conf, messageToSend)
                })
              })
            })
          })
        })
        break
      }
    })
  });
}
<commit_msg>Fixes an error when mail server sends template instead of real content.<commit_after>var models = require('./../../app/models')
  , redis = require('redis')
  , async = require('async')
  , configLocal = require('./../../conf/envLocal.js')
  , fs = require("fs")
  , ejs = require("ejs")
  , mailer = require('./email-identification-mailer.js');

exports.listen = function() {
  var conf = configLocal.getMailerConfig();

  fs.readFile('app/scripts/views/mailer/index.ejs', 'utf8', function (err, template) {
    if (err)
      return console.log(err);

    var htmlTemplate = template
    var sub = redis.createClient();

    sub.subscribe('newPost', 'newComment', 'newLike')

    sub.on('message', function(channel, msg) {
      switch(channel) {
      case 'newPost':
        var data = JSON.parse(msg);
        models.Post.findById(data.postId, function(err, post) {
          if (!post)
            return

          models.Timeline.findById(data.timelineId, {}, function(err, timeline) {
            if (!timeline || timeline.name !== 'River of news')
              return

            models.User.findById(timeline.userId, function(err, user) {
              models.User.findById(post.userId, function(err, owner) {
                if (!user || user.type === 'group' ||
                    !user.info || user.info.receiveEmails !== '0' ||
                    !user.info.email || user.id === post.userId) return

                html = ejs.render(htmlTemplate, {
                  screenName: owner.info.screenName,
                  username: owner.username,
                  post: post.body,
                  conf: conf,
                  post_id: post.id,
                  likes: [],
                  comments: []
                })

                var messageToSend = {
                  to: user.info.screenName + ' <' + user.info.email + '>',
                  subject: post.body.truncate(50),
                  html: html
                };
                mailer.sendMailToUser(conf, messageToSend)
              })
            })
          })
        })
        break

      case 'newComment':
        var data = JSON.parse(msg);
        if (data.inRiverOfNews !== 1 || !data.timelineId) return

        models.Comment.findById(data.commentId, function(err, comment) {
          if (!comment) return

          models.Post.findById(comment.postId, function(err, post) {
            if (!post) return

            models.Timeline.findById(data.timelineId, {}, function(err, timeline) {
              if (!timeline || !timeline.userId ||
                  timeline.name !== 'River of news') return

              models.User.findById(timeline.userId, function(err, user) {
                models.User.findById(post.userId, function(err, owner) {
                  if (!user || user.id === post.userId ||
                      user.type === 'group' ||
                      user.info === null || user.info.receiveEmails !== '0' ||
                      !user.info.email) return

                  post.getComments(function(err, comments) {
                    html = ejs.render(htmlTemplate, {
                      screenName: owner.info.screenName,
                      username: owner.username,
                      post: post.body,
                      conf: conf,
                      post_id: post.id,
                      comments: comments
                    })

                    var messageToSend = {
                      to: user.info.screenName + ' <' + user.info.email + '>',
                      subject: post.body.truncate(50),
                      html: html
                    };
                    mailer.sendMailToUser(conf, messageToSend)
                  })
                })
              })
            })
          })
        })

        break

      case 'newLike':
        var data = JSON.parse(msg);
        if (data.inRiverOfNews !== 1 || !data.timelineId)
          return

        models.Post.findById(data.postId, function(err, post) {
          if (!post) return

          models.Timeline.findById(data.timelineId, {}, function(err, timeline) {
            if (!timeline || !timeline.userId || timeline.name !== 'River of news')
              return

            models.User.findById(timeline.userId, function(err, user) {
              models.User.findById(post.userId, function(err, owner) {
                if (!user || user.id === post.userId || user.type === 'group' ||
                    !user.info || user.info.receiveEmails !== '0') return

                post.getComments(function(err, comments) {
                  html = ejs.render(htmlTemplate, {
                    screenName: owner.info.screenName,
                    username: owner.username,
                    post: post.body,
                    conf: conf,
                    post_id: post.id,
                    comments: post.comments
                  })

                  var messageToSend = {
                    to: user.info.screenName + ' <' + user.info.email + '>',
                    subject: post.body.truncate(50),
                    html: html
                  };
                  mailer.sendMailToUser(conf, messageToSend)
                })
              })
            })
          })
        })
        break
      }
    })
  });
}
<|endoftext|>


<commit_before>$(function()
{
  $('#sympal_toggle_editor').css('height', $('#sympal_editor').css('height'));

  if ($.cookie('sympal_editor_open') === null)
  {
    $.cookie('sympal_editor_open', 'false');
  }

  if ($.cookie('sympal_editor_open') == 'true')
  {
    $('div#sympal_editor').css({marginLeft:'-20px'});
  }

  hiConfig = {
      sensitivity: 1, // number = sensitivity threshold (must be 1 or higher)
      interval: 100, // number = milliseconds for onMouseOver polling interval
      timeout: 100, // number = milliseconds delay before onMouseOut
      over: function() {
          if ($.cookie('sympal_editor_open') == 'true')
          {
            $.cookie('sympal_editor_open', 'false');
            $('div#sympal_editor').animate({marginLeft:'-500px'}, 'slow');
          }
          else
          {
            $.cookie('sympal_editor_open', 'true');
            $('div#sympal_editor').animate({marginLeft:'-20px'}, 'slow');
          }

      }
  }
  $('#sympal_toggle_editor').hoverIntent(hiConfig);

  $('.sympal_inline_edit_bar_buttons').hide();

  if (location.hash == '#edit')
  {
    toggleEditMode();
  }

  var enabled = false;

  function toggleEditMode()
  {
    enabled = enabled ? false : true;

    $('.sympal_content_slot .editor').toggle();
    $($(this).parent().get(0)).find('.editor input, .editor textarea, .editor select:first').focus();

    $('.sympal_content_slot .value').toggle();

    if (enabled)
    {
      enabled = false;
      $('a.toggle_edit_mode').hide();
      $('.sympal_inline_edit_bar_buttons').show();
    }
  }

  $('.toggle_edit_mode').click(function() {
    toggleEditMode();
  });

  $('.sympal_change_slot_type').click(function() {
    $('.sympal_change_slot_type_dropdown').slideToggle();
  });

  $('.sympal_change_slot_type_dropdown select').change(function() {
    var select = $(this);
    var form = $(this.form);
    var url = form.attr('action').replace('edit', 'change').replace('/save', '');
    form.ajaxSubmit({
      url: url,
      target: form.parents('.sympal_content_slot').find('.editor .sympal_content_slot_editor_form'),
      success: select.parents('.sympal_change_slot_type_dropdown').slideToggle()
    });
  });

  $('.sympal_save_content_slots').click(function() {
    $('.sympal_content_slot form').each(function() {
      var form = $(this);
      $(this).ajaxSubmit({
        target: form.parents('.sympal_content_slot').find('.value')
      });
    });
    $('.sympal_content_slot .editor').toggle();
    $('.sympal_content_slot .value').toggle();

    $('a.toggle_edit_mode').show();
    $('.sympal_inline_edit_bar_buttons').hide();
    location.hash = '';
  });

  $('.sympal_preview_content_slots').click(function() {
    $('.sympal_content_slot form').each(function() {
      var form = $(this);
      var url = form.attr('action').replace('edit', 'preview').replace('/save', '');
      $(this).ajaxSubmit({
        url: url,
        target: form.parents('.sympal_content_slot').find('.value')
      });
      location.hash = '';
    });
    $('.sympal_content_slot .editor').toggle();
    $('.sympal_content_slot .value').toggle();

    $('a.toggle_edit_mode').show();
    $('.sympal_inline_edit_bar_buttons').hide();
  });
});<commit_msg>[1.4][sfSympalPlugin][0.7] Js fixes for editor and added comments<commit_after>$(function()
{
  // Initialize sympal editor on left side of screen for content records
  // It shows when you hover over the bar on the left side of the screen
  $('#sympal_toggle_editor').css('height', $('#sympal_editor').css('height'));

  // Remember the state of the panel with a cokie
  if ($.cookie('sympal_editor_open') === null)
  {
    $.cookie('sympal_editor_open', 'false');
  }

  if ($.cookie('sympal_editor_open') == 'true')
  {
    $('div#sympal_editor').css({marginLeft:'-20px'});
  }

  // Setup hover intent for the bar
  hiConfig = {
      sensitivity: 1, // number = sensitivity threshold (must be 1 or higher)
      interval: 100, // number = milliseconds for onMouseOver polling interval
      timeout: 100, // number = milliseconds delay before onMouseOut
      over: function() {
          if ($.cookie('sympal_editor_open') == 'true')
          {
            $.cookie('sympal_editor_open', 'false');
            $('div#sympal_editor').animate({marginLeft:'-500px'}, 'slow');
          }
          else
          {
            $.cookie('sympal_editor_open', 'true');
            $('div#sympal_editor').animate({marginLeft:'-20px'}, 'slow');
          }

      }
  }
  $('#sympal_toggle_editor').hoverIntent(hiConfig);

  // Hide the inline edit bar buttons by default
  // These are the Save and Preview buttons which will be shown when the user
  // clicks Edit
  $('.sympal_inline_edit_bar_buttons').hide();

  // If url hash is #edit lets enable edit mode
  if (location.hash == '#edit')
  {
    toggleEditMode();
  }

  // Function to toggle edit mode on and off
  var enabled = false;
  function toggleEditMode(clicked)
  {
    enabled = enabled ? false : true;

    // Toggle the editor state
    $('.sympal_content_slot .editor').toggle();

    if (clicked)
    {
      // Focus on the form element that was clicked to enable inline editing
      $($(clicked).parent().get(0)).find('.editor input, .editor textarea, .editor select:first').focus();
    }

    // Toggle the value state
    $('.sympal_content_slot .value').toggle();

    // If the state is being enabled then lets change the inline edit bar buttons and link
    if (enabled)
    {
      enabled = false;
      $('a.toggle_edit_mode').hide();
      $('.sympal_inline_edit_bar_buttons').show();
    }
  }

  // When an element with class="toggle_edit_mode" is clicked toggle edit mode
  $('.toggle_edit_mode').click(function() {
    toggleEditMode(this);
  });

  // Show the change slot type dropdown when class="sympal_change_slot_type" is clicked
  $('.sympal_change_slot_type').click(function() {
    $('.sympal_change_slot_type_dropdown').slideToggle();
  });

  // Update the editor widget for this slot when the dropdown is changed
  $('.sympal_change_slot_type_dropdown select').change(function() {
    var select = $(this);
    var form = $(this.form);
    var url = form.attr('action').replace('edit', 'change').replace('/save', '');
    form.ajaxSubmit({
      url: url,
      target: form.parents('.sympal_content_slot').find('.editor .sympal_content_slot_editor_form'),
      success: select.parents('.sympal_change_slot_type_dropdown').slideToggle()
    });
  });

  // Save all the slots on the page
  $('.sympal_save_content_slots').click(function() {
    // Save each content slot form
    $('.sympal_content_slot form').each(function() {
      var form = $(this);
      $(this).ajaxSubmit({
        target: form.parents('.sympal_content_slot').find('.value')
      });
    });
    // Toggle the editor and value states
    $('.sympal_content_slot .editor').toggle();
    $('.sympal_content_slot .value').toggle();

    // Update the inline edit bar buttons and links
    $('a.toggle_edit_mode').show();
    $('.sympal_inline_edit_bar_buttons').hide();
    location.hash = '';
  });

  // Render a preview of all the slots
  $('.sympal_preview_content_slots').click(function() {
    // Submit each slot form to render a preview
    $('.sympal_content_slot form').each(function() {
      var form = $(this);
      var url = form.attr('action').replace('edit', 'preview').replace('/save', '');
      $(this).ajaxSubmit({
        url: url,
        target: form.parents('.sympal_content_slot').find('.value')
      });
      location.hash = '';
    });
    // Toggle the editor and value states
    $('.sympal_content_slot .editor').toggle();
    $('.sympal_content_slot .value').toggle();

    // Update the inline edit bar buttons and links
    $('a.toggle_edit_mode').show();
    $('.sympal_inline_edit_bar_buttons').hide();
  });
});<|endoftext|>


<commit_before>/*
 * simple-gallery.js - v1.0.0
 * Author: Alex Kalicki (https://github.com/akalicki)
 *
 * simple-gallery.js is a lightweight jQuery extension for quickly creating
 * highly customizable photo galleries using standard jQuery notation.
 *
 * All work contained in this file is licensed under a Creative Commons Attribution 3.0
 * Unported License.  Please contact the copyright holder with further questions.
*/
;(function($) {
    $.fn.gallery = function(options) {

        // merge defaults and user-supplied options
        var options = $.extend($.fn.gallery.defaults, options);

        // global plugin variables
        var obj = this;
        var nextImg = options.startImg;

        // set the target background CSS, perform any needed initialization
        $.fn.gallery.init = function() {
            $(options.target).css({
                "background-repeat": "no-repeat",
                "background-position": "center",
                "opacity": 0
            });
        }

        // perform transition to remove current image from target
        $.fn.gallery.startTransition = function() {
            $(options.target).animate(
                {"opacity": 0},
                options.changeTime,
                options.easing
            );
        }

        // perform transition to add new image to target
        $.fn.gallery.endTransition = function() {
            $(options.target).animate(
                {"opacity": 1},
                options.changeTime,
                options.easing
            );
        }

        // select a new image to be placed in target
        function selectImg(index) {
            var selected = obj.get(index);
            var url = selected.src;
            $(options.target).css("background-image", "url(" + url + ")");
            $("." + options.selectClass).removeClass(options.selectClass);
            selected.className += options.selectClass;
            nextImg = index + 1;
        }

        // transition out, select new image, transition in
        function changeToImg(index) {
            $.fn.gallery.startTransition();
            $(options.target).promise().done(function() {
                selectImg(index);
                $.fn.gallery.endTransition();
                $(options.target).promise().done(function() {
                    cycle = window.setTimeout(loadNext, options.waitTime);
                });
            });
        }

        // load the next image in cycle
        function loadNext() {
            if (nextImg < obj.length) {       // more images in cycle
                changeToImg(nextImg);
            }
            else if (options.restartOnEnd) {  // end of cycle, restart
                nextImg = 0;
                changeToImg(nextImg);
            }
        }

        // switch to given image on click, reset cycle interval
        function onClick() {
            window.clearTimeout(cycle);
            nextImg = obj.index($(this));
            changeToImg(nextImg);
        }

        // initialize gallery and set click events
        $.fn.gallery.init();
        changeToImg(nextImg);
        return this.each(function() {
            $(this).click(onClick);
        });

    };

    // create public defaults which can be overridden if requested
    $.fn.gallery.defaults = {
        target: "",
        startImg: 0,
        waitTime: 5000,
        changeTime: 700,
        easing: "swing",
        restartOnEnd: true,
        selectClass: "selected"
    };
})(jQuery);<commit_msg>Updated version number to 1.1.0<commit_after>/*
 * simple-gallery.js - v1.1.0
 * Author: Alex Kalicki (https://github.com/akalicki)
 *
 * simple-gallery.js is a lightweight jQuery extension for quickly creating
 * highly customizable photo galleries using standard jQuery notation.
 *
 * All work contained in this file is licensed under a Creative Commons Attribution 3.0
 * Unported License.  Please contact the copyright holder with further questions.
*/
;(function($) {
    $.fn.gallery = function(options) {

        // merge defaults and user-supplied options
        var options = $.extend($.fn.gallery.defaults, options);

        // global plugin variables
        var obj = this;
        var nextImg = options.startImg;

        // set the target background CSS, perform any needed initialization
        $.fn.gallery.init = function() {
            $(options.target).css({
                "background-repeat": "no-repeat",
                "background-position": "center",
                "opacity": 0
            });
        }

        // perform transition to remove current image from target
        $.fn.gallery.startTransition = function() {
            $(options.target).animate(
                {"opacity": 0},
                options.changeTime,
                options.easing
            );
        }

        // perform transition to add new image to target
        $.fn.gallery.endTransition = function() {
            $(options.target).animate(
                {"opacity": 1},
                options.changeTime,
                options.easing
            );
        }

        // select a new image to be placed in target
        function selectImg(index) {
            var selected = obj.get(index);
            var url = selected.src;
            $(options.target).css("background-image", "url(" + url + ")");
            $("." + options.selectClass).removeClass(options.selectClass);
            selected.className += options.selectClass;
            nextImg = index + 1;
        }

        // transition out, select new image, transition in
        function changeToImg(index) {
            $.fn.gallery.startTransition();
            $(options.target).promise().done(function() {
                selectImg(index);
                $.fn.gallery.endTransition();
                $(options.target).promise().done(function() {
                    cycle = window.setTimeout(loadNext, options.waitTime);
                });
            });
        }

        // load the next image in cycle
        function loadNext() {
            if (nextImg < obj.length) {       // more images in cycle
                changeToImg(nextImg);
            }
            else if (options.restartOnEnd) {  // end of cycle, restart
                nextImg = 0;
                changeToImg(nextImg);
            }
        }

        // switch to given image on click, reset cycle interval
        function onClick() {
            window.clearTimeout(cycle);
            nextImg = obj.index($(this));
            changeToImg(nextImg);
        }

        // initialize gallery and set click events
        $.fn.gallery.init();
        changeToImg(nextImg);
        return this.each(function() {
            $(this).click(onClick);
        });

    };

    // create public defaults which can be overridden if requested
    $.fn.gallery.defaults = {
        target: "",
        startImg: 0,
        waitTime: 5000,
        changeTime: 700,
        easing: "swing",
        restartOnEnd: true,
        selectClass: "selected"
    };
})(jQuery);<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var app = express();

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

var examplePlaylist = {
  playlist: {
    current : {
      id: "a76f8c",
      name: "Super Mario Bros. Theme",
      img: "https://upload.wikimedia.org/wikipedia/en/9/99/MarioSMBW.png",
      artist: "Gregg Pollack"
    },
    following: [
      {
        id: "b5da8",
        name: "Doctor Who Theme",
        img: null,
        artist: null,
        likes: 13,
        dyslikes: 2
      },
      {
        id: "b5da8",
        name: "Doctor Who Theme",
        img: null,
        artist: null,
        likes: 13,
        dyslikes: 2
      }
    ]
  }
};

app.use('/playlist', function(req, res, next) {
	res.send(JSON.stringify(examplePlaylist));
});

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;
<commit_msg>Added basic play routes<commit_after>var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var play = require('play').Play();

var app = express();

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

var playlistPaths = {
	'a76f8c': '/home/pi/musics/Epic Sax Guy _.mp3',
	'b5da8': '/home/pi/musics/match0.wav'
};

var examplePlaylist = {
  playlist: {
    current : {
      id: 'a76f8c',
      name: 'Super Mario Bros. Theme',
      img: 'https://upload.wikimedia.org/wikipedia/en/9/99/MarioSMBW.png',
      artist: 'Gregg Pollack'
    },
    following: [
      {
        id: 'b5da8',
        name: 'Doctor Who Theme',
        img: null,
        artist: null,
        likes: 13,
        dyslikes: 2
      },
      {
        id: 'b5da8',
        name: 'Doctor Who Theme',
        img: null,
        artist: null,
        likes: 13,
        dyslikes: 2
      }
    ]
  }
};

app.get('/playlist', function(req, res, next) {
	res.send(JSON.stringify(examplePlaylist));
});

app.get('/playcurrent', function(req, res, next) {
	play.sound(playlistPaths[examplePlaylist.playlist.current.id]);
	res.send('ok');
});

app.get('/play/:id', function(req, res, next) {
//	play.sound(playlistPaths[req.id]);
	res.send('ok');
});

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;
<|endoftext|>


<commit_before>var ENTER = 13;
function mainController()
{
	//contains story controller
	//contains battle controller
	//controls when story and battle controller are active.

}

function storyController()
{
	//contains the diaglogue tree
	//has a persistent pointer to dialogue tree
}

var cDebug;
function BattleController()
{
	var spellBook = new Dictionary();
	var engine = new SpellEngine();
	var player = new Human("Name",100);

	// For testing. Wont be hardcoded later
	var boss;
	//var boss = new AI("Boss Name",200,3000);
	var bossManager = new BossManager();

	// Queue of spell requests by player. Should do boss too....In later refactor
	var spellQueue = new Array();
	var stopGame;

	function processSpell(event){
		if(event.which == ENTER)
		{
			var spell = $("#controller").val().toLowerCase();
			$("#controller").val(null);
			spell = spellBook.spellSearch(spell);
			spellQueue.push(spell);
			//TODO Later i need to put process queue in here.
		}
	}

	// In later refactor boss will be using spell engine as well.
	function processQueue(boss)
	{
		if(spellQueue.length !== 0){
			var spell = engine.evaluate(spellQueue,player);
			console.log(spell);
			if(spell.power !== 0 && spell !== 0)
			{
				spell.power.toFixed(2);
				boss.reduceHealth(spell.power);
				boss.healthBarUpdate();
				if(spell.type == "Cast"){
					battleLog(spell,"playerLog",player);
				}
			}
		}
	}

	/*function processBossQueue()
	{
		if(boss.castQueue.length !== 0)
		{
			var bossSpell = {};
			var spellToken = boss.castQueue.pop();
			bossSpell.full = spellToken[0];
			bossSpell.dmg = spellToken[1];
			player.reduceHealth(bossSpell.dmg);
			battleLog(bossSpell,"bossLog",boss);
			boss.cast(bossSpell.full,boss);
		}
	}*/

	function battleStart()
	{
		var boss = bossManager.getNextBoss();
		boss.init();
		$(document).on("keydown","#controller",processSpell);
		setInterval(processQueue,100,boss);
		//setInterval(processBossQueue,100);/
		boss.cast(boss,player);
	}
	battleStart();

	function playerDump()
	{
		console.log(player);
	}

	//$(document).on("input","#controller",printSpell);

}

function battleLog(spell,type,mage)
{
	var div = "
";
	var log = "[" + mage.name + "]:" + " " + spell.full;
	if(spell.base !== undefined)
	{
		log += " " + spell.base;
	}
	var dmg = "<"+spell.power+"&#62";
	var close ="
";
	var node = div + log + dmg + close;
	$("#battleLog").append(node);
	$("#battleLogWrapper").scrollTop($("#battleLog").height());
}
function dmgBracket(dmg){
	return "<"+dmg+"&#62";
}
// Debugging tools

<commit_msg>fixed precision on dmg<commit_after>var ENTER = 13;
function mainController()
{
	//contains story controller
	//contains battle controller
	//controls when story and battle controller are active.

}

function storyController()
{
	//contains the diaglogue tree
	//has a persistent pointer to dialogue tree
}

var cDebug;
function BattleController()
{
	var spellBook = new Dictionary();
	var engine = new SpellEngine();
	var player = new Human("Name",100);

	// For testing. Wont be hardcoded later
	var boss;
	//var boss = new AI("Boss Name",200,3000);
	var bossManager = new BossManager();

	// Queue of spell requests by player. Should do boss too....In later refactor
	var spellQueue = new Array();
	var stopGame;

	function processSpell(event){
		if(event.which == ENTER)
		{
			var spell = $("#controller").val().toLowerCase();
			$("#controller").val(null);
			spell = spellBook.spellSearch(spell);
			spellQueue.push(spell);
			//TODO Later i need to put process queue in here.
		}
	}

	// In later refactor boss will be using spell engine as well.
	function processQueue(boss)
	{
		if(spellQueue.length !== 0){
			var spell = engine.evaluate(spellQueue,player);
			console.log(spell);
			if(spell.power !== 0 && spell !== 0)
			{
				spell.power = spell.power.toFixed(2);
				boss.reduceHealth(spell.power);
				boss.healthBarUpdate();
				if(spell.type == "Cast"){
					battleLog(spell,"playerLog",player);
				}
			}
		}
	}

	/*function processBossQueue()
	{
		if(boss.castQueue.length !== 0)
		{
			var bossSpell = {};
			var spellToken = boss.castQueue.pop();
			bossSpell.full = spellToken[0];
			bossSpell.dmg = spellToken[1];
			player.reduceHealth(bossSpell.dmg);
			battleLog(bossSpell,"bossLog",boss);
			boss.cast(bossSpell.full,boss);
		}
	}*/

	function battleStart()
	{
		var boss = bossManager.getNextBoss();
		boss.init();
		$(document).on("keydown","#controller",processSpell);
		setInterval(processQueue,100,boss);
		//setInterval(processBossQueue,100);/
		boss.cast(boss,player);
	}
	battleStart();

	function playerDump()
	{
		console.log(player);
	}

	//$(document).on("input","#controller",printSpell);

}

function battleLog(spell,type,mage)
{
	var div = "
";
	var log = "[" + mage.name + "]:" + " " + spell.full;
	if(spell.base !== undefined)
	{
		log += " " + spell.base;
	}
	var dmg = "<"+spell.power+"&#62";
	var close ="
";
	var node = div + log + dmg + close;
	$("#battleLog").append(node);
	$("#battleLogWrapper").scrollTop($("#battleLog").height());
}
function dmgBracket(dmg){
	return "<"+dmg+"&#62";
}
// Debugging tools

<|endoftext|>


<commit_before>/**
 * @author vincent loh <vincent.ml@gmail.com>
 * @update J Manuel Corona <jmcg92@gmail.com>
 * @update zhixin wen <wenzhixin2010@gmail.com>
 */

const Utils = $.fn.bootstrapTable.utils

$.extend($.fn.bootstrapTable.defaults, {
  stickyHeader: false,
  stickyHeaderOffsetY: 0,
  stickyHeaderOffsetLeft: 0,
  stickyHeaderOffsetRight: 0
})

$.BootstrapTable = class extends $.BootstrapTable {
  initHeader (...args) {
    super.initHeader(...args)

    if (!this.options.stickyHeader) {
      return
    }

    this.$tableBody.find('.sticky-header-container,.sticky_anchor_begin,.sticky_anchor_end').remove()

    this.$el.before('

')
    this.$el.before('

')
    this.$el.after('

')
    this.$header.addClass('sticky-header')

    // clone header just once, to be used as sticky header
    // deep clone header, using source header affects tbody>td width
    this.$stickyContainer = this.$tableBody.find('.sticky-header-container')
    this.$stickyBegin = this.$tableBody.find('.sticky_anchor_begin')
    this.$stickyEnd = this.$tableBody.find('.sticky_anchor_end')
    this.$stickyHeader = this.$header.clone(true, true)

    // render sticky on window scroll or resize
    const resizeEvent = Utils.getEventName('resize.sticky-header-table', this.$el.attr('id'))
    const scrollEvent = Utils.getEventName('scroll.sticky-header-table', this.$el.attr('id'))

    $(window).off(resizeEvent).on(resizeEvent, () => this.renderStickyHeader())
    $(window).off(scrollEvent).on(scrollEvent, () => this.renderStickyHeader())
    this.$tableBody.off('scroll').on('scroll', () => this.matchPositionX())
  }

  onColumnSearch ({ currentTarget, keyCode }) {
    super.onColumnSearch({ currentTarget, keyCode })
    this.renderStickyHeader()
  }

  resetView (...args) {
    super.resetView(...args)

    $('.bootstrap-table.fullscreen').off('scroll')
      .on('scroll', () => this.renderStickyHeader())
  }

  getCaret (...args) {
    super.getCaret(...args)

    if (this.$stickyHeader) {
      const $ths = this.$stickyHeader.find('th')

      this.$header.find('th').each((i, th) => {
        $ths.eq(i).find('.sortable').attr('class', $(th).find('.sortable').attr('class'))
      })
    }
  }

  horizontalScroll () {
    super.horizontalScroll()
    this.$tableBody.on('scroll', () => this.matchPositionX())
  }

  renderStickyHeader () {
    const that = this

    this.$stickyHeader = this.$header.clone(true, true)

    if (this.options.filterControl) {
      $(this.$stickyHeader).off('keyup change mouseup').on('keyup change mouse', function (e) {
        const $target = $(e.target)
        const value = $target.val()
        const field = $target.parents('th').data('field')
        const $coreTh = that.$header.find(`th[data-field="${ field }"]`)

        if ($target.is('input')) {
          $coreTh.find('input').val(value)
        } else if ($target.is('select')) {
          const $select = $coreTh.find('select')

          $select.find('option[selected]').removeAttr('selected')
          $select.find(`option[value="${ value }"]`).attr('selected', true)
        }

        that.triggerSearch()
      })
    }

    const top = $(window).scrollTop()
    // top anchor scroll position, minus header height
    const start = this.$stickyBegin.offset().top - this.options.stickyHeaderOffsetY
    // bottom anchor scroll position, minus header height, minus sticky height
    const end = this.$stickyEnd.offset().top - this.options.stickyHeaderOffsetY - this.$header.height()

    // show sticky when top anchor touches header, and when bottom anchor not exceeded
    if (top > start && top <= end) {
      // ensure clone and source column widths are the same
      // this.$stickyHeader.find('tr:eq(0)').find('th').each((index, el) => {
      //   $(el).css('min-width', this.$header.find('tr:eq(0)').find('th').eq(index).css('width'))
      // })
      // "y" axis
      this.$stickyHeader.find('tr').map(function(index, el) {
        var axis_x = $(el).find('th');
        axis_x.each(function(indexX, elX) {
          $__default['default'](elX).css('min-width', _this4.$header.find('tr:eq('+index+')').find('th:eq('+ indexX+')').css('width'));
        });
      });
      // match bootstrap table style
      this.$stickyContainer.show().addClass('fix-sticky fixed-table-container')
      // stick it in position
      const coords = this.$tableBody[0].getBoundingClientRect()
      let width = '100%'
      let stickyHeaderOffsetLeft = this.options.stickyHeaderOffsetLeft
      let stickyHeaderOffsetRight = this.options.stickyHeaderOffsetRight

      if (!stickyHeaderOffsetLeft) {
        stickyHeaderOffsetLeft = coords.left
      }
      if (!stickyHeaderOffsetRight) {
        width = `${coords.width}px`
      }
      if (this.$el.closest('.bootstrap-table').hasClass('fullscreen')) {
        stickyHeaderOffsetLeft = 0
        stickyHeaderOffsetRight = 0
        width = '100%'
      }
      this.$stickyContainer.css('top', `${this.options.stickyHeaderOffsetY}px`)
      this.$stickyContainer.css('left', `${stickyHeaderOffsetLeft}px`)
      this.$stickyContainer.css('right', `${stickyHeaderOffsetRight}px`)
      this.$stickyContainer.css('width', `${width}`)
      // create scrollable container for header
      this.$stickyTable = $('
')
      this.$stickyTable.addClass(this.options.classes)
      // append cloned header to dom
      this.$stickyContainer.html(this.$stickyTable.append(this.$stickyHeader))
      // match clone and source header positions when left-right scroll
      this.matchPositionX()
    } else {
      this.$stickyContainer.removeClass('fix-sticky').hide()
    }
  }

  matchPositionX () {
    this.$stickyContainer.scrollLeft(this.$tableBody.scrollLeft())
  }
}
<commit_msg>Bug fixes with eslint<commit_after>/**
 * @author vincent loh <vincent.ml@gmail.com>
 * @update J Manuel Corona <jmcg92@gmail.com>
 * @update zhixin wen <wenzhixin2010@gmail.com>
 */

const Utils = $.fn.bootstrapTable.utils

$.extend($.fn.bootstrapTable.defaults, {
  stickyHeader: false,
  stickyHeaderOffsetY: 0,
  stickyHeaderOffsetLeft: 0,
  stickyHeaderOffsetRight: 0
})

$.BootstrapTable = class extends $.BootstrapTable {
  initHeader (...args) {
    super.initHeader(...args)

    if (!this.options.stickyHeader) {
      return
    }

    this.$tableBody.find('.sticky-header-container,.sticky_anchor_begin,.sticky_anchor_end').remove()

    this.$el.before('

')
    this.$el.before('

')
    this.$el.after('

')
    this.$header.addClass('sticky-header')

    // clone header just once, to be used as sticky header
    // deep clone header, using source header affects tbody>td width
    this.$stickyContainer = this.$tableBody.find('.sticky-header-container')
    this.$stickyBegin = this.$tableBody.find('.sticky_anchor_begin')
    this.$stickyEnd = this.$tableBody.find('.sticky_anchor_end')
    this.$stickyHeader = this.$header.clone(true, true)

    // render sticky on window scroll or resize
    const resizeEvent = Utils.getEventName('resize.sticky-header-table', this.$el.attr('id'))
    const scrollEvent = Utils.getEventName('scroll.sticky-header-table', this.$el.attr('id'))

    $(window).off(resizeEvent).on(resizeEvent, () => this.renderStickyHeader())
    $(window).off(scrollEvent).on(scrollEvent, () => this.renderStickyHeader())
    this.$tableBody.off('scroll').on('scroll', () => this.matchPositionX())
  }

  onColumnSearch ({ currentTarget, keyCode }) {
    super.onColumnSearch({ currentTarget, keyCode })
    this.renderStickyHeader()
  }

  resetView (...args) {
    super.resetView(...args)

    $('.bootstrap-table.fullscreen').off('scroll')
      .on('scroll', () => this.renderStickyHeader())
  }

  getCaret (...args) {
    super.getCaret(...args)

    if (this.$stickyHeader) {
      const $ths = this.$stickyHeader.find('th')

      this.$header.find('th').each((i, th) => {
        $ths.eq(i).find('.sortable').attr('class', $(th).find('.sortable').attr('class'))
      })
    }
  }

  horizontalScroll () {
    super.horizontalScroll()
    this.$tableBody.on('scroll', () => this.matchPositionX())
  }

  renderStickyHeader () {
    const that = this

    this.$stickyHeader = this.$header.clone(true, true)

    if (this.options.filterControl) {
      $(this.$stickyHeader).off('keyup change mouseup').on('keyup change mouse', function (e) {
        const $target = $(e.target)
        const value = $target.val()
        const field = $target.parents('th').data('field')
        const $coreTh = that.$header.find(`th[data-field="${ field }"]`)

        if ($target.is('input')) {
          $coreTh.find('input').val(value)
        } else if ($target.is('select')) {
          const $select = $coreTh.find('select')

          $select.find('option[selected]').removeAttr('selected')
          $select.find(`option[value="${ value }"]`).attr('selected', true)
        }

        that.triggerSearch()
      })
    }

    const top = $(window).scrollTop()
    // top anchor scroll position, minus header height
    const start = this.$stickyBegin.offset().top - this.options.stickyHeaderOffsetY
    // bottom anchor scroll position, minus header height, minus sticky height
    const end = this.$stickyEnd.offset().top - this.options.stickyHeaderOffsetY - this.$header.height()

    // show sticky when top anchor touches header, and when bottom anchor not exceeded
    if (top > start && top <= end) {
      // ensure clone and source column widths are the same
      this.$stickyHeader.find('tr').each((indexRows, rows) => {
        const columns = $(rows).find('th')

        columns.each((indexColumns, celd) => {
          $(celd).css('min-width', this.$header.find(`tr:eq(${indexRows})`).find(`th:eq(${indexColumns})`).css('width'))
        })
      })
      // match bootstrap table style
      this.$stickyContainer.show().addClass('fix-sticky fixed-table-container')
      // stick it in position
      const coords = this.$tableBody[0].getBoundingClientRect()
      let width = '100%'
      let stickyHeaderOffsetLeft = this.options.stickyHeaderOffsetLeft
      let stickyHeaderOffsetRight = this.options.stickyHeaderOffsetRight

      if (!stickyHeaderOffsetLeft) {
        stickyHeaderOffsetLeft = coords.left
      }
      if (!stickyHeaderOffsetRight) {
        width = `${coords.width}px`
      }
      if (this.$el.closest('.bootstrap-table').hasClass('fullscreen')) {
        stickyHeaderOffsetLeft = 0
        stickyHeaderOffsetRight = 0
        width = '100%'
      }
      this.$stickyContainer.css('top', `${this.options.stickyHeaderOffsetY}px`)
      this.$stickyContainer.css('left', `${stickyHeaderOffsetLeft}px`)
      this.$stickyContainer.css('right', `${stickyHeaderOffsetRight}px`)
      this.$stickyContainer.css('width', `${width}`)
      // create scrollable container for header
      this.$stickyTable = $('
')
      this.$stickyTable.addClass(this.options.classes)
      // append cloned header to dom
      this.$stickyContainer.html(this.$stickyTable.append(this.$stickyHeader))
      // match clone and source header positions when left-right scroll
      this.matchPositionX()
    } else {
      this.$stickyContainer.removeClass('fix-sticky').hide()
    }
  }

  matchPositionX () {
    this.$stickyContainer.scrollLeft(this.$tableBody.scrollLeft())
  }
}
<|endoftext|>


<commit_before>/*
 * eHistory Chrome Extension
 * https://chrome.google.com/webstore/detail/hiiknjobjfknoghbeelhfilaaikffopb
 *
 * Copyright 2011, Amjad Masad
 * Licensed under the MIT license
 * https://github.com/amasad/eHistory/blob/master/LICENSE.txt
 *
 * Date: Mon May 9
 */

(function($){
/** Global **/
initialSearch = function () {
  $('#frm-search').submit();
};
/******** Utils **********/
/*  parseQuery:  Parses the search query
 *      @arg (String) input: The search query
 *      @returns (Array) [settings, filters, text]
 */
function parseQuery (input) {
  // assumes search query is a space delimted key/value pairs
  var options = (input.split(/\s/));
  // initiate possible filters to null
  var filters = {
    inurl: null,
    intitle: null,
    site: null
  };
  // initiate possible settings in query
  var searchSettings = {
    startTime: null,
    endTime: null,
    text: ""
  };
  // text types
  var pureText = "", combined = "";

  // loop each pair in the query string
  $.each(options, function (i, pair) {
    if (!pair) return;
    // assume key:value
    pair = pair.split(":");
    searchSettings[pair[0]] !== undefined ?
        // pair is a search setting type
        searchSettings[pair[0]] = pair[1] :
        // pair is a filter type
        filters[pair[0]] !== undefined ?
            combined += " " + (filters[pair[0]] = pair[1]) :
            combined += " " + (pair[1] || pair[0] || "");
    // pair is is just text
    if (!pair[1]) pureText += " " + pair[0];
  });
  searchSettings.text = $.trim(combined);
  // delete all empty filters
  for (var prop in filters) {
    if (filters[prop] === null) {
      delete filters[prop];
    }
  }
  return [
    searchSettings,
    filters,
    $.trim(pureText)
  ];
}

/* parseForm: Parses the html form into text format
 *    @arg (jQueryObject) $form: jQuery object containing the form element
 *    @returns (String) text query equivalent to the form
 * intitle:title inurl:url site:site startTime:startime endTime:endtime searchquery
 */
function parseForm ($form) {
  var query = "",
      text = "";
  // loop over all input elements
  $form.find('input').each(function (i, elem) {
    elem = $(elem);
    if (elem.attr("id") == "pure-text") {
      // just text
      text += elem.val();
    } else {
      // filter/setting
      query += elem.val() ?  " " + elem.data("settings-item") + ":" + elem.val() : "";
    }
  });
  // return filter/setting text format key:value followed by regular text
  return $.trim(query + " " + text);
}

// Check version number
$(function() {
  var manifest = JSON.parse($.ajax({
          url: 'manifest.json',
          async: false
        }).responseText || '{}');
  var version = manifest.version;
  if (localStorage['version'] != version) {
    $('#version-updated').show("slow");
    localStorage.clear();
    localStorage['version'] = version;
  }

  setTimeout(function () {
    $('#version-updated').hide("slow");
  }, 5000);
})
/*************** Controller  ***************/
/*  Collection of functions and event handlers
 *    Interacts with UI, historyModel and historyView
 */
$(function(){
  // DOM ready
  // search box
  var $query = $('#query');
  // advanced search form
  var $pnlAdvanced = $('#pnl-advanced');
  // history items table
  var $resultsTable = $('#tbl-main');

  // fill the advanced search form with parsed filter/settings values
  function fillForm (config) {
    // merge all types of key value pairs
    var operators = $.extend(config[0], config[1]);
    // loop over the form input and fill them with values
    $pnlAdvanced.find('input').each(function (i, elem) {
      elem = $(elem);
      if (elem.attr('id') == "pure-text"){
        elem.val(config[2]);
      } else {
        // in the elements data contains type of settings/filter
        elem.val(operators[elem.data("settings-item")] || "");
      }
    });
  }

  // fills the search box
  function fillText (text) {
    $query.val(text || "");
  }

  // results day headers check-boxs handler
  $resultsTable.delegate(".chk-day", "change", function () {
    // check all results until the next day header
    $(this).parents('tr').nextUntil('.hdr-day')
        .children(':nth-child(1)').children()
            .attr("checked",  $(this).attr("checked")).trigger("change");
  });

  // result item checkbox handler
  $resultsTable.delegate(".chk-entry", "change", function () {
    var val =  $(this).attr("checked"),
        $row = $(this).parents("tr"),
        // decides what function to call, select/unselect
        fn = val ? $.proxy(historyModel.select, historyModel) : $.proxy(historyModel.unselect, historyModel);
    fn($row.data("id"),$row.data("day"));
  });

  // advanced search checkbox handler
  $("#chk-advanced").click(function () {
    var $this = $(this);
    // if the panel is visible enable searchbox
    // parse the panel's form to fill searchbox
    // otherwise disable searchbox and and fill form
		if ($pnlAdvanced.is(":visible")) {
		  $query.attr("disabled", false);
			fillText(parseForm($pnlAdvanced));
			$query.focus();
		} else {
		  $query.attr("disabled", true);
			fillForm(parseQuery($query.val()));
		}
		// toggle visibility
	  $pnlAdvanced.toggle();
	});

  // called to initiate the search
  function search(config) {
    var settings = config[0],
        filters = config[1],
        text = config[2];

    historyView.displayThrobber();
    historyView.setSummary(settings.text || "");

      EHistory.search({
        text: settings.text || "",
        startTime: new Date(settings.startTime || 0).getTime() ,
        endTime: new Date(settings.endTime || Date.now()).getTime(),
        maxResults: historyModel.pageSize
      }, filters, function(results){
        historyModel.append(results);
      });
  }

  // form submit handler
  $('#frm-search').submit( function () {
    var text;
    //clear everything
    historyModel.clear();
    historyView.clear();
    historyView.disableControls();

    if ($pnlAdvanced.is(":visible")){
      text = parseForm($pnlAdvanced);
      search(parseQuery(text));
    } else {
      search(parseQuery($query.val()));
    }
    //return false;
  });

  // show url checkbox handler
  // loop over all entries and swap href with title
  // title saved in the data
  $('#show-url input').change(function () {
    var link,
        $entries = $('.entry a');
    if ($(this).attr('checked')) {
      $entries.each(function () {
        var $this = $(this),
            title = $this.text();
        if (!$this.data('title')) {
          $this.data('title', title);
        }
        $this.text($this.attr('href'));
      });
    } else {
      $entries.each(function () {
        var $this = $(this);
        $this.text($this.data('title'));
      });
    }
  });

  // instantiate date pickers
  $('#date-frm').datepicker();
  $('#date-to').datepicker();
  // static overlay element
  var $overLay = $('

');
  // confirms with the user and proceeds according to which edit button was pressed
  // msg is found in the event data "OK" handler and message to show in the confirm box
  var confirmAndProgress = function (e) {
    $( "#dialog-confirm" )
      .attr('title', e.data.msg)
      .dialog({
        resizable: false,
        height:140,
        modal: true,
        buttons: {
          "Delete all items": function() {
            $( this ).dialog( "close" );
            progress();
            (e.data.ok || $.noop)();
          },
          Cancel: function() {
            $( this ).dialog( "close" );
          }
        }
      });
  };
  // shows the overlay and throbber
  var progress = function (e) {
    $overLay.appendTo('body').show();
  };
  // edit buttons handlers
  // sends msg and OK handler in the event data

  $('#btn-clear-history').click({
     msg:"Delete all items from history?",
     ok: $.proxy(historyModel.clearHistory, historyModel)
  },confirmAndProgress);

  $("#btn-delete-selected").click({
    msg:"Delete selected items?",
    ok: $.proxy(historyModel.removeSelected, historyModel)
  }, confirmAndProgress);

  $('#btn-delete-all').click({
    msg:"Delete all search results?",
    ok: $.proxy(historyModel.clearResults, historyModel)
  }, confirmAndProgress);

});

})(jQuery);
<commit_msg>Updating the contents of the main search box live when filters change.<commit_after>/*
 * eHistory Chrome Extension
 * https://chrome.google.com/webstore/detail/hiiknjobjfknoghbeelhfilaaikffopb
 *
 * Copyright 2011, Amjad Masad
 * Licensed under the MIT license
 * https://github.com/amasad/eHistory/blob/master/LICENSE.txt
 *
 * Date: Mon May 9
 */

(function($){
/** Global **/
initialSearch = function () {
  $('#frm-search').submit();
};
/******** Utils **********/
/*  parseQuery:  Parses the search query
 *      @arg (String) input: The search query
 *      @returns (Array) [settings, filters, text]
 */
function parseQuery (input) {
  // assumes search query is a space delimted key/value pairs
  var options = (input.split(/\s/));
  // initiate possible filters to null
  var filters = {
    inurl: null,
    intitle: null,
    site: null
  };
  // initiate possible settings in query
  var searchSettings = {
    startTime: null,
    endTime: null,
    text: ""
  };
  // text types
  var pureText = "", combined = "";

  // loop each pair in the query string
  $.each(options, function (i, pair) {
    if (!pair) return;
    // assume key:value
    pair = pair.split(":");
    searchSettings[pair[0]] !== undefined ?
        // pair is a search setting type
        searchSettings[pair[0]] = pair[1] :
        // pair is a filter type
        filters[pair[0]] !== undefined ?
            combined += " " + (filters[pair[0]] = pair[1]) :
            combined += " " + (pair[1] || pair[0] || "");
    // pair is is just text
    if (!pair[1]) pureText += " " + pair[0];
  });
  searchSettings.text = $.trim(combined);
  // delete all empty filters
  for (var prop in filters) {
    if (filters[prop] === null) {
      delete filters[prop];
    }
  }
  return [
    searchSettings,
    filters,
    $.trim(pureText)
  ];
}

/* parseForm: Parses the html form into text format
 *    @arg (jQueryObject) $form: jQuery object containing the form element
 *    @returns (String) text query equivalent to the form
 * intitle:title inurl:url site:site startTime:startime endTime:endtime searchquery
 */
function parseForm ($form) {
  var query = "",
      text = "";
  // loop over all input elements
  $form.find('input').each(function (i, elem) {
    elem = $(elem);
    if (elem.attr("id") == "pure-text") {
      // just text
      text += elem.val();
    } else {
      // filter/setting
      query += elem.val() ?  " " + elem.data("settings-item") + ":" + elem.val() : "";
    }
  });
  // return filter/setting text format key:value followed by regular text
  return $.trim(query + " " + text);
}

// Check version number
$(function() {
  var manifest = JSON.parse($.ajax({
          url: 'manifest.json',
          async: false
        }).responseText || '{}');
  var version = manifest.version;
  if (localStorage['version'] != version) {
    $('#version-updated').show("slow");
    localStorage.clear();
    localStorage['version'] = version;
  }

  setTimeout(function () {
    $('#version-updated').hide("slow");
  }, 5000);
})
/*************** Controller  ***************/
/*  Collection of functions and event handlers
 *    Interacts with UI, historyModel and historyView
 */
$(function(){
  // DOM ready
  // search box
  var $query = $('#query');
  // advanced search form
  var $pnlAdvanced = $('#pnl-advanced');
  // history items table
  var $resultsTable = $('#tbl-main');

  // fill the advanced search form with parsed filter/settings values
  function fillForm (config) {
    // merge all types of key value pairs
    var operators = $.extend(config[0], config[1]);
    // loop over the form input and fill them with values
    $pnlAdvanced.find('input').each(function (i, elem) {
      elem = $(elem);
      if (elem.attr('id') == "pure-text"){
        elem.val(config[2]);
      } else {
        // in the elements data contains type of settings/filter
        elem.val(operators[elem.data("settings-item")] || "");
      }
    });
  }

  // fills the search box
  function fillText (text) {
    $query.val(text || "");
  }

  // results day headers check-boxs handler
  $resultsTable.delegate(".chk-day", "change", function () {
    // check all results until the next day header
    $(this).parents('tr').nextUntil('.hdr-day')
        .children(':nth-child(1)').children()
            .attr("checked",  $(this).attr("checked")).trigger("change");
  });

  // result item checkbox handler
  $resultsTable.delegate(".chk-entry", "change", function () {
    var val =  $(this).attr("checked"),
        $row = $(this).parents("tr"),
        // decides what function to call, select/unselect
        fn = val ? $.proxy(historyModel.select, historyModel) : $.proxy(historyModel.unselect, historyModel);
    fn($row.data("id"),$row.data("day"));
  });

  // Update the main search box whenever advanced settings are changed.
  $("input", $pnlAdvanced).change(function () {
    console.log('change');
    fillText(parseForm($pnlAdvanced));
  }).keypress(function() {
    $(this).change();
  }).keydown(function() {
    $(this).change();
  });

  // advanced search checkbox handler
  $("#chk-advanced").click(function () {
    var $this = $(this);
    // if the panel is visible enable searchbox
    // parse the panel's form to fill searchbox
    // otherwise disable searchbox and and fill form
		if ($pnlAdvanced.is(":visible")) {
		  $query.attr("disabled", false);
			fillText(parseForm($pnlAdvanced));
			$query.focus();
		} else {
		  $query.attr("disabled", true);
			fillForm(parseQuery($query.val()));
		}
		// toggle visibility
	  $pnlAdvanced.toggle();
	});

  // called to initiate the search
  function search(config) {
    var settings = config[0],
        filters = config[1],
        text = config[2];

    historyView.displayThrobber();
    historyView.setSummary(settings.text || "");

      EHistory.search({
        text: settings.text || "",
        startTime: new Date(settings.startTime || 0).getTime() ,
        endTime: new Date(settings.endTime || Date.now()).getTime(),
        maxResults: historyModel.pageSize
      }, filters, function(results){
        historyModel.append(results);
      });
  }

  // form submit handler
  $('#frm-search').submit( function () {
    var text;
    //clear everything
    historyModel.clear();
    historyView.clear();
    historyView.disableControls();

    if ($pnlAdvanced.is(":visible")){
      text = parseForm($pnlAdvanced);
      search(parseQuery(text));
    } else {
      search(parseQuery($query.val()));
    }
    //return false;
  });

  // show url checkbox handler
  // loop over all entries and swap href with title
  // title saved in the data
  $('#show-url input').change(function () {
    var link,
        $entries = $('.entry a');
    if ($(this).attr('checked')) {
      $entries.each(function () {
        var $this = $(this),
            title = $this.text();
        if (!$this.data('title')) {
          $this.data('title', title);
        }
        $this.text($this.attr('href'));
      });
    } else {
      $entries.each(function () {
        var $this = $(this);
        $this.text($this.data('title'));
      });
    }
  });

  // instantiate date pickers
  $('#date-frm').datepicker();
  $('#date-to').datepicker();
  // static overlay element
  var $overLay = $('

');
  // confirms with the user and proceeds according to which edit button was pressed
  // msg is found in the event data "OK" handler and message to show in the confirm box
  var confirmAndProgress = function (e) {
    $( "#dialog-confirm" )
      .attr('title', e.data.msg)
      .dialog({
        resizable: false,
        height:140,
        modal: true,
        buttons: {
          "Delete all items": function() {
            $( this ).dialog( "close" );
            progress();
            (e.data.ok || $.noop)();
          },
          Cancel: function() {
            $( this ).dialog( "close" );
          }
        }
      });
  };
  // shows the overlay and throbber
  var progress = function (e) {
    $overLay.appendTo('body').show();
  };
  // edit buttons handlers
  // sends msg and OK handler in the event data

  $('#btn-clear-history').click({
     msg:"Delete all items from history?",
     ok: $.proxy(historyModel.clearHistory, historyModel)
  },confirmAndProgress);

  $("#btn-delete-selected").click({
    msg:"Delete selected items?",
    ok: $.proxy(historyModel.removeSelected, historyModel)
  }, confirmAndProgress);

  $('#btn-delete-all').click({
    msg:"Delete all search results?",
    ok: $.proxy(historyModel.clearResults, historyModel)
  }, confirmAndProgress);

});

})(jQuery);
<|endoftext|>


<commit_before>'use strict';

import webpack from 'webpack';
import autoprefixer from 'autoprefixer';
import postcssMixins from 'postcss-mixins';
import postcssExtend from 'postcss-extend';
import postcssSimpleVars from 'postcss-simple-vars';
import postcssNested from 'postcss-nested';
import postcssImporter from 'postcss-import';
import postcssFunctions from 'postcss-functions';
import postcssHexRgba from 'postcss-hexrgba';
import path from 'path';

const prodPlugins = [
  // new webpack.HotModuleReplacementPlugin(),
  // new webpack.optimize.UglifyJsPlugin({
  //   compress: {
  //     warnings: false,
  //     dead_code: true,
  //     drop_debugger: true,
  //     drop_console: true
  //   },
  //   comments: false
  // }),
  // new webpack.optimize.DedupePlugin(),
  // new webpack.optimize.OccurrenceOrderPlugin()
];

const config = {

  context: path.join(__dirname, 'src'),

  entry: [
    'webpack/hot/dev-server',
    './index.html',
    './anniversary.html',
    './main.js',
  ],

  publicPath: '/assets/',

  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js'
  },

  module: {
    loaders: [
      {test: /\.html$/, loader: 'file?name=[name].[ext]'},
      {test: /\.(js$)/, loader: 'babel-loader', exclude: /node_modules/},
      {test: /\.(postcss$|css$)/, loader: 'style-loader!css-loader!postcss-loader'},
      {test: /\.(png|jpg|gif|svg)$/, loader: 'url-loader?prefix=image/&limit=5000&context=./src/images'},
      {test: /\.(eot|ttf|woff2|woff)$/, loader: 'url-loader?prefix=fonts/&context=./src/fonts'},
    ]
  },

  plugins: process.env.NODE_ENV === 'production' ? prodPlugins : [],

  postcss: (webpack) => [
    postcssImporter({ addDependencyTo: webpack }),
    autoprefixer,
    postcssMixins,
    postcssExtend,
    postcssSimpleVars,
    postcssNested,
    postcssFunctions({
      functions: {
        rem: (px) => (px / 16) + 'rem'
      }
    }),
    postcssHexRgba
  ]

};

export default config;
<commit_msg>urgency fix<commit_after>'use strict';

import webpack from 'webpack';
import autoprefixer from 'autoprefixer';
import postcssMixins from 'postcss-mixins';
import postcssExtend from 'postcss-extend';
import postcssSimpleVars from 'postcss-simple-vars';
import postcssNested from 'postcss-nested';
import postcssImporter from 'postcss-import';
import postcssFunctions from 'postcss-functions';
import postcssHexRgba from 'postcss-hexrgba';
import path from 'path';

const prodPlugins = [
  new webpack.HotModuleReplacementPlugin()
  // new webpack.optimize.UglifyJsPlugin({
  //   compress: {
  //     warnings: false,
  //     dead_code: true,
  //     drop_debugger: true,
  //     drop_console: true
  //   },
  //   comments: false
  // }),
  // new webpack.optimize.DedupePlugin(),
  // new webpack.optimize.OccurrenceOrderPlugin()
];

const config = {

  context: path.join(__dirname, 'src'),

  entry: [
    'webpack/hot/dev-server',
    './index.html',
    './anniversary.html',
    './main.js',
  ],

  publicPath: '/assets/',

  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js'
  },

  module: {
    loaders: [
      {test: /\.html$/, loader: 'file?name=[name].[ext]'},
      {test: /\.(js$)/, loader: 'babel-loader', exclude: /node_modules/},
      {test: /\.(postcss$|css$)/, loader: 'style-loader!css-loader!postcss-loader'},
      {test: /\.(png|jpg|gif|svg)$/, loader: 'url-loader?prefix=image/&limit=5000&context=./src/images'},
      {test: /\.(eot|ttf|woff2|woff)$/, loader: 'url-loader?prefix=fonts/&context=./src/fonts'},
    ]
  },

  plugins: prodPlugins,

  postcss: (webpack) => [
    postcssImporter({ addDependencyTo: webpack }),
    autoprefixer,
    postcssMixins,
    postcssExtend,
    postcssSimpleVars,
    postcssNested,
    postcssFunctions({
      functions: {
        rem: (px) => (px / 16) + 'rem'
      }
    }),
    postcssHexRgba
  ]

};

export default config;
<|endoftext|>