<commit_before>"use strict"

const expect = require('expect')
const createDataReader = require('./createDataReader')
const {readFormat, T} = require('./readFormat')
const padEnd = require('lodash/padEnd')
const fill = require('lodash/fill')

{
  // can read unsigned types

  const buffer = Buffer.concat([
    Buffer.from([0xff]),
    Buffer.from(new Uint16Array([0xffff]).buffer),
    Buffer.from(new Uint32Array([0xffffffff]).buffer),
  ])

  const data = readFormat({
    format: {
      a: T.u8,
      b: T.u16,
      c: T.u32,
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({a: 0xff, b: 0xffff, c: 0xffffffff})
}

{
  // can read string types

  const buffer = Buffer.concat([
    Buffer.from(' \n\t\r'),
    Buffer.from(padEnd('Cute', 20, '\0')),
    Buffer.from('Cuddly Kittens 255 65535 4294967295')
  ])

  const data = readFormat({
    format: {
      _: T.whitespace,
      adjective: T.stringFixed(20),
      type: T.string,
      animal: T.string,
      a: T.stringU8,
      b: T.stringU16,
      c: T.stringU32,
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    _: ' \n\t\r',
    adjective: 'Cute',
    type: 'Cuddly',
    animal: 'Kittens',
    a: 255,
    b: 65535,
    c: 4294967295,
  })
}

{
  // can read fixed length strings of... dynamic length 🤔
  //
  // the verge2 chr loader reads a length for idle animation
  // strings and then reads a fixed length string of that length.
  // for a string field of length L at position P, if the null
  // terminator always lies at P+L-1, that would allow the use
  // of a function such as readStringNullTerminated. of course,
  // in that case, the leading L on disk would be ignored. but
  // it may solve the human readability issue.
  //
  // alternatively, perhaps rename readStringFixed to
  // readStringNullTerminated and pass an optional length
  // parameter. without a given length, it would read until
  // finding a null terminator. with a length, it would behave
  // as readStringFixed currently does.

  const buffer = Buffer.concat([
    Buffer.from([5]),
    Buffer.from('Cute\0Cuddly Kittens'),
  ])

  const data = readFormat({
    format: {
      adjectiveLength: T.u8,
      adjective: T.stringFixed(({record}) => record.adjectiveLength),
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    adjectiveLength: 5,
    adjective: 'Cute',
  })
}

{
  // can read lists of lists

  const buffer = Buffer.concat([
    Buffer.from([1, 2, 3]),
    Buffer.from([4, 5, 6]),
  ])

  const data = readFormat({
    format: {
      a: T.list({
        b: T.list(T.u8, 3),
      }, 2)
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    a: [
      {b: [1, 2, 3]},
      {b: [4, 5, 6]},
    ]
  })
}

{
  // can read compressed buffers

  const buffer = Buffer.concat([
    Buffer.from(new Uint32Array([5]).buffer),
    Buffer.from([1, 0xff, (16 * 16) - 2, 2, 3]),
    Buffer.from(new Uint32Array([4 * 2]).buffer),
    Buffer.from(new Uint16Array([1111, ((16 * 16) - 2) | 0xff00, 2222, 3333]).buffer),
  ])

  const data = readFormat({
    format: {
      a: T.compressedU8(16 * 16),
      b: T.compressedU16(16 * 16),
    },
    reader: createDataReader({data: buffer})
  })

  const expandedA = fill(Array(16 * 16), 2)
  expandedA[0] = 1
  expandedA[255] = 3

  expect(data.a.decompressed).toEqual(expandedA)
  expect(data.b.decompressed).toEqual(expandedA.map(v => v * 1111))
}

{
  // can read dynamic length compressed buffers

  const buffer = Buffer.concat([
    Buffer.from(new Uint16Array([16 * 16, 16 * 16]).buffer),
    Buffer.from(new Uint32Array([5]).buffer),
    Buffer.from([1, 0xff, (16 * 16) - 2, 2, 3]),
    Buffer.from(new Uint32Array([4 * 2]).buffer),
    Buffer.from(new Uint16Array([1111, ((16 * 16) - 2) | 0xff00, 2222, 3333]).buffer),
  ])

  const data = readFormat({
    format: {
      lengthA: T.u16,
      lengthB: T.u16,
      a: T.compressedU8(({record}) => record.lengthA),
      b: T.compressedU16(({record}) => record.lengthB),
    },
    reader: createDataReader({data: buffer})
  })

  const expandedA = fill(Array(16 * 16), 2)
  expandedA[0] = 1
  expandedA[255] = 3

  expect(data.a.decompressed).toEqual(expandedA)
  expect(data.b.decompressed).toEqual(expandedA.map(v => v * 1111))
}

{
  // can read list of types

  const buffer = Buffer.concat([
    Buffer.from([0xff, 0xff]),
    Buffer.from(new Uint16Array([0xffff, 0xffff]).buffer),
    Buffer.from(new Uint32Array([0xffffffff, 0xffffffff]).buffer),
  ])

  const data = readFormat({
    format: {
      a: T.list(T.u8, 2),
      b: T.list(T.u16, 2),
      c: T.list(T.u32, 2),
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    a: [0xff, 0xff],
    b: [0xffff, 0xffff],
    c: [0xffffffff, 0xffffffff],
  })
}

{
  // T.list requires a length

  expect(() => (
    readFormat({format: T.list(T.u8)})
  )).toThrow(Error, 'T.list length must be defined')
}

{
  // can read nested formats

  const buffer = Buffer.concat([
    Buffer.from([0xff]),
    Buffer.from(new Uint16Array([0xffff]).buffer),
    Buffer.from(new Uint32Array([0xffffffff]).buffer),
  ])

  const data = readFormat({
    format: {
      a: T.u8,
      b: {
        c: T.u16,
        d: T.u32,
      },
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    a: 0xff,
    b: {
      c: 0xffff,
      d: 0xffffffff,
    }
  })
}

{
  // can read list of formats

  const buffer = Buffer.concat([
    Buffer.from([0xff]),
    Buffer.from(new Uint16Array([0xffff]).buffer),
    Buffer.from(new Uint32Array([0xffffffff]).buffer),
    Buffer.from(new Uint16Array([0xffff]).buffer),
    Buffer.from(new Uint32Array([0xffffffff]).buffer),
  ])

  const data = readFormat({
    format: {
      a: T.list({
        b: T.u16,
        c: T.u32,
      }, 2)
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    a: [
      {b: 0xffff, c: 0xffffffff},
      {b: 0xffff, c: 0xffffffff},
    ]
  })
}

{
  // can read list of dynamic length

  const buffer = Buffer.concat([
    Buffer.from([2, 3, 44, 55, 66, 77, 88, 99]),
  ])

  const data = readFormat({
    format: {
      w: T.u8,
      h: T.u8,
      grid: T.list(T.u8, ({record}) => record.w * record.h),
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    w: 2,
    h: 3,
    grid: [44, 55, 66, 77, 88, 99],
  })
}

{
  // can read current T.list index in dynamic length calculators

  const firstLayerWidth = 3
  const firstLayerHeight = 4
  const firstLayerFill = 77
  const secondLayerWidth = 5
  const secondLayerHeight = 6
  const secondLayerFill = 88
  const buffer = Buffer.concat([
    Buffer.from([
      2,
      firstLayerWidth, firstLayerHeight,
      secondLayerWidth, secondLayerHeight,
    ]),
    Buffer.concat([
      Buffer.from(new Uint32Array([2 * 2]).buffer),
      Buffer.from(new Uint16Array([
        (firstLayerWidth * firstLayerHeight) | 0xff00,
        firstLayerFill,
      ]).buffer),
      Buffer.from(new Uint32Array([2 * 2]).buffer),
      Buffer.from(new Uint16Array([
        (secondLayerWidth * secondLayerHeight) | 0xff00,
        secondLayerFill
      ]).buffer),
    ])
  ])

  const data = readFormat({
    format: {
      numlayers: T.u8,
      layer: T.list({
        sizex: T.u8,
        sizey: T.u8,
      }, ({record}) => record.numlayers),
      layers: T.list(
        T.compressedU16(({record, listIndex}) => {
          const sizex = record.layer[listIndex].sizex
          const sizey = record.layer[listIndex].sizey
          const size = sizex * sizey
          return size
        }),
        ({record}) => record.numlayers
      )
    },
    reader: createDataReader({data: buffer})
  })

  expect(data.numlayers).toBe(2)
  expect(data.layer.length).toBe(2)
  expect(data.layers.length).toBe(2)
  expect(data.layers[0].decompressed).toEqual(
    fill(Array(firstLayerWidth * firstLayerHeight), firstLayerFill)
  )
  expect(data.layers[1].decompressed).toEqual(
    fill(Array(secondLayerWidth * secondLayerHeight), secondLayerFill)
  )
}

{
  // can read list of all remaining bytes

  const buffer = Buffer.concat([
    Buffer.from([44, 55, 66, 77, 88, 99]),
  ])

  const data = readFormat({
    format: {
      grid: T.list(T.u8, ({reader}) => reader.remaining),
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    grid: [44, 55, 66, 77, 88, 99],
  })
}<commit_msg>simplify<commit_after>"use strict"

const expect = require('expect')
const createDataReader = require('./createDataReader')
const {readFormat, T} = require('./readFormat')
const padEnd = require('lodash/padEnd')
const fill = require('lodash/fill')

{
  // can read unsigned types

  const buffer = Buffer.concat([
    Buffer.from([0xff]),
    Buffer.from(new Uint16Array([0xffff]).buffer),
    Buffer.from(new Uint32Array([0xffffffff]).buffer),
  ])

  const data = readFormat({
    format: {
      a: T.u8,
      b: T.u16,
      c: T.u32,
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({a: 0xff, b: 0xffff, c: 0xffffffff})
}

{
  // can read string types

  const buffer = Buffer.concat([
    Buffer.from(' \n\t\r'),
    Buffer.from(padEnd('Cute', 20, '\0')),
    Buffer.from('Cuddly Kittens 255 65535 4294967295')
  ])

  const data = readFormat({
    format: {
      _: T.whitespace,
      adjective: T.stringFixed(20),
      type: T.string,
      animal: T.string,
      a: T.stringU8,
      b: T.stringU16,
      c: T.stringU32,
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    _: ' \n\t\r',
    adjective: 'Cute',
    type: 'Cuddly',
    animal: 'Kittens',
    a: 255,
    b: 65535,
    c: 4294967295,
  })
}

{
  // can read fixed length strings of... dynamic length 🤔
  //
  // the verge2 chr loader reads a length for idle animation
  // strings and then reads a fixed length string of that length.
  // for a string field of length L at position P, if the null
  // terminator always lies at P+L-1, that would allow the use
  // of a function such as readStringNullTerminated. of course,
  // in that case, the leading L on disk would be ignored. but
  // it may solve the human readability issue.
  //
  // alternatively, perhaps rename readStringFixed to
  // readStringNullTerminated and pass an optional length
  // parameter. without a given length, it would read until
  // finding a null terminator. with a length, it would behave
  // as readStringFixed currently does.

  const buffer = Buffer.concat([
    Buffer.from([5]),
    Buffer.from('Cute\0Cuddly Kittens'),
  ])

  const data = readFormat({
    format: {
      adjectiveLength: T.u8,
      adjective: T.stringFixed(({record}) => record.adjectiveLength),
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    adjectiveLength: 5,
    adjective: 'Cute',
  })
}

{
  // can read lists of lists

  const buffer = Buffer.concat([
    Buffer.from([1, 2, 3]),
    Buffer.from([4, 5, 6]),
  ])

  const data = readFormat({
    format: {
      a: T.list({
        b: T.list(T.u8, 3),
      }, 2)
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    a: [
      {b: [1, 2, 3]},
      {b: [4, 5, 6]},
    ]
  })
}

{
  // can read compressed buffers

  const buffer = Buffer.concat([
    Buffer.from(new Uint32Array([5]).buffer),
    Buffer.from([1, 0xff, (16 * 16) - 2, 2, 3]),
    Buffer.from(new Uint32Array([4 * 2]).buffer),
    Buffer.from(new Uint16Array([1111, ((16 * 16) - 2) | 0xff00, 2222, 3333]).buffer),
  ])

  const data = readFormat({
    format: {
      a: T.compressedU8(16 * 16),
      b: T.compressedU16(16 * 16),
    },
    reader: createDataReader({data: buffer})
  })

  const expandedA = fill(Array(16 * 16), 2)
  expandedA[0] = 1
  expandedA[255] = 3

  expect(data.a.decompressed).toEqual(expandedA)
  expect(data.b.decompressed).toEqual(expandedA.map(v => v * 1111))
}

{
  // can read dynamic length compressed buffers

  const buffer = Buffer.concat([
    Buffer.from(new Uint16Array([16 * 16, 16 * 16]).buffer),
    Buffer.from(new Uint32Array([5]).buffer),
    Buffer.from([1, 0xff, (16 * 16) - 2, 2, 3]),
    Buffer.from(new Uint32Array([4 * 2]).buffer),
    Buffer.from(new Uint16Array([1111, ((16 * 16) - 2) | 0xff00, 2222, 3333]).buffer),
  ])

  const data = readFormat({
    format: {
      lengthA: T.u16,
      lengthB: T.u16,
      a: T.compressedU8(({record}) => record.lengthA),
      b: T.compressedU16(({record}) => record.lengthB),
    },
    reader: createDataReader({data: buffer})
  })

  const expandedA = fill(Array(16 * 16), 2)
  expandedA[0] = 1
  expandedA[255] = 3

  expect(data.a.decompressed).toEqual(expandedA)
  expect(data.b.decompressed).toEqual(expandedA.map(v => v * 1111))
}

{
  // can read list of types

  const buffer = Buffer.concat([
    Buffer.from([0xff, 0xff]),
    Buffer.from(new Uint16Array([0xffff, 0xffff]).buffer),
    Buffer.from(new Uint32Array([0xffffffff, 0xffffffff]).buffer),
  ])

  const data = readFormat({
    format: {
      a: T.list(T.u8, 2),
      b: T.list(T.u16, 2),
      c: T.list(T.u32, 2),
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    a: [0xff, 0xff],
    b: [0xffff, 0xffff],
    c: [0xffffffff, 0xffffffff],
  })
}

{
  // T.list requires a length

  expect(() => T.list(T.u8)).toThrow(Error, 'T.list length must be defined')
}

{
  // can read nested formats

  const buffer = Buffer.concat([
    Buffer.from([0xff]),
    Buffer.from(new Uint16Array([0xffff]).buffer),
    Buffer.from(new Uint32Array([0xffffffff]).buffer),
  ])

  const data = readFormat({
    format: {
      a: T.u8,
      b: {
        c: T.u16,
        d: T.u32,
      },
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    a: 0xff,
    b: {
      c: 0xffff,
      d: 0xffffffff,
    }
  })
}

{
  // can read list of formats

  const buffer = Buffer.concat([
    Buffer.from([0xff]),
    Buffer.from(new Uint16Array([0xffff]).buffer),
    Buffer.from(new Uint32Array([0xffffffff]).buffer),
    Buffer.from(new Uint16Array([0xffff]).buffer),
    Buffer.from(new Uint32Array([0xffffffff]).buffer),
  ])

  const data = readFormat({
    format: {
      a: T.list({
        b: T.u16,
        c: T.u32,
      }, 2)
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    a: [
      {b: 0xffff, c: 0xffffffff},
      {b: 0xffff, c: 0xffffffff},
    ]
  })
}

{
  // can read list of dynamic length

  const buffer = Buffer.concat([
    Buffer.from([2, 3, 44, 55, 66, 77, 88, 99]),
  ])

  const data = readFormat({
    format: {
      w: T.u8,
      h: T.u8,
      grid: T.list(T.u8, ({record}) => record.w * record.h),
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    w: 2,
    h: 3,
    grid: [44, 55, 66, 77, 88, 99],
  })
}

{
  // can read current T.list index in dynamic length calculators

  const firstLayerWidth = 3
  const firstLayerHeight = 4
  const firstLayerFill = 77
  const secondLayerWidth = 5
  const secondLayerHeight = 6
  const secondLayerFill = 88
  const buffer = Buffer.concat([
    Buffer.from([
      2,
      firstLayerWidth, firstLayerHeight,
      secondLayerWidth, secondLayerHeight,
    ]),
    Buffer.concat([
      Buffer.from(new Uint32Array([2 * 2]).buffer),
      Buffer.from(new Uint16Array([
        (firstLayerWidth * firstLayerHeight) | 0xff00,
        firstLayerFill,
      ]).buffer),
      Buffer.from(new Uint32Array([2 * 2]).buffer),
      Buffer.from(new Uint16Array([
        (secondLayerWidth * secondLayerHeight) | 0xff00,
        secondLayerFill
      ]).buffer),
    ])
  ])

  const data = readFormat({
    format: {
      numlayers: T.u8,
      layer: T.list({
        sizex: T.u8,
        sizey: T.u8,
      }, ({record}) => record.numlayers),
      layers: T.list(
        T.compressedU16(({record, listIndex}) => {
          const sizex = record.layer[listIndex].sizex
          const sizey = record.layer[listIndex].sizey
          const size = sizex * sizey
          return size
        }),
        ({record}) => record.numlayers
      )
    },
    reader: createDataReader({data: buffer})
  })

  expect(data.numlayers).toBe(2)
  expect(data.layer.length).toBe(2)
  expect(data.layers.length).toBe(2)
  expect(data.layers[0].decompressed).toEqual(
    fill(Array(firstLayerWidth * firstLayerHeight), firstLayerFill)
  )
  expect(data.layers[1].decompressed).toEqual(
    fill(Array(secondLayerWidth * secondLayerHeight), secondLayerFill)
  )
}

{
  // can read list of all remaining bytes

  const buffer = Buffer.concat([
    Buffer.from([44, 55, 66, 77, 88, 99]),
  ])

  const data = readFormat({
    format: {
      grid: T.list(T.u8, ({reader}) => reader.remaining),
    },
    reader: createDataReader({data: buffer})
  })

  expect(data).toEqual({
    grid: [44, 55, 66, 77, 88, 99],
  })
}<|endoftext|>


<commit_before>/*
 * haibu.js: Top level include for the haibu module
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

var fs = require('fs'),
    events = require('events'),
    path = require('path'),
    hookio = require('hook.io');

var haibu = module.exports = new events.EventEmitter();

//
// Expose version through `pkginfo`.
//
require('pkginfo')(module, 'version');

haibu.log           = require('cliff');
haibu.config        = require('./haibu/core/config');
haibu.utils         = require('./haibu/utils');
haibu.Spawner       = require('./haibu/core/spawner').Spawner;
haibu.repository    = require('./haibu/repositories');
haibu.balancer      = require('./haibu/balancer');
haibu.drone         = require('./haibu/drone');
haibu.initialized   = false;
haibu.running       = {};
haibu.plugins       = {};
haibu.activePlugins = {};

//
// function init (options, callback)
// Initializes haibu directories and models
//
haibu.init = function (options, callback) {
  if (haibu.initialized) {
    return callback();
  }

  haibu.config.load(options, function (err) {
    if (err) {
      return callback(err);
    }

    haibu.utils.initDirectories(function initialized () {
      haibu.initialized = true;
      callback();
    });
  });
};

//
// ### function use (plugin)
// #### @plugin {Object} Instance of a plugin from `haibu.plugins`
// Adds the specified `plugin` to the set of active plugins used by haibu.
//
haibu.use = function (plugin) {
  var args = Array.prototype.slice.call(arguments),
      callback = typeof args[args.length - 1] === 'function' && args.pop(),
      options = args.length > 1 && args.pop();

  if (!callback) {
    callback = function () {};
  }

  if (haibu.activePlugins[plugin.name]) {
    return callback();
  }

  haibu.activePlugins[plugin.name] = plugin;

  return plugin.init
    ? plugin.init(options, callback)
    : callback();
};

//
// Define each of our plugins as a lazy loaded `require` statement
//
fs.readdirSync(__dirname + '/haibu/plugins').forEach(function (plugin) {
  plugin = plugin.replace('.js', '');
  haibu.plugins.__defineGetter__(plugin, function () {
    return require('./haibu/plugins/' + plugin);
  });
});
<commit_msg>add streaming deploy interface<commit_after>/*
 * haibu.js: Top level include for the haibu module
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

var fs = require('fs'),
    events = require('events'),
    path = require('path'),
    hookio = require('hook.io')
    ;

var haibu = module.exports = new events.EventEmitter();

//
// Expose version through `pkginfo`.
//
require('pkginfo')(module, 'version');

haibu.log           = require('cliff');
haibu.config        = require('./haibu/core/config');
haibu.utils         = require('./haibu/utils');
haibu.Spawner       = require('./haibu/core/spawner').Spawner;
haibu.repository    = require('./haibu/repositories');
haibu.balancer      = require('./haibu/balancer');
haibu.drone         = require('./haibu/drone');
haibu.deploy = null;
haibu.initialized   = false;
haibu.running       = {};
haibu.plugins       = {};
haibu.activePlugins = {};

//
// function init (options, callback)
// Initializes haibu directories and models
//
haibu.init = function (options, callback) {
  if (haibu.initialized) {
    return callback();
  }

  haibu.config.load(options, function (err) {
    if (err) {
      return callback(err);
    }

    haibu.utils.initDirectories(function initialized () {
    deploy = require('./haibu/deploy') //push deploy

      haibu.initialized = true;
      callback();
    });
  });
};

//
// ### function use (plugin)
// #### @plugin {Object} Instance of a plugin from `haibu.plugins`
// Adds the specified `plugin` to the set of active plugins used by haibu.
//
haibu.use = function (plugin) {
  var args = Array.prototype.slice.call(arguments),
      callback = typeof args[args.length - 1] === 'function' && args.pop(),
      options = args.length > 1 && args.pop();

  if (!callback) {
    callback = function () {};
  }

  if (haibu.activePlugins[plugin.name]) {
    return callback();
  }

  haibu.activePlugins[plugin.name] = plugin;

  return plugin.init
    ? plugin.init(options, callback)
    : callback();
};

//
// Define each of our plugins as a lazy loaded `require` statement
//
fs.readdirSync(__dirname + '/haibu/plugins').forEach(function (plugin) {
  plugin = plugin.replace('.js', '');
  haibu.plugins.__defineGetter__(plugin, function () {
    return require('./haibu/plugins/' + plugin);
  });
});
<|endoftext|>


<commit_before>/**
 * Featherlight - ultra slim jQuery lightbox
 * https://github.com/noelboss/featherlight
 *
 * Copyright 2014, Noel Bossart
 * MIT Licensed.
**/
(function($) {
	"use strict";
	if($ === 'undefined') {return; }

	/* featherlight object */
	var fl = {
		id: 0, /* used to manage ids */
		defaults: { /* you can access and override all defaults using $.fl.defaults */
			selector:     '[data-featherlight]',  /* elements that trigger the lightbox */
			context:      'body',                 /* context used to search for the lightbox content and triggers */
			type: {                               /* manually set type of lightbox. Otherwise, it will check for the targetAttrs value. */
				image: false,
				ajax: false
			},
			targetAttr:   'data-featherlight',    /* attribute of the triggered element that contains the selector to the lightbox content */
			openTrigger:  'click',                /* event that triggers the lightbox */
			closeTrigger: 'click',                /* event that triggers the closing of the lightbox */
			namespace:    'featherlight',         /* name of the events and css class prefix */
			resetCss:     false,                  /* reset all css */
			variant:      null,                   /* class that will be added to change look of the lightbox */
			closeOnBg:    true,                   /* close lightbox on click on the background */
			closeOnEsc:   true,                   /* close lightbox when pressing esc */
			background:   null,                   /* custom DOM for the background, wrapper and the closebutton */
			autostart:    true,                   /* initialize all links with that match "selector" on document ready */
			open: function(event){                /* opens the lightbox "this" contains $instance with the lightbox, and with the config */
				$.proxy($.featherlight.methods.open, this, event)();
			},
			close: function(event){                   /* closes the lightbox "this" contains $instance with the lightbox, and with the config */
				$.proxy($.featherlight.methods.close, this, event)();
			}
		},
		methods: { /* you can access and override all methods using $.featherlight.methods */
			/* setup iterrates over a single instance of featherlight and prepares the background and binds the events */
			setup: function(config, content){
				var $elm = $(this) || $(),
					config = $.extend({}, fl.defaults, config),
					variant = $elm.attr('data-'+config.namespace+'-variant') || config.variant,
					css = !config.resetCss ? config.namespace : config.namespace+'-reset', /* by adding -reset to the classname, we reset all the default css */
					$background = $(config.background || '

X

'),

					/* everything that we need later is stored in self (target) */
					self = {
						id: fl.id++,
						config: config,
						content: content,
						$elm: $elm,
						$instance: $background.clone().addClass(variant) /* clone DOM for the background, wrapper and the closebutton */
					};

				/* close when click on background */
				self.$instance.on(config.closeTrigger+'.'+config.namespace, $.proxy(config.close, self));

				/* bind or call open function */
				if($elm.length > 0 && this.tagName){
					$elm.on(config.openTrigger+'.'+config.namespace, $.proxy(config.open, self));
				} else {
					$.proxy(config.open, self)();
				}
			},

			/* this method prepares the content and converts it into a jQuery object */
			getContent: function(){
				var self = this,
					content = self.content,
					attr = self.$elm.attr(self.config.targetAttr) || '';

				/* if we have DOM, convert to jQuery Object */
				if(typeof content === 'string'){
					self.content = $(content);
				} else if(content instanceof $ === false){ /* if we have no jQuery Object */
					/* check if we have an image and create element */
					if(self.config.type.image === true || attr === 'image' || attr.match(/\.(png|jpg|jpeg|gif|tiff|bmp)$/i)){
						var url = attr.match(/\.(png|jpg|jpeg|gif|tiff|bmp)$/i) ? attr : self.$elm.attr('href');
						self.content = $('');
					}
					/* check if we have an ajax link */
					else if(self.config.type.ajax === true || attr === 'ajax' || attr.match(/(http|htm|php)/i)){
						var url = attr.match(/(http|htm|php)/i) ? attr : self.$elm.attr('href'),
						/* we are using load so one can specify a target with: url.html #targetelement */
						content = url ? $('

').load(url, function(response, status){
							if ( status !== "error" ) {
								$.featherlight(content.html());
							}
						}) : null;
						return false;
					}
					/* otherwise create jquery element by using the attribute as selector */
					if(attr) {
						self.content = $($(attr), self.config.context);
					}
					/* could not find any content */
					else {
						return false;
					}
				}

				/* we need a special class for the iframe */
				if(self.content.is('iframe') || $('iframe', self.content).length > 0){
					self.$instance.addClass(self.config.namespace+'-iframe');
				}
				self.content.addClass(self.config.namespace+'-inner');
			},

			/* opens the lightbox "this" contains $instance with the lightbox, and with the config */
			open: function(event){
				if(event){event.preventDefault();}
				var self = this;

				/* If we have content, add it and show lightbox */
				if($.proxy(fl.methods.getContent, self)() !== false){

					if(self.config.closeOnEsc){
						$(document).bind('keyup.'+self.config.namespace+self.id, function(e) {
							if (e.keyCode === 27) { // esc keycode
								self.$instance.find('.'+self.config.namespace+'-close').click();
							}
						});
					}

					self.$instance
						.prependTo('body').fadeIn()
						.find('.'+self.config.namespace+'-close')
						.after(self.content);
				}
			},

			/* closes the lightbox "this" contains $instance with the lightbox, and with the config */
			close: function(event){
				if(event){
					event.preventDefault();
				}
				var self = this,
					config = self.config,
					$instance = $(event.target);

				if((config.closeOnBg && $instance.is('.'+config.namespace)) || $instance.is('.'+config.namespace+'-close') ){
					if(self.config.closeOnEsc){
						$(document).unbind('keyup.'+self.config.namespace+self.id);
					}

					self.$instance.fadeOut(function(){
						self.$instance.detach();
					});
				}
			}
		}
	};

	/* extend jQuery with standalone featherlight method  $.featherlight(elm, config); */
	$.featherlight = function($content, config) {
		$.proxy(fl.methods.setup, null, config, $content)();
	};

	/* extend jQuery with selector featherlight method $(elm).featherlight(config, elm); */
	$.fn.featherlight = function(config, $content) {
		$(this).each(function(){
			$.proxy(fl.methods.setup, this, config, $content)();
		});
	};

	/* extend featherlight with defaults and methods */
	$.extend($.featherlight, fl);

	/* bind featherlight on ready if config autostart is true */
	$(document).ready(function(){
		var config = $.featherlight.defaults;
		if(config.autostart){
			$(config.selector, config.context).featherlight();
		}
	});
}(typeof jQuery === 'function' ? jQuery : alert('To much lightness, Featherlight needs jQuery.')));<commit_msg>Added closing and opening speed<commit_after>/**
 * Featherlight - ultra slim jQuery lightbox
 * https://github.com/noelboss/featherlight
 *
 * Copyright 2014, Noel Bossart
 * MIT Licensed.
**/
(function($) {
	"use strict";
	if($ === 'undefined') {return; }

	/* featherlight object */
	var fl = {
		id: 0,                                    /* used to id single featherlight instances */
		defaults: {                               /* you can access and override all defaults using $.fl.defaults */
			selector:     '[data-featherlight]',  /* elements that trigger the lightbox */
			context:      'body',                 /* context used to search for the lightbox content and triggers */
			type: {                               /* manually set type of lightbox. Otherwise, it will check for the targetAttrs value. */
				image: false,
				ajax: false
			},
			targetAttr:   'data-featherlight',    /* attribute of the triggered element that contains the selector to the lightbox content */
			openTrigger:  'click',                /* event that triggers the lightbox */
			closeTrigger: 'click',                /* event that triggers the closing of the lightbox */
			openSpeed:    250,                    /* duration of opening animation */
			closeSpeed:   250,                    /* duration of closing animation */
			namespace:    'featherlight',         /* name of the events and css class prefix */
			resetCss:     false,                  /* reset all css */
			variant:      null,                   /* class that will be added to change look of the lightbox */
			closeOnBg:    true,                   /* close lightbox on click on the background */
			closeOnEsc:   true,                   /* close lightbox when pressing esc */
			background:   null,                   /* custom DOM for the background, wrapper and the closebutton */
			autostart:    true,                   /* initialize all links with that match "selector" on document ready */
			open: function(event){                /* opens the lightbox "this" contains $instance with the lightbox, and with the config */
				$.proxy($.featherlight.methods.open, this, event)();
			},
			close: function(event){                   /* closes the lightbox "this" contains $instance with the lightbox, and with the config */
				$.proxy($.featherlight.methods.close, this, event)();
			}
		},
		methods: { /* you can access and override all methods using $.featherlight.methods */
			/* setup iterrates over a single instance of featherlight and prepares the background and binds the events */
			setup: function(config, content){
				config = $.extend({}, fl.defaults, config);

				var $elm = $(this) || $(),
					variant = $elm.attr('data-'+config.namespace+'-variant') || config.variant,
					css = !config.resetCss ? config.namespace : config.namespace+'-reset', /* by adding -reset to the classname, we reset all the default css */
					$background = $(config.background || '

X

'),

					/* everything that we need later is stored in self (target) */
					self = {
						id: fl.id++,
						config: config,
						content: content,
						$elm: $elm,
						$instance: $background.clone().addClass(variant) /* clone DOM for the background, wrapper and the closebutton */
					};

				/* close when click on background */
				self.$instance.on(config.closeTrigger+'.'+config.namespace, $.proxy(config.close, self));

				/* bind or call open function */
				if($elm.length > 0 && this.tagName){
					$elm.on(config.openTrigger+'.'+config.namespace, $.proxy(config.open, self));
				} else {
					$.proxy(config.open, self)();
				}
			},

			/* this method prepares the content and converts it into a jQuery object */
			getContent: function(){
				var self = this,
					content = self.content,
					attr = self.$elm.attr(self.config.targetAttr) || '',
					url = '';

				/* if we have DOM, convert to jQuery Object */
				if(typeof content === 'string'){
					self.content = $(content);
				} else if(content instanceof $ === false){ /* if we have no jQuery Object */
					/* check if we have an image and create element */
					if(self.config.type.image === true || attr === 'image' || attr.match(/\.(png|jpg|jpeg|gif|tiff|bmp)$/i)){
						url = attr.match(/\.(png|jpg|jpeg|gif|tiff|bmp)$/i) ? attr : self.$elm.attr('href');
						self.content = $('');
					}
					/* check if we have an ajax link */
					else if(self.config.type.ajax === true || attr === 'ajax' || attr.match(/(http|htm|php)/i)){
						url = attr.match(/(http|htm|php)/i) ? attr : self.$elm.attr('href');
						/* we are using load so one can specify a target with: url.html #targetelement */
						content = url ? $('

').load(url, function(response, status){
							if ( status !== "error" ) {
								$.featherlight(content.html());
							}
						}) : null;
						return false;
					}
					/* otherwise create jquery element by using the attribute as selector */
					else if(attr) {
						self.content = $($(attr), self.config.context);
					}
					/* could not find any content */
					else {
						return false;
					}
				}

				/* we need a special class for the iframe */
				if(self.content.is('iframe') || $('iframe', self.content).length > 0){
					self.$instance.addClass(self.config.namespace+'-iframe');
				}
				self.content.addClass(self.config.namespace+'-inner');
			},

			/* opens the lightbox "this" contains $instance with the lightbox, and with the config */
			open: function(event){
				if(event){event.preventDefault();}
				var self = this;

				/* If we have content, add it and show lightbox */
				if($.proxy(fl.methods.getContent, self)() !== false){

					if(self.config.closeOnEsc){
						$(document).bind('keyup.'+self.config.namespace+self.id, function(e) {
							if (e.keyCode === 27) { // esc keycode
								self.$instance.find('.'+self.config.namespace+'-close').click();
							}
						});
					}

					self.$instance
						.prependTo('body').fadeIn(self.config.openSpeed)
						.find('.'+self.config.namespace+'-close')
						.after(self.content);
				}
			},

			/* closes the lightbox "this" contains $instance with the lightbox, and with the config */
			close: function(event){
				if(event){
					event.preventDefault();
				}
				var self = this,
					config = self.config,
					$instance = $(event.target);

				if((config.closeOnBg && $instance.is('.'+config.namespace)) || $instance.is('.'+config.namespace+'-close') ){
					if(self.config.closeOnEsc){
						$(document).unbind('keyup.'+self.config.namespace+self.id);
					}

					self.$instance.fadeOut(self.config.closeSpeed,function(){
						self.$instance.detach();
					});
				}
			}
		}
	};

	/* extend jQuery with standalone featherlight method  $.featherlight(elm, config); */
	$.featherlight = function($content, config) {
		$.proxy(fl.methods.setup, null, config, $content)();
	};

	/* extend jQuery with selector featherlight method $(elm).featherlight(config, elm); */
	$.fn.featherlight = function(config, $content) {
		$(this).each(function(){
			$.proxy(fl.methods.setup, this, config, $content)();
		});
	};

	/* extend featherlight with defaults and methods */
	$.extend($.featherlight, fl);

	/* bind featherlight on ready if config autostart is true */
	$(document).ready(function(){
		var config = $.featherlight.defaults;
		if(config.autostart){
			$(config.selector, config.context).featherlight();
		}
	});
}(typeof jQuery === 'function' ? jQuery : alert('To much lightness, Featherlight needs jQuery.')));<|endoftext|>


<commit_before>const { promisify } = require('util');
const hostile = require('hostile');
const { red, yellow, bold } = require('chalk');

const { hosts, sites: contextSites } = require('../context');
const { suggestScript } = require('./suggestScript');

const setSystemHost = promisify(hostile.set);
const getSystemHosts = promisify(hostile.get);

const getAppHosts = (configuredSites = contextSites) =>
  configuredSites
    .filter((site) => site.host)
    .map((site) => site.host)
    .concat(hosts);

const setupHosts = async () => {
  try {
    const appHosts = getAppHosts().filter((host) => host !== 'localhost');

    for (let i = 0; i < appHosts.length; i++) {
      const host = appHosts[i];

      await setSystemHost('127.0.0.1', host);
      console.log(`Sucessfully added '${bold(host)}' to your hosts file`);
    }
  } catch (e) {
    if (e.code === 'EACCES') {
      console.log(red('Error: setup-hosts must be run with root privileges'));
    } else {
      console.error(e);
    }

    throw e;
  }
};

const getMissingHosts = async (sites) => {
  const systemHosts = await getSystemHosts(false);
  const appHosts = getAppHosts(sites);

  return appHosts.filter(
    (appHost) => !systemHosts.find(([_, host]) => appHost === host),
  );
};

const checkHosts = async () => {
  try {
    const missingHosts = await getMissingHosts();

    if (missingHosts.length > 0) {
      missingHosts.forEach((appHost) => {
        console.log(
          yellow(
            `Host '${bold(appHost)}' is not configured in your hosts file`,
          ),
        );
      });

      await suggestScript('setup-hosts', { sudo: true });
    }
  } catch (e) {
    // swallow error as this just a warning check
  }
};

module.exports = {
  setupHosts,
  checkHosts,
  getAppHosts,
  getMissingHosts,
};
<commit_msg>Fix setup-hosts typo (#551)<commit_after>const { promisify } = require('util');
const hostile = require('hostile');
const { red, yellow, bold } = require('chalk');

const { hosts, sites: contextSites } = require('../context');
const { suggestScript } = require('./suggestScript');

const setSystemHost = promisify(hostile.set);
const getSystemHosts = promisify(hostile.get);

const getAppHosts = (configuredSites = contextSites) =>
  configuredSites
    .filter((site) => site.host)
    .map((site) => site.host)
    .concat(hosts);

const setupHosts = async () => {
  try {
    const appHosts = getAppHosts().filter((host) => host !== 'localhost');

    for (let i = 0; i < appHosts.length; i++) {
      const host = appHosts[i];

      await setSystemHost('127.0.0.1', host);
      console.log(`Successfully added '${bold(host)}' to your hosts file`);
    }
  } catch (e) {
    if (e.code === 'EACCES') {
      console.log(red('Error: setup-hosts must be run with root privileges'));
    } else {
      console.error(e);
    }

    throw e;
  }
};

const getMissingHosts = async (sites) => {
  const systemHosts = await getSystemHosts(false);
  const appHosts = getAppHosts(sites);

  return appHosts.filter(
    (appHost) => !systemHosts.find(([_, host]) => appHost === host),
  );
};

const checkHosts = async () => {
  try {
    const missingHosts = await getMissingHosts();

    if (missingHosts.length > 0) {
      missingHosts.forEach((appHost) => {
        console.log(
          yellow(
            `Host '${bold(appHost)}' is not configured in your hosts file`,
          ),
        );
      });

      await suggestScript('setup-hosts', { sudo: true });
    }
  } catch (e) {
    // swallow error as this just a warning check
  }
};

module.exports = {
  setupHosts,
  checkHosts,
  getAppHosts,
  getMissingHosts,
};
<|endoftext|>


<commit_before>/*
* Flocking Browser-Dependent Unit Generators
* http://github.com/colinbdclark/flocking
*
* Copyright 2013-2014, Colin Clark
* Dual licensed under the MIT and GPL Version 2 licenses.
*/

/*global require, Float32Array, window*/
/*jshint white: false, newcap: true, regexp: true, browser: true,
    forin: false, nomen: true, bitwise: false, maxerr: 100,
    indent: 4, plusplus: false, curly: true, eqeqeq: true,
    freeze: true, latedef: true, noarg: true, nonew: true, quotmark: double, undef: true,
    unused: true, strict: true, asi: false, boss: false, evil: false, expr: false,
    funcscope: false*/

var fluid = fluid || require("infusion"),
    flock = fluid.registerNamespace("flock");

(function () {
    "use strict";

    var $ = fluid.registerNamespace("jQuery");

    fluid.registerNamespace("flock.ugen");

    /***************************
     * Browser-dependent UGens *
     ***************************/

    flock.ugen.scope = function (inputs, output, options) {
        var that = flock.ugen(inputs, output, options);

        that.gen = function (numSamps) {
            var m = that.model,
                spf = m.spf,
                bufIdx = m.bufIdx,
                buf = m.scope.values,
                i;

            for (i = 0; i < numSamps; i++) {
                buf[bufIdx] = that.inputs.source.output[i];
                if (bufIdx < spf) {
                    bufIdx += 1;
                } else {
                    bufIdx = 0;
                    that.scopeView.refreshView();
                }
            }
            m.bufIdx = bufIdx;
        };

        that.onInputChanged = function () {
            // Pass the "source" input directly back as the output from this ugen.
            that.output = that.inputs.source.output;
        };

        that.init = function () {
            that.model.spf = Math.round(that.model.sampleRate / that.options.fps);
            that.model.bufIdx = 0;

            // Set up the scopeView widget.
            that.model.scope = that.options.styles;
            that.model.scope.values = new Float32Array(that.model.spf);
            that.scopeView = flock.view.scope(that.options.canvas, that.model.scope);

            that.onInputChanged();
            that.scopeView.refreshView();
        };

        that.init();
        return that;
    };

    fluid.defaults("flock.ugen.scope", {
        rate: "audio",
        inputs: {
            source: null
        },
        ugenOptions: {
            fps: 60,
            styles: {
                strokeColor: "#777777",
                strokeWidth: 1
            }
        }
    });

    flock.ugen.mouse = {};

    /**
     * Tracks the mouse's position along the specified axis within the boundaries the whole screen.
     * This unit generator will generate a signal between 0.0 and 1.0 based on the position of the mouse;
     * use the mul and add inputs to scale this value to an appropriate control signal.
     */
    flock.ugen.mouse.cursor = function (inputs, output, options) {
        var that = flock.ugen(inputs, output, options);

        /**
         * Generates a control rate signal between 0.0 and 1.0 by tracking the mouse's position along the specified axis.
         *
         * @param numSamps the number of samples to generate
         */
        that.exponentialGen = function (numSamps) {
            var m = that.model,
                scaledMouse = m.mousePosition / m.size,
                movingAvg = m.movingAvg,
                lag = that.inputs.lag.output[0],
                add = that.inputs.add.output[0],
                mul = that.inputs.mul.output[0],
                lagCoef = m.lagCoef,
                out = that.output,
                pow = Math.pow,
                i,
                max;

            if (lag !== lagCoef) {
                lagCoef = lag === 0 ? 0.0 : Math.exp(flock.LOG001 / (lag * m.sampleRate));
                m.lagCoef = lagCoef;
            }

            for (i = 0; i < numSamps; i++) {
                max = mul + add;
                scaledMouse = pow(max  / add, scaledMouse) * add;
                movingAvg = scaledMouse + lagCoef * (movingAvg - scaledMouse); // 1-pole filter averages mouse values.
                out[i] = movingAvg;
            }

            m.movingAvg = movingAvg;
        };

        that.linearGen = function (numSamps) {
            var m = that.model,
                scaledMouse = m.mousePosition / m.size,
                movingAvg = m.movingAvg,
                lag = that.inputs.lag.output[0],
                add = that.inputs.add.output[0],
                mul = that.inputs.mul.output[0],
                lagCoef = m.lagCoef,
                out = that.output,
                i;

            if (lag !== lagCoef) {
                lagCoef = lag === 0 ? 0.0 : Math.exp(flock.LOG001 / (lag * m.sampleRate));
                m.lagCoef = lagCoef;
            }

            for (i = 0; i < numSamps; i++) {
                movingAvg = scaledMouse + lagCoef * (movingAvg - scaledMouse);
                out[i] = movingAvg * mul + add;
            }

            m.movingAvg = movingAvg;
        };

        that.noInterpolationGen = function (numSamps) {
            var m = that.model,
                scaledMouse = m.mousePosition / m.size,
                add = that.inputs.add.output[0],
                mul = that.inputs.mul.output[0],
                out = that.output,
                i;

            for (i = 0; i < numSamps; i++) {
                out[i] = scaledMouse * mul + add;
            }
        };

        that.moveListener = function (e) {
            var m = that.model,
                pos = e[m.eventProp],
                off;

            if (pos === undefined) {
                off = $(e.target).offset();
                e.offsetX = e.clientX - off.left;
                e.offsetY = e.clientY - off.top;
                pos = e[m.eventProp];
            }
            m.mousePosition = m.isWithinTarget ? pos : 0.0;
        };

        that.overListener = function () {
            that.model.isWithinTarget = true;
        };

        that.outListener = function () {
            var m = that.model;
            m.isWithinTarget = false;
            m.mousePosition = 0.0;
        };

        that.downListener = function () {
            that.model.isMouseDown = true;
        };

        that.upListener = function () {
            var m = that.model;
            m.isMouseDown = false;
            m.mousePosition = 0;
        };

        that.moveWhileDownListener = function (e) {
            if (that.model.isMouseDown) {
                that.moveListener(e);
            }
        };

        that.bindEvents = function () {
            var m = that.model,
                target = m.target,
                moveListener = that.moveListener;

            if (that.options.onlyOnMouseDown) {
                target.mousedown(that.downListener);
                target.mouseup(that.upListener);
                moveListener = that.moveWhileDownListener;
            }

            target.mouseover(that.overListener);
            target.mouseout(that.outListener);
            target.mousemove(moveListener);
        };

        that.onInputChanged = function () {
            flock.onMulAddInputChanged(that);

            var interp = that.options.interpolation;
            that.gen = interp === "none" ? that.noInterpolationGen : interp === "exponential" ? that.exponentialGen : that.linearGen;
            that.model.exponential = interp === "exponential";
        };

        that.init = function () {
            var m = that.model,
                options = that.options,
                axis = options.axis,
                target = $(options.target || window);

            if (axis === "x" || axis === "width" || axis === "horizontal") {
                m.eventProp = "offsetX";
                m.size = target.width();
            } else {
                m.eventProp = "offsetY";
                m.size = target.height();
            }

            m.mousePosition = 0;
            m.movingAvg = 0;
            m.target = target;

            that.bindEvents();
            that.onInputChanged();
        };

        that.init();
        return that;
    };

    fluid.defaults("flock.ugen.mouse.cursor", {
        rate: "control",
        inputs: {
            lag: 0.5,
            add: 0.0,
            mul: 1.0
        },

        ugenOptions: {
            axis: "x"
        }
    });

    flock.ugen.mouse.click = function (inputs, output, options) {
        var that = flock.ugen(inputs, output, options);

        that.gen = function (numSamps) {
            var out = that.output,
                m = that.model,
                i;

            for (i = 0; i < numSamps; i++) {
                out[i] = m.value;
            }

            that.mulAdd(numSamps);
        };

        that.mouseDownListener = function () {
            that.model.value = 1.0;
        };

        that.mouseUpListener = function () {
            that.model.value = 0.0;
        };

        that.init = function () {
            var m = that.model;
            m.target = typeof (that.options.target) === "string" ?
                document.querySelector(that.options.target) : that.options.target || window;
            m.value = 0.0;
            m.target.addEventListener("mousedown", that.mouseDownListener, false);
            m.target.addEventListener("mouseup", that.mouseUpListener, false);

            that.onInputChanged();
        };

        that.onInputChanged = function () {
            flock.onMulAddInputChanged(that);
        };

        that.init();
        return that;
    };

    fluid.defaults("flock.ugen.mouse.click", {
        rate: "control"
    });

}());
<commit_msg>change mousemove behavior to clientX,Y instead of offsetX,Y<commit_after>/*
* Flocking Browser-Dependent Unit Generators
* http://github.com/colinbdclark/flocking
*
* Copyright 2013-2014, Colin Clark
* Dual licensed under the MIT and GPL Version 2 licenses.
*/

/*global require, Float32Array, window*/
/*jshint white: false, newcap: true, regexp: true, browser: true,
    forin: false, nomen: true, bitwise: false, maxerr: 100,
    indent: 4, plusplus: false, curly: true, eqeqeq: true,
    freeze: true, latedef: true, noarg: true, nonew: true, quotmark: double, undef: true,
    unused: true, strict: true, asi: false, boss: false, evil: false, expr: false,
    funcscope: false*/

var fluid = fluid || require("infusion"),
    flock = fluid.registerNamespace("flock");

(function () {
    "use strict";

    var $ = fluid.registerNamespace("jQuery");

    fluid.registerNamespace("flock.ugen");

    /***************************
     * Browser-dependent UGens *
     ***************************/

    flock.ugen.scope = function (inputs, output, options) {
        var that = flock.ugen(inputs, output, options);

        that.gen = function (numSamps) {
            var m = that.model,
                spf = m.spf,
                bufIdx = m.bufIdx,
                buf = m.scope.values,
                i;

            for (i = 0; i < numSamps; i++) {
                buf[bufIdx] = that.inputs.source.output[i];
                if (bufIdx < spf) {
                    bufIdx += 1;
                } else {
                    bufIdx = 0;
                    that.scopeView.refreshView();
                }
            }
            m.bufIdx = bufIdx;
        };

        that.onInputChanged = function () {
            // Pass the "source" input directly back as the output from this ugen.
            that.output = that.inputs.source.output;
        };

        that.init = function () {
            that.model.spf = Math.round(that.model.sampleRate / that.options.fps);
            that.model.bufIdx = 0;

            // Set up the scopeView widget.
            that.model.scope = that.options.styles;
            that.model.scope.values = new Float32Array(that.model.spf);
            that.scopeView = flock.view.scope(that.options.canvas, that.model.scope);

            that.onInputChanged();
            that.scopeView.refreshView();
        };

        that.init();
        return that;
    };

    fluid.defaults("flock.ugen.scope", {
        rate: "audio",
        inputs: {
            source: null
        },
        ugenOptions: {
            fps: 60,
            styles: {
                strokeColor: "#777777",
                strokeWidth: 1
            }
        }
    });

    flock.ugen.mouse = {};

    /**
     * Tracks the mouse's position along the specified axis within the boundaries the whole screen.
     * This unit generator will generate a signal between 0.0 and 1.0 based on the position of the mouse;
     * use the mul and add inputs to scale this value to an appropriate control signal.
     */
    flock.ugen.mouse.cursor = function (inputs, output, options) {
        var that = flock.ugen(inputs, output, options);

        /**
         * Generates a control rate signal between 0.0 and 1.0 by tracking the mouse's position along the specified axis.
         *
         * @param numSamps the number of samples to generate
         */
        that.exponentialGen = function (numSamps) {
            var m = that.model,
                scaledMouse = m.mousePosition / m.size,
                movingAvg = m.movingAvg,
                lag = that.inputs.lag.output[0],
                add = that.inputs.add.output[0],
                mul = that.inputs.mul.output[0],
                lagCoef = m.lagCoef,
                out = that.output,
                pow = Math.pow,
                i,
                max;

            if (lag !== lagCoef) {
                lagCoef = lag === 0 ? 0.0 : Math.exp(flock.LOG001 / (lag * m.sampleRate));
                m.lagCoef = lagCoef;
            }

            for (i = 0; i < numSamps; i++) {
                max = mul + add;
                scaledMouse = pow(max  / add, scaledMouse) * add;
                movingAvg = scaledMouse + lagCoef * (movingAvg - scaledMouse); // 1-pole filter averages mouse values.
                out[i] = movingAvg;
            }

            m.movingAvg = movingAvg;
        };

        that.linearGen = function (numSamps) {
            var m = that.model,
                scaledMouse = m.mousePosition / m.size,
                movingAvg = m.movingAvg,
                lag = that.inputs.lag.output[0],
                add = that.inputs.add.output[0],
                mul = that.inputs.mul.output[0],
                lagCoef = m.lagCoef,
                out = that.output,
                i;

            if (lag !== lagCoef) {
                lagCoef = lag === 0 ? 0.0 : Math.exp(flock.LOG001 / (lag * m.sampleRate));
                m.lagCoef = lagCoef;
            }

            for (i = 0; i < numSamps; i++) {
                movingAvg = scaledMouse + lagCoef * (movingAvg - scaledMouse);
                out[i] = movingAvg * mul + add;
            }

            m.movingAvg = movingAvg;
        };

        that.noInterpolationGen = function (numSamps) {
            var m = that.model,
                scaledMouse = m.mousePosition / m.size,
                add = that.inputs.add.output[0],
                mul = that.inputs.mul.output[0],
                out = that.output,
                i;

            for (i = 0; i < numSamps; i++) {
                out[i] = scaledMouse * mul + add;
            }
        };

        that.moveListener = function (e) {
            var m = that.model,
                pos = e[m.eventProp],
                off;

            if (pos === undefined) {
                off = $(e.target).offset();
                e.offsetX = e.clientX - off.left;
                e.offsetY = e.clientY - off.top;
                pos = e[m.eventProp];
            }
            m.mousePosition = m.isWithinTarget ? pos : 0.0;
        };

        that.overListener = function () {
            that.model.isWithinTarget = true;
        };

        that.outListener = function () {
            var m = that.model;
            m.isWithinTarget = false;
            m.mousePosition = 0.0;
        };

        that.downListener = function () {
            that.model.isMouseDown = true;
        };

        that.upListener = function () {
            var m = that.model;
            m.isMouseDown = false;
            m.mousePosition = 0;
        };

        that.moveWhileDownListener = function (e) {
            if (that.model.isMouseDown) {
                that.moveListener(e);
            }
        };

        that.bindEvents = function () {
            var m = that.model,
                target = m.target,
                moveListener = that.moveListener;

            if (that.options.onlyOnMouseDown) {
                target.mousedown(that.downListener);
                target.mouseup(that.upListener);
                moveListener = that.moveWhileDownListener;
            }

            target.mouseover(that.overListener);
            target.mouseout(that.outListener);
            target.mousemove(moveListener);
        };

        that.onInputChanged = function () {
            flock.onMulAddInputChanged(that);

            var interp = that.options.interpolation;
            that.gen = interp === "none" ? that.noInterpolationGen : interp === "exponential" ? that.exponentialGen : that.linearGen;
            that.model.exponential = interp === "exponential";
        };

        that.init = function () {
            var m = that.model,
                options = that.options,
                axis = options.axis,
                target = $(options.target || window);

            if (axis === "x" || axis === "width" || axis === "horizontal") {
                m.eventProp = "clientX";
                m.size = target.width();
            } else {
                m.eventProp = "clientY";
                m.size = target.height();
            }

            m.mousePosition = 0;
            m.movingAvg = 0;
            m.target = target;

            that.bindEvents();
            that.onInputChanged();
        };

        that.init();
        return that;
    };

    fluid.defaults("flock.ugen.mouse.cursor", {
        rate: "control",
        inputs: {
            lag: 0.5,
            add: 0.0,
            mul: 1.0
        },

        ugenOptions: {
            axis: "x"
        }
    });

    flock.ugen.mouse.click = function (inputs, output, options) {
        var that = flock.ugen(inputs, output, options);

        that.gen = function (numSamps) {
            var out = that.output,
                m = that.model,
                i;

            for (i = 0; i < numSamps; i++) {
                out[i] = m.value;
            }

            that.mulAdd(numSamps);
        };

        that.mouseDownListener = function () {
            that.model.value = 1.0;
        };

        that.mouseUpListener = function () {
            that.model.value = 0.0;
        };

        that.init = function () {
            var m = that.model;
            m.target = typeof (that.options.target) === "string" ?
                document.querySelector(that.options.target) : that.options.target || window;
            m.value = 0.0;
            m.target.addEventListener("mousedown", that.mouseDownListener, false);
            m.target.addEventListener("mouseup", that.mouseUpListener, false);

            that.onInputChanged();
        };

        that.onInputChanged = function () {
            flock.onMulAddInputChanged(that);
        };

        that.init();
        return that;
    };

    fluid.defaults("flock.ugen.mouse.click", {
        rate: "control"
    });

}());
<|endoftext|>


<commit_before>(function(Two) {

  /**
   * Constants
   */
  var mod = Two.Utils.mod, toFixed = Two.Utils.toFixed;
  var getRatio = Two.Utils.getRatio;

  var canvas = {

    group: {

      renderChild: function(child) {
        canvas[child._renderer.type].render.call(child, this.ctx, true, this.clip);
      },

      render: function(ctx) {

        // TODO: Add a check here to only invoke _update if need be.
        this._update();

        var matrix = this._matrix.elements;
        var parent = this.parent;
        this._renderer.opacity = this._opacity
          * (parent && parent._renderer ? parent._renderer.opacity : 1);

        var mask = this._mask;
        // var clip = this._clip;

        if (!this._renderer.context) {
          this._renderer.context = {};
        }

        this._renderer.context.ctx = ctx;
        // this._renderer.context.clip = clip;

        ctx.save();

        ctx.transform(
          matrix[0], matrix[3], matrix[1], matrix[4], matrix[2], matrix[5]);

        if (mask) {
          canvas[mask._renderer.type].render.call(mask, ctx, true);
        }

        this.children.forEach(canvas.group.renderChild, ctx);

        ctx.restore();

       /**
         * Commented two-way functionality of clips / masks with groups and
         * polygons. Uncomment when this bug is fixed:
         * https://code.google.com/p/chromium/issues/detail?id=370951
         */

        // if (clip) {
        //   ctx.clip();
        // }

        return this.flagReset();

      }

    },

    polygon: {

      render: function(ctx, forced, parentClipped) {

        var matrix, stroke, linewidth, fill, opacity, visible, cap, join, miter,
            closed, commands, length, last, next, prev, a, c, d, ux, uy, vx, vy,
            ar, bl, br, cl, x, y, mask, clip;

        // TODO: Add a check here to only invoke _update if need be.
        this._update();

        matrix = this._matrix.elements;
        stroke = this._stroke;
        linewidth = this._linewidth;
        fill = this._fill;
        opacity = this._opacity * this.parent._renderer.opacity;
        visible = this._visible;
        cap = this._cap;
        join = this._join;
        miter = this._miter;
        closed = this._closed;
        commands = this._vertices; // Commands
        length = commands.length;
        last = length - 1;

        // mask = this._mask;
        clip = this._clip;

        if (!forced && (!visible || clip)) {
          return this;
        }

        // Transform

        ctx.save();

        if (matrix) {
          ctx.transform(
            matrix[0], matrix[3], matrix[1], matrix[4], matrix[2], matrix[5]);
        }

       /**
         * Commented two-way functionality of clips / masks with groups and
         * polygons. Uncomment when this bug is fixed:
         * https://code.google.com/p/chromium/issues/detail?id=370951
         */

        // if (mask) {
        //   canvas[mask._renderer.type].render.call(mask, ctx, true);
        // }

        // Styles

        if (fill) {
          ctx.fillStyle = fill;
        }
        if (stroke) {
          ctx.strokeStyle = stroke;
        }
        if (linewidth) {
          ctx.lineWidth = linewidth;
        }
        if (miter) {
          ctx.miterLimit = miter;
        }
        if (join) {
          ctx.lineJoin = join;
        }
        if (cap) {
          ctx.lineCap = cap;
        }
        if (_.isNumber(opacity)) {
          ctx.globalAlpha = opacity;
        }

        ctx.beginPath();
        commands.forEach(function(b, i) {

          x = toFixed(b.x);
          y = toFixed(b.y);

          switch (b._command) {

            case Two.Commands.close:
              ctx.closePath();
              break;

            case Two.Commands.curve:

              prev = closed ? mod(i - 1, length) : Math.max(i - 1, 0);
              next = closed ? mod(i + 1, length) : Math.min(i + 1, last);

              a = commands[prev];
              c = commands[next];
              ar = (a.controls && a.controls.right) || a;
              bl = (b.controls && b.controls.left) || b;

              if (a._relative) {
                vx = (ar.x + toFixed(a.x));
                vy = (ar.y + toFixed(a.y));
              } else {
                vx = toFixed(ar.x);
                vy = toFixed(ar.y);
              }

              if (b._relative) {
                ux = (bl.x + toFixed(b.x));
                uy = (bl.y + toFixed(b.y));
              } else {
                ux = toFixed(bl.x);
                uy = toFixed(bl.y);
              }

              ctx.bezierCurveTo(vx, vy, ux, uy, x, y);

              if (i >= last && closed) {

                c = d;

                br = (b.controls && b.controls.right) || b;
                cl = (c.controls && c.controls.left) || c;

                if (b._relative) {
                  vx = (br.x + toFixed(b.x));
                  vy = (br.y + toFixed(b.y));
                } else {
                  vx = toFixed(br.x);
                  vy = toFixed(br.y);
                }

                if (c._relative) {
                  ux = (cl.x + toFixed(c.x));
                  uy = (cl.y + toFixed(c.y));
                } else {
                  ux = toFixed(cl.x);
                  uy = toFixed(cl.y);
                }

                x = toFixed(c.x);
                y = toFixed(c.y);

                ctx.bezierCurveTo(vx, vy, ux, uy, x, y);

              }

              break;

            case Two.Commands.line:
              ctx.lineTo(x, y);
              break;

            case Two.Commands.move:
              d = b;
              ctx.moveTo(x, y);
              break;

          }

        });

        // Loose ends

        if (closed) {
          ctx.closePath();
        }

        if (!clip && !parentClipped) {
          ctx.fill();
          ctx.stroke();
        }

        ctx.restore();

        if (clip && !parentClipped) {
          ctx.clip();
        }

        return this.flagReset();

      }

    }

  };

  var Renderer = Two[Two.Types.canvas] = function(params) {

    this.domElement = params.domElement || document.createElement('canvas');
    this.ctx = this.domElement.getContext('2d');
    this.overdraw = params.overdraw || false;

    // Everything drawn on the canvas needs to be added to the scene.
    this.scene = new Two.Group();
    this.scene.parent = this;

  };

  _.extend(Renderer, {

    Utils: canvas

  });

  _.extend(Renderer.prototype, Backbone.Events, {

    setSize: function(width, height, ratio) {

      this.width = width;
      this.height = height;

      this.ratio = _.isUndefined(ratio) ? getRatio(this.ctx) : ratio;

      this.domElement.width = width * this.ratio;
      this.domElement.height = height * this.ratio;

      _.extend(this.domElement.style, {
        width: width + 'px',
        height: height + 'px'
      });

      return this;

    },

    render: function() {

      var isOne = this.ratio === 1;

      if (!isOne) {
        this.ctx.save();
        this.ctx.scale(this.ratio, this.ratio);
      }

      if (!this.overdraw) {
        this.ctx.clearRect(0, 0, this.width, this.height);
      }

      canvas.group.render.call(this.scene, this.ctx);

      if (!isOne) {
        this.ctx.restore();
      }

      return this;

    }

  });

  function resetTransform(ctx) {
    ctx.setTransform(1, 0, 0, 1, 0, 0);
  }

})(Two);
<commit_msg>Fix merge<commit_after>(function(Two) {

  /**
   * Constants
   */
  var mod = Two.Utils.mod, toFixed = Two.Utils.toFixed;
  var getRatio = Two.Utils.getRatio;

  var canvas = {

    group: {

      renderChild: function(child) {
        canvas[child._renderer.type].render.call(child, this.ctx, true, this.clip);
      },

      render: function(ctx) {

        // TODO: Add a check here to only invoke _update if need be.
        this._update();

        var matrix = this._matrix.elements;
        var parent = this.parent;
        this._renderer.opacity = this._opacity
          * (parent && parent._renderer ? parent._renderer.opacity : 1);

        var mask = this._mask;
        // var clip = this._clip;

        if (!this._renderer.context) {
          this._renderer.context = {};
        }

        this._renderer.context.ctx = ctx;
        // this._renderer.context.clip = clip;

        ctx.save();

        ctx.transform(
          matrix[0], matrix[3], matrix[1], matrix[4], matrix[2], matrix[5]);

        if (mask) {
          canvas[mask._renderer.type].render.call(mask, ctx, true);
        }

        this.children.forEach(canvas.group.renderChild, this._renderer.context);

        ctx.restore();

       /**
         * Commented two-way functionality of clips / masks with groups and
         * polygons. Uncomment when this bug is fixed:
         * https://code.google.com/p/chromium/issues/detail?id=370951
         */

        // if (clip) {
        //   ctx.clip();
        // }

        return this.flagReset();

      }

    },

    polygon: {

      render: function(ctx, forced, parentClipped) {

        var matrix, stroke, linewidth, fill, opacity, visible, cap, join, miter,
            closed, commands, length, last, next, prev, a, c, d, ux, uy, vx, vy,
            ar, bl, br, cl, x, y, mask, clip;

        // TODO: Add a check here to only invoke _update if need be.
        this._update();

        matrix = this._matrix.elements;
        stroke = this._stroke;
        linewidth = this._linewidth;
        fill = this._fill;
        opacity = this._opacity * this.parent._renderer.opacity;
        visible = this._visible;
        cap = this._cap;
        join = this._join;
        miter = this._miter;
        closed = this._closed;
        commands = this._vertices; // Commands
        length = commands.length;
        last = length - 1;

        // mask = this._mask;
        clip = this._clip;

        if (!forced && (!visible || clip)) {
          return this;
        }

        // Transform

        ctx.save();

        if (matrix) {
          ctx.transform(
            matrix[0], matrix[3], matrix[1], matrix[4], matrix[2], matrix[5]);
        }

       /**
         * Commented two-way functionality of clips / masks with groups and
         * polygons. Uncomment when this bug is fixed:
         * https://code.google.com/p/chromium/issues/detail?id=370951
         */

        // if (mask) {
        //   canvas[mask._renderer.type].render.call(mask, ctx, true);
        // }

        // Styles

        if (fill) {
          ctx.fillStyle = fill;
        }
        if (stroke) {
          ctx.strokeStyle = stroke;
        }
        if (linewidth) {
          ctx.lineWidth = linewidth;
        }
        if (miter) {
          ctx.miterLimit = miter;
        }
        if (join) {
          ctx.lineJoin = join;
        }
        if (cap) {
          ctx.lineCap = cap;
        }
        if (_.isNumber(opacity)) {
          ctx.globalAlpha = opacity;
        }

        ctx.beginPath();
        commands.forEach(function(b, i) {

          x = toFixed(b.x);
          y = toFixed(b.y);

          switch (b._command) {

            case Two.Commands.close:
              ctx.closePath();
              break;

            case Two.Commands.curve:

              prev = closed ? mod(i - 1, length) : Math.max(i - 1, 0);
              next = closed ? mod(i + 1, length) : Math.min(i + 1, last);

              a = commands[prev];
              c = commands[next];
              ar = (a.controls && a.controls.right) || a;
              bl = (b.controls && b.controls.left) || b;

              if (a._relative) {
                vx = (ar.x + toFixed(a.x));
                vy = (ar.y + toFixed(a.y));
              } else {
                vx = toFixed(ar.x);
                vy = toFixed(ar.y);
              }

              if (b._relative) {
                ux = (bl.x + toFixed(b.x));
                uy = (bl.y + toFixed(b.y));
              } else {
                ux = toFixed(bl.x);
                uy = toFixed(bl.y);
              }

              ctx.bezierCurveTo(vx, vy, ux, uy, x, y);

              if (i >= last && closed) {

                c = d;

                br = (b.controls && b.controls.right) || b;
                cl = (c.controls && c.controls.left) || c;

                if (b._relative) {
                  vx = (br.x + toFixed(b.x));
                  vy = (br.y + toFixed(b.y));
                } else {
                  vx = toFixed(br.x);
                  vy = toFixed(br.y);
                }

                if (c._relative) {
                  ux = (cl.x + toFixed(c.x));
                  uy = (cl.y + toFixed(c.y));
                } else {
                  ux = toFixed(cl.x);
                  uy = toFixed(cl.y);
                }

                x = toFixed(c.x);
                y = toFixed(c.y);

                ctx.bezierCurveTo(vx, vy, ux, uy, x, y);

              }

              break;

            case Two.Commands.line:
              ctx.lineTo(x, y);
              break;

            case Two.Commands.move:
              d = b;
              ctx.moveTo(x, y);
              break;

          }

        });

        // Loose ends

        if (closed) {
          ctx.closePath();
        }

        if (!clip && !parentClipped) {
          ctx.fill();
          ctx.stroke();
        }

        ctx.restore();

        if (clip && !parentClipped) {
          ctx.clip();
        }

        return this.flagReset();

      }

    }

  };

  var Renderer = Two[Two.Types.canvas] = function(params) {

    this.domElement = params.domElement || document.createElement('canvas');
    this.ctx = this.domElement.getContext('2d');
    this.overdraw = params.overdraw || false;

    // Everything drawn on the canvas needs to be added to the scene.
    this.scene = new Two.Group();
    this.scene.parent = this;

  };

  _.extend(Renderer, {

    Utils: canvas

  });

  _.extend(Renderer.prototype, Backbone.Events, {

    setSize: function(width, height, ratio) {

      this.width = width;
      this.height = height;

      this.ratio = _.isUndefined(ratio) ? getRatio(this.ctx) : ratio;

      this.domElement.width = width * this.ratio;
      this.domElement.height = height * this.ratio;

      _.extend(this.domElement.style, {
        width: width + 'px',
        height: height + 'px'
      });

      return this;

    },

    render: function() {

      var isOne = this.ratio === 1;

      if (!isOne) {
        this.ctx.save();
        this.ctx.scale(this.ratio, this.ratio);
      }

      if (!this.overdraw) {
        this.ctx.clearRect(0, 0, this.width, this.height);
      }

      canvas.group.render.call(this.scene, this.ctx);

      if (!isOne) {
        this.ctx.restore();
      }

      return this;

    }

  });

  function resetTransform(ctx) {
    ctx.setTransform(1, 0, 0, 1, 0, 0);
  }

})(Two);
<|endoftext|>


<commit_before>import Component from './component';
import Trie from 'route-trie';
import VText from 'virtual-dom/vnode/vtext';

export default class RouterComponent extends Component {

  constructor(application, parent, name, routes = {}) {
    let trie = new Trie();
    let compiledRoutes = {};
    for (let pattern of Object.keys(routes)) {
      compiledRoutes[pattern] = {
        node: trie.define(pattern),
        initializer: routes[pattern]
      };
    }

    let initialState = {
      __trie: trie,
      __compiledRoutes: compiledRoutes
    };
    super(application, parent, name, initialState);

    this.onPopStateHandlerBinded = this.onPopStateHandler.bind(this);
  }

  activate() {
    super.activate();

    this.onPopStateHandler();
    window.addEventListener('popstate', this.onPopStateHandlerBinded);
  }

  deactivate() {
    window.removeEventListener('popstate', this.onPopStateHandlerBinded);

    super.deactivate();
  }

  get currentComponentName() {
    return this.state.currentComponentName;
  }

  get currentComponent() {
    return this.currentComponentName === undefined
      ? undefined
      : this.currentComponentName === null
        ? null
        : this.state[this.currentComponentName];
  }

  get __currentMatch() {
    let hash = this.application.rootNode.ownerDocument.location.hash;
    let path = hash.slice(1);
    return this.state.__trie.match(path);
  }

  onPopStateHandler() {
    if (this.currentComponentName !== undefined && this.currentComponentName !== null) {
      this.currentComponent.deactivate();
      this.state.set(this.currentComponentName, null);
    }
    this.state.set('currentComponentName', null);

    if (this.__currentMatch !== null) {
      let currentPattern = currentMatch.node._nodeState.pattern;
      let currentRoute = this.state.__compiledRoutes[currentPattern];

      let currentComponent = currentRoute.initializer(currentMatch, this);

      this.state.set({
        currentComponentName: currentComponent.name,
        [currentComponent.name]: currentComponent
      });

      this.currentComponent.activate();
    }
  };

  render() {
    if (this.currentComponentName === undefined || this.currentComponentName === null) {
      return new VText('Invalid route!');
    }

    return this.currentComponent.render();
  }

}
<commit_msg>routerComponent: Extract .renderInvalidRoute method<commit_after>import Component from './component';
import Trie from 'route-trie';
import VText from 'virtual-dom/vnode/vtext';

export default class RouterComponent extends Component {

  constructor(application, parent, name, routes = {}) {
    let trie = new Trie();
    let compiledRoutes = {};
    for (let pattern of Object.keys(routes)) {
      compiledRoutes[pattern] = {
        node: trie.define(pattern),
        initializer: routes[pattern]
      };
    }

    let initialState = {
      __trie: trie,
      __compiledRoutes: compiledRoutes
    };
    super(application, parent, name, initialState);

    this.onPopStateHandlerBinded = this.onPopStateHandler.bind(this);
  }

  activate() {
    super.activate();

    this.onPopStateHandler();
    window.addEventListener('popstate', this.onPopStateHandlerBinded);
  }

  deactivate() {
    window.removeEventListener('popstate', this.onPopStateHandlerBinded);

    super.deactivate();
  }

  get currentComponentName() {
    return this.state.currentComponentName;
  }

  get currentComponent() {
    return this.currentComponentName === undefined
      ? undefined
      : this.currentComponentName === null
        ? null
        : this.state[this.currentComponentName];
  }

  get __currentMatch() {
    let hash = this.application.rootNode.ownerDocument.location.hash;
    let path = hash.slice(1);
    return this.state.__trie.match(path);
  }

  onPopStateHandler() {
    if (this.currentComponentName !== undefined && this.currentComponentName !== null) {
      this.currentComponent.deactivate();
      this.state.set(this.currentComponentName, null);
    }
    this.state.set('currentComponentName', null);

    if (this.__currentMatch !== null) {
      let currentPattern = currentMatch.node._nodeState.pattern;
      let currentRoute = this.state.__compiledRoutes[currentPattern];

      let currentComponent = currentRoute.initializer(currentMatch, this);

      this.state.set({
        currentComponentName: currentComponent.name,
        [currentComponent.name]: currentComponent
      });

      this.currentComponent.activate();
    }
  };

  renderInvalidRoute() {
    return new VText('Invalid route!');
  }

  render() {
    return this.currentComponentName !== undefined && this.currentComponentName !== null
      ? this.currentComponent.render()
      : this.renderInvalidRoute();
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

// My HTTP Request

frappe.provide('frappe.request');
frappe.request.url = '/';
frappe.request.ajax_count = 0;
frappe.request.waiting_for_ajax = [];

// generic server call (call page, object)
frappe.call = function(opts) {
	if(opts.quiet) {
		opts.no_spinner = true;
	}
	var args = $.extend({}, opts.args);

	// cmd
	if(opts.module && opts.page) {
		args.cmd = opts.module+'.page.'+opts.page+'.'+opts.page+'.'+opts.method;
	} else if(opts.doc) {
		$.extend(args, {
			cmd: "runserverobj",
			docs: frappe.get_doc(opts.doc.doctype, opts.doc.name),
			method: opts.method,
			args: opts.args,
		});
	} else if(opts.method) {
		args.cmd = opts.method;
	}

	var callback = function(data, response_text) {
		if(data.task_id) {
			// async call, subscribe
			frappe.socket.subscribe(data.task_id, opts);

			if(opts.queued) {
				opts.queued(data);
			}
		}
		else if (opts.callback) {
			// ajax
			return opts.callback(data, response_text);
		}
	}

	return frappe.request.call({
		type: opts.type || "POST",
		args: args,
		success: callback,
		error: opts.error,
		always: opts.always,
		btn: opts.btn,
		freeze: opts.freeze,
		freeze_message: opts.freeze_message,
		// show_spinner: !opts.no_spinner,
		async: opts.async,
		url: opts.url || frappe.request.url,
	});
}

frappe.request.call = function(opts) {
	frappe.request.prepare(opts);

	var statusCode = {
		200: function(data, xhr) {
			opts.success_callback && opts.success_callback(data, xhr.responseText);
		},
		401: function(xhr) {
			if(frappe.app.session_expired_dialog && frappe.app.session_expired_dialog.display) {
				frappe.app.redirect_to_login();
			} else {
				frappe.app.handle_session_expired();
			}
		},
		404: function(xhr) {
			frappe.msgprint({title:__("Not found"), indicator:'red',
				message: __('The resource you are looking for is not available')});
		},
		403: function(xhr) {
			if (frappe.get_cookie('sid')==='Guest') {
				// session expired
				frappe.app.handle_session_expired();
			}
			else if(xhr.responseJSON && xhr.responseJSON._error_message) {
				frappe.msgprint({
					title:__("Not permitted"), indicator:'red',
					message: xhr.responseJSON._error_message
				});

				xhr.responseJSON._server_messages = null;
			}
			else if (xhr.responseJSON && xhr.responseJSON._server_messages) {
				var _server_messages = JSON.parse(xhr.responseJSON._server_messages);

				// avoid double messages
				if (_server_messages.indexOf(__("Not permitted"))!==-1) {
					return;
				}
			}
			else {
				frappe.msgprint({
					title:__("Not permitted"), indicator:'red',
					message: __('You do not have enough permissions to access this resource. Please contact your manager to get access.')});
			}

		},
		508: function(xhr) {
			frappe.utils.play_sound("error");
			frappe.msgprint({title:__('Please try again'), indicator:'red',
				message:__("Another transaction is blocking this one. Please try again in a few seconds.")});
		},
		413: function(data, xhr) {
			frappe.msgprint({indicator:'red', title:__('File too big'), message:__("File size exceeded the maximum allowed size of {0} MB",
				[(frappe.boot.max_file_size || 5242880) / 1048576])});
		},
		417: function(xhr) {
			var r = xhr.responseJSON;
			if (!r) {
				try {
					r = JSON.parse(xhr.responseText);
				} catch (e) {
					r = xhr.responseText;
				}
			}

			opts.error_callback && opts.error_callback(r);
		},
		501: function(data, xhr) {
			if(typeof data === "string") data = JSON.parse(data);
			opts.error_callback && opts.error_callback(data, xhr.responseText);
		},
		500: function(xhr) {
			frappe.utils.play_sound("error");
			frappe.msgprint({message:__("Server Error: Please check your server logs or contact tech support."), title:__('Something went wrong'), indicator: 'red'});
			opts.error_callback && opts.error_callback();
			frappe.request.report_error(xhr, opts);
		},
		504: function(xhr) {
			frappe.msgprint(__("Request Timed Out"))
			opts.error_callback && opts.error_callback();
		}
	};

	var ajax_args = {
		url: opts.url || frappe.request.url,
		data: opts.args,
		type: opts.type,
		dataType: opts.dataType || 'json',
		async: opts.async,
		headers: { "X-Frappe-CSRF-Token": frappe.csrf_token },
		cache: false
	};

	frappe.last_request = ajax_args.data;

	return $.ajax(ajax_args)
		.done(function(data, textStatus, xhr) {
			if(typeof data === "string") data = JSON.parse(data);

			// sync attached docs
			if(data.docs || data.docinfo) {
				frappe.model.sync(data);
			}

			// sync translated messages
			if(data.__messages) {
				$.extend(frappe._messages, data.__messages);
			}

			// callbacks
			var status_code_handler = statusCode[xhr.statusCode().status];
			if (status_code_handler) {
				status_code_handler(data, xhr);
			}
		})
		.always(function(data, textStatus, xhr) {
			try {
				if(typeof data==="string") {
					data = JSON.parse(data);
				}
				if(data.responseText) {
					var xhr = data;
					data = JSON.parse(data.responseText);
				}
			} catch(e) {
				data = null;
				// pass
			}
			frappe.request.cleanup(opts, data);
			if(opts.always) {
				opts.always(data);
			}
		})
		.fail(function(xhr, textStatus) {
			var status_code_handler = statusCode[xhr.statusCode().status];
			if (status_code_handler) {
				status_code_handler(xhr);
			} else {
				// if not handled by error handler!
				opts.error_callback && opts.error_callback(xhr);
			}
		});
}

// call execute serverside request
frappe.request.prepare = function(opts) {
	frappe.request.ajax_count++;

	$("body").attr("data-ajax-state", "triggered");

	// btn indicator
	if(opts.btn) $(opts.btn).prop("disabled", true);

	// freeze page
	if(opts.freeze) frappe.dom.freeze(opts.freeze_message);

	// stringify args if required
	for(var key in opts.args) {
		if(opts.args[key] && ($.isPlainObject(opts.args[key]) || $.isArray(opts.args[key]))) {
			opts.args[key] = JSON.stringify(opts.args[key]);
		}
	}

	// no cmd?
	if(!opts.args.cmd && !opts.url) {
		console.log(opts)
		throw "Incomplete Request";
	}

	opts.success_callback = opts.success;
	opts.error_callback = opts.error;
	delete opts.success;
	delete opts.error;

}

frappe.request.cleanup = function(opts, r) {
	// stop button indicator
	if(opts.btn) {
		$(opts.btn).prop("disabled", false);
	}

	$("body").attr("data-ajax-state", "complete");

	// un-freeze page
	if(opts.freeze) frappe.dom.unfreeze();

	if(!r) {
		return;
	}

	// session expired? - Guest has no business here!
	if(r.session_expired || frappe.get_cookie("sid")==="Guest") {
		frappe.app.handle_session_expired();
		return;
	}

	// show messages
	if(r._server_messages && !opts.silent) {
		r._server_messages = JSON.parse(r._server_messages);
		frappe.hide_msgprint();
		frappe.msgprint(r._server_messages);
	}

	// show errors
	if(r.exc) {
		r.exc = JSON.parse(r.exc);
		if(r.exc instanceof Array) {
			$.each(r.exc, function(i, v) {
				if(v) {
					console.log(v);
				}
			})
		} else {
			console.log(r.exc);
		}
	}

	// debug messages
	if(r._debug_messages) {
		if(opts.args) {
			console.log("======== arguments ========");
			console.log(opts.args);
			console.log("========")
		}
		$.each(JSON.parse(r._debug_messages), function(i, v) { console.log(v); });
		console.log("======== response ========");
		delete r._debug_messages;
		console.log(r);
		console.log("========");
	}

	frappe.last_response = r;

	frappe.request.ajax_count--;
	if(!frappe.request.ajax_count) {
		$.each(frappe.request.waiting_for_ajax || [], function(i, fn) {
			fn();
		});
		frappe.request.waiting_for_ajax = [];
	}
}

frappe.after_server_call = () => {
	if(frappe.request.ajax_count) {
		return new Promise(resolve => {
			frappe.request.waiting_for_ajax.push(() => {
				resolve();
			});
		});
	} else {
		return null;
	}
};

frappe.after_ajax = function(fn) {
	return new Promise(resolve => {
		if(frappe.request.ajax_count) {
			frappe.request.waiting_for_ajax.push(() => {
				if(fn) fn();
				resolve();
			});
		} else {
			if(fn) fn();
			resolve();
		}
	});
};

frappe.request.report_error = function(xhr, request_opts) {
	var data = JSON.parse(xhr.responseText);
	if (data.exc) {
		var exc = (JSON.parse(data.exc) || []).join("\n");
		delete data.exc;
	} else {
		var exc = "";
	}

	if (exc) {
		var error_report_email = (frappe.boot.error_report_email || []).join(", ");
		var error_message = '
\

'
				+ exc.replace(/</g, '<').replace(/>/g, '>') + '
'
			+'
'
			+ __("Report this issue") + '
'
			+'
';

		request_opts = frappe.request.cleanup_request_opts(request_opts);

		msg_dialog = frappe.msgprint({message:error_message, indicator:'red'});

		msg_dialog.msg_area.find(".report-btn")
			.toggle(error_report_email ? true : false)
			.on("click", function() {
				var error_report_message = [
					'
Please type some additional information that could help us reproduce this issue:
',
					'

',
					'
',
					'
App Versions
',
					'
' + JSON.stringify(frappe.boot.versions, null, "\t") + '
',
					'
Route
',
					'
' + frappe.get_route_str() + '
',
					'
',
					'
Error Report
',
					'
' + exc + '
',
					'
',
					'
Request Data
',
					'
' + JSON.stringify(request_opts, null, "\t") + '
',
					'
',
					'
Response JSON
',
					'
' + JSON.stringify(data, null, '\t')+ '
'
				].join("\n");

				var communication_composer = new frappe.views.CommunicationComposer({
					subject: 'Error Report [' + frappe.datetime.nowdate() + ']',
					recipients: error_report_email,
					message: error_report_message,
					doc: {
						doctype: "User",
						name: frappe.session.user
					}
				});
				communication_composer.dialog.$wrapper.css("z-index", cint(msg_dialog.$wrapper.css("z-index")) + 1);
			});
	}
};

frappe.request.cleanup_request_opts = function(request_opts) {
	var doc = (request_opts.args || {}).doc;
	if (doc) {
		doc = JSON.parse(doc);
		$.each(Object.keys(doc), function(i, key) {
			if (key.indexOf("password")!==-1 && doc[key]) {
				// mask the password
				doc[key] = "*****";
			}
		});
		request_opts.args.doc = JSON.stringify(doc);
	}
	return request_opts;
};
<commit_msg>Fixed ajax count after server request failed (#3746)<commit_after>// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

// My HTTP Request

frappe.provide('frappe.request');
frappe.request.url = '/';
frappe.request.ajax_count = 0;
frappe.request.waiting_for_ajax = [];

// generic server call (call page, object)
frappe.call = function(opts) {
	if(opts.quiet) {
		opts.no_spinner = true;
	}
	var args = $.extend({}, opts.args);

	// cmd
	if(opts.module && opts.page) {
		args.cmd = opts.module+'.page.'+opts.page+'.'+opts.page+'.'+opts.method;
	} else if(opts.doc) {
		$.extend(args, {
			cmd: "runserverobj",
			docs: frappe.get_doc(opts.doc.doctype, opts.doc.name),
			method: opts.method,
			args: opts.args,
		});
	} else if(opts.method) {
		args.cmd = opts.method;
	}

	var callback = function(data, response_text) {
		if(data.task_id) {
			// async call, subscribe
			frappe.socket.subscribe(data.task_id, opts);

			if(opts.queued) {
				opts.queued(data);
			}
		}
		else if (opts.callback) {
			// ajax
			return opts.callback(data, response_text);
		}
	}

	return frappe.request.call({
		type: opts.type || "POST",
		args: args,
		success: callback,
		error: opts.error,
		always: opts.always,
		btn: opts.btn,
		freeze: opts.freeze,
		freeze_message: opts.freeze_message,
		// show_spinner: !opts.no_spinner,
		async: opts.async,
		url: opts.url || frappe.request.url,
	});
}

frappe.request.call = function(opts) {
	frappe.request.prepare(opts);

	var statusCode = {
		200: function(data, xhr) {
			opts.success_callback && opts.success_callback(data, xhr.responseText);
		},
		401: function(xhr) {
			if(frappe.app.session_expired_dialog && frappe.app.session_expired_dialog.display) {
				frappe.app.redirect_to_login();
			} else {
				frappe.app.handle_session_expired();
			}
		},
		404: function(xhr) {
			frappe.msgprint({title:__("Not found"), indicator:'red',
				message: __('The resource you are looking for is not available')});
		},
		403: function(xhr) {
			if (frappe.get_cookie('sid')==='Guest') {
				// session expired
				frappe.app.handle_session_expired();
			}
			else if(xhr.responseJSON && xhr.responseJSON._error_message) {
				frappe.msgprint({
					title:__("Not permitted"), indicator:'red',
					message: xhr.responseJSON._error_message
				});

				xhr.responseJSON._server_messages = null;
			}
			else if (xhr.responseJSON && xhr.responseJSON._server_messages) {
				var _server_messages = JSON.parse(xhr.responseJSON._server_messages);

				// avoid double messages
				if (_server_messages.indexOf(__("Not permitted"))!==-1) {
					return;
				}
			}
			else {
				frappe.msgprint({
					title:__("Not permitted"), indicator:'red',
					message: __('You do not have enough permissions to access this resource. Please contact your manager to get access.')});
			}

		},
		508: function(xhr) {
			frappe.utils.play_sound("error");
			frappe.msgprint({title:__('Please try again'), indicator:'red',
				message:__("Another transaction is blocking this one. Please try again in a few seconds.")});
		},
		413: function(data, xhr) {
			frappe.msgprint({indicator:'red', title:__('File too big'), message:__("File size exceeded the maximum allowed size of {0} MB",
				[(frappe.boot.max_file_size || 5242880) / 1048576])});
		},
		417: function(xhr) {
			var r = xhr.responseJSON;
			if (!r) {
				try {
					r = JSON.parse(xhr.responseText);
				} catch (e) {
					r = xhr.responseText;
				}
			}

			opts.error_callback && opts.error_callback(r);
		},
		501: function(data, xhr) {
			if(typeof data === "string") data = JSON.parse(data);
			opts.error_callback && opts.error_callback(data, xhr.responseText);
		},
		500: function(xhr) {
			frappe.utils.play_sound("error");
			frappe.msgprint({message:__("Server Error: Please check your server logs or contact tech support."), title:__('Something went wrong'), indicator: 'red'});
			opts.error_callback && opts.error_callback();
			frappe.request.report_error(xhr, opts);
		},
		504: function(xhr) {
			frappe.msgprint(__("Request Timed Out"))
			opts.error_callback && opts.error_callback();
		}
	};

	var ajax_args = {
		url: opts.url || frappe.request.url,
		data: opts.args,
		type: opts.type,
		dataType: opts.dataType || 'json',
		async: opts.async,
		headers: { "X-Frappe-CSRF-Token": frappe.csrf_token },
		cache: false
	};

	frappe.last_request = ajax_args.data;

	return $.ajax(ajax_args)
		.done(function(data, textStatus, xhr) {
			try {
				if(typeof data === "string") data = JSON.parse(data);

				// sync attached docs
				if(data.docs || data.docinfo) {
					frappe.model.sync(data);
				}

				// sync translated messages
				if(data.__messages) {
					$.extend(frappe._messages, data.__messages);
				}

				// callbacks
				var status_code_handler = statusCode[xhr.statusCode().status];
				if (status_code_handler) {
					status_code_handler(data, xhr);
				}
			} catch(e) {
				console.log("Unable to handle response");
				console.trace(e);
			}

		})
		.always(function(data, textStatus, xhr) {
			try {
				if(typeof data==="string") {
					data = JSON.parse(data);
				}
				if(data.responseText) {
					var xhr = data;
					data = JSON.parse(data.responseText);
				}
			} catch(e) {
				data = null;
				// pass
			}
			frappe.request.cleanup(opts, data);
			if(opts.always) {
				opts.always(data);
			}
		})
		.fail(function(xhr, textStatus) {
			var status_code_handler = statusCode[xhr.statusCode().status];
			if (status_code_handler) {
				status_code_handler(xhr);
			} else {
				// if not handled by error handler!
				opts.error_callback && opts.error_callback(xhr);
			}
		});
}

// call execute serverside request
frappe.request.prepare = function(opts) {
	frappe.request.ajax_count++;

	$("body").attr("data-ajax-state", "triggered");

	// btn indicator
	if(opts.btn) $(opts.btn).prop("disabled", true);

	// freeze page
	if(opts.freeze) frappe.dom.freeze(opts.freeze_message);

	// stringify args if required
	for(var key in opts.args) {
		if(opts.args[key] && ($.isPlainObject(opts.args[key]) || $.isArray(opts.args[key]))) {
			opts.args[key] = JSON.stringify(opts.args[key]);
		}
	}

	// no cmd?
	if(!opts.args.cmd && !opts.url) {
		console.log(opts)
		throw "Incomplete Request";
	}

	opts.success_callback = opts.success;
	opts.error_callback = opts.error;
	delete opts.success;
	delete opts.error;

}

frappe.request.cleanup = function(opts, r) {
	// stop button indicator
	if(opts.btn) {
		$(opts.btn).prop("disabled", false);
	}

	$("body").attr("data-ajax-state", "complete");

	// un-freeze page
	if(opts.freeze) frappe.dom.unfreeze();

	if(r) {

		// session expired? - Guest has no business here!
		if(r.session_expired || frappe.get_cookie("sid")==="Guest") {
			frappe.app.handle_session_expired();
			return;
		}

		// show messages
		if(r._server_messages && !opts.silent) {
			r._server_messages = JSON.parse(r._server_messages);
			frappe.hide_msgprint();
			frappe.msgprint(r._server_messages);
		}

		// show errors
		if(r.exc) {
			r.exc = JSON.parse(r.exc);
			if(r.exc instanceof Array) {
				$.each(r.exc, function(i, v) {
					if(v) {
						console.log(v);
					}
				})
			} else {
				console.log(r.exc);
			}
		}

		// debug messages
		if(r._debug_messages) {
			if(opts.args) {
				console.log("======== arguments ========");
				console.log(opts.args);
				console.log("========")
			}
			$.each(JSON.parse(r._debug_messages), function(i, v) { console.log(v); });
			console.log("======== response ========");
			delete r._debug_messages;
			console.log(r);
			console.log("========");
		}
	}

	frappe.last_response = r;

	frappe.request.ajax_count--;
	if(!frappe.request.ajax_count) {
		$.each(frappe.request.waiting_for_ajax || [], function(i, fn) {
			fn();
		});
		frappe.request.waiting_for_ajax = [];
	}
}

frappe.after_server_call = () => {
	if(frappe.request.ajax_count) {
		return new Promise(resolve => {
			frappe.request.waiting_for_ajax.push(() => {
				resolve();
			});
		});
	} else {
		return null;
	}
};

frappe.after_ajax = function(fn) {
	return new Promise(resolve => {
		if(frappe.request.ajax_count) {
			frappe.request.waiting_for_ajax.push(() => {
				if(fn) fn();
				resolve();
			});
		} else {
			if(fn) fn();
			resolve();
		}
	});
};

frappe.request.report_error = function(xhr, request_opts) {
	var data = JSON.parse(xhr.responseText);
	if (data.exc) {
		var exc = (JSON.parse(data.exc) || []).join("\n");
		delete data.exc;
	} else {
		var exc = "";
	}

	if (exc) {
		var error_report_email = (frappe.boot.error_report_email || []).join(", ");
		var error_message = '
\

'
				+ exc.replace(/</g, '<').replace(/>/g, '>') + '
'
			+'
'
			+ __("Report this issue") + '
'
			+'
';

		request_opts = frappe.request.cleanup_request_opts(request_opts);

		msg_dialog = frappe.msgprint({message:error_message, indicator:'red'});

		msg_dialog.msg_area.find(".report-btn")
			.toggle(error_report_email ? true : false)
			.on("click", function() {
				var error_report_message = [
					'
Please type some additional information that could help us reproduce this issue:
',
					'

',
					'
',
					'
App Versions
',
					'
' + JSON.stringify(frappe.boot.versions, null, "\t") + '
',
					'
Route
',
					'
' + frappe.get_route_str() + '
',
					'
',
					'
Error Report
',
					'
' + exc + '
',
					'
',
					'
Request Data
',
					'
' + JSON.stringify(request_opts, null, "\t") + '
',
					'
',
					'
Response JSON
',
					'
' + JSON.stringify(data, null, '\t')+ '
'
				].join("\n");

				var communication_composer = new frappe.views.CommunicationComposer({
					subject: 'Error Report [' + frappe.datetime.nowdate() + ']',
					recipients: error_report_email,
					message: error_report_message,
					doc: {
						doctype: "User",
						name: frappe.session.user
					}
				});
				communication_composer.dialog.$wrapper.css("z-index", cint(msg_dialog.$wrapper.css("z-index")) + 1);
			});
	}
};

frappe.request.cleanup_request_opts = function(request_opts) {
	var doc = (request_opts.args || {}).doc;
	if (doc) {
		doc = JSON.parse(doc);
		$.each(Object.keys(doc), function(i, key) {
			if (key.indexOf("password")!==-1 && doc[key]) {
				// mask the password
				doc[key] = "*****";
			}
		});
		request_opts.args.doc = JSON.stringify(doc);
	}
	return request_opts;
};
<|endoftext|>