<commit_before>const keystone = require('keystone');
const {normalizeProduct} = require('./helper/product');

function onInitView(view, next) {
    const {res, req} = view;
    const {locals} = res;

    keystone
        .list('Product')
        .paginate({
            page: req.query.page || 1,
            perPage: 30
        })
        .find()
        // .find({available: true})
        .sort({createdAt: -1})
        // .select('slug name description price externalImages image0 promotable')
        .exec((err, result) => {
            if (err) {
                res.status(500);
                res.render('errors/500');
                return;
            }

            const {results} = result;

            if (results.length === 0) {
                res.status(404);
                res.render('errors/404');
                return;
            }

            Object.assign(locals, {
                indexPagination: {
                    totalPages: result.totalPages,
                    startPage: result.currentPage
                },
                products: results.map(normalizeProduct)
            });

            next(err);
        });
}

exports = module.exports = (req, res) => {
    const view = new keystone.View(req, res);

    view.on('init', next => onInitView(view, next));

    view.render('index');
};
<commit_msg>add todo for cache<commit_after>const keystone = require('keystone');
const {normalizeProduct} = require('./helper/product');

function onInitView(view, next) {
    const {res, req} = view;
    const {locals} = res;

    keystone
        .list('Product')
        .paginate({
            page: req.query.page || 1,
            perPage: 30
        })
        .find()
        // .find({available: true})
        .sort({createdAt: -1})
        // .select('slug name description price externalImages image0 promotable')
        .exec((err, result) => {
            if (err) {
                res.status(500);
                res.render('errors/500');
                return;
            }

            const {results} = result;

            if (results.length === 0) {
                res.status(404);
                res.render('errors/404');
                return;
            }

            Object.assign(locals, {
                indexPagination: {
                    totalPages: result.totalPages,
                    startPage: result.currentPage
                },
                products: results.map(normalizeProduct)
            });

            next(err);
            // TODO: cache result
            // next(locals);
        });
}

exports = module.exports = (req, res) => {
    const view = new keystone.View(req, res);

    view.on('init', next => onInitView(view, next));

    view.render('index');

    // TODO: cache result
    // use variable keystone.set({lastUpdate: Date.now()})
    // update for every product, category, variant
    // if page last update little then lastUpdate => update page
    // onInitView(view, locals => {
    //     view.render('index', locals, (err, html) => res.end(html))
    // });
};
<|endoftext|>


<commit_before>import debugModule from "debug";
const debug = debugModule("debugger:test:data:calldata");

import {assert} from "chai";

import Ganache from "ganache-core";

import {prepareContracts, lineOf} from "../helpers";
import Debugger from "lib/debugger";

import * as Codec from "@truffle/codec";

import solidity from "lib/solidity/selectors";

const __CALLDATA = `
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;

contract CalldataTest {

  event Done();

  struct Pair {
    uint x;
    uint y;
  }

  struct StringBox {
    string it;
  }

  function simpleTest(string calldata hello) external {
    emit Done(); //break simple
  }

  function staticTest(string calldata hello) external pure returns (string memory) {
    return hello; //break static
  }

  function staticTester() public {
    this.staticTest("hello world");
  }

  function delegateTester() public {
    CalldataLibrary.delegateTest("hello world");
  }

  function multiTest(
    string calldata hello,
    uint[] calldata someInts,
    Pair calldata pair)
  external {
    emit Done(); //break multi
  }

  function multiTester() public {
    uint[2] memory twoInts;
    uint[] memory someInts;
    someInts = new uint[](2);
    someInts[0] = 41;
    someInts[1] = 42;
    Pair memory pair;
    pair.x = 321;
    pair.y = 2049;
    this.multiTest("hello", someInts, pair);
  }

  function stringBoxTest(StringBox calldata stringBox) external returns (string memory) {
    return stringBox.it; //break stringBox
  }

  function sliceTest(uint[] calldata nums) external returns (uint[] memory) {
    uint[] calldata sliced = nums[1 : nums.length - 1];
    emit Done(); //break slice
  }

  fallback(bytes calldata input) external returns (bytes memory output) {
    output = input;
    emit Done(); //break fallback
  }

}

library CalldataLibrary {

  event Done();

  function delegateTest(string calldata hello) external {
    emit Done(); //break delegate
  }
}
`;

const __MIGRATION = `
var CalldataTest = artifacts.require("CalldataTest");
var CalldataLibrary = artifacts.require("CalldataLibrary");

module.exports = function(deployer) {
  deployer.deploy(CalldataLibrary);
  deployer.link(CalldataLibrary, CalldataTest);
  deployer.deploy(CalldataTest);
};
`;

let sources = {
  "CalldataTest.sol": __CALLDATA
};

let migrations = {
  "2_deploy_contracts.js": __MIGRATION
};

describe("Calldata Decoding", function () {
  var provider;

  var abstractions;
  var compilations;

  before("Create Provider", async function () {
    provider = Ganache.provider({seed: "debugger", gasLimit: 7000000});
  });

  before("Prepare contracts and artifacts", async function () {
    this.timeout(30000);

    let prepared = await prepareContracts(provider, sources, migrations);
    abstractions = prepared.abstractions;
    compilations = prepared.compilations;
  });

  it("Decodes various types correctly", async function () {
    this.timeout(9000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.multiTester();
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {provider, compilations});

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break multi", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      hello: "hello",
      someInts: [41, 42],
      pair: {x: 321, y: 2049}
    };

    assert.deepInclude(variables, expectedResult);
  });

  it("Decodes correctly in the initial call", async function () {
    this.timeout(6000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.simpleTest("hello world");
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {provider, compilations});

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break simple", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      hello: "hello world"
    };

    assert.include(variables, expectedResult);
  });

  it("Decodes dynamic structs correctly", async function () {
    this.timeout(6000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.stringBoxTest({it: "hello world"});
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {provider, compilations});

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break stringBox", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      stringBox: {
        it: "hello world"
      }
    };

    assert.deepInclude(variables, expectedResult);
  });

  it("Decodes correctly in a pure call", async function () {
    this.timeout(6000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.staticTester();
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {
      provider,
      compilations
    });

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break static", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      hello: "hello world"
    };

    assert.include(variables, expectedResult);
  });

  it("Decodes correctly in a library call", async function () {
    this.timeout(6000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.delegateTester();
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {
      provider,
      compilations
    });

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break delegate", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      hello: "hello world"
    };

    assert.include(variables, expectedResult);
  });

  it("Decodes array slices correctly", async function () {
    this.timeout(6000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.sliceTest([20, 21, 22, 23, 24]);
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {
      provider,
      compilations
    });

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break slice", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      sliced: [21, 22, 23]
    };

    assert.deepInclude(variables, expectedResult);
  });

  it("Decodes fallback function input and output", async function () {
    this.timeout(6000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.sendTransaction({ data: "0xdeadbeef" });
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {
      provider,
      compilations
    });

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break fallback", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      input: "0xdeadbeef",
      output: "0xdeadbeef"
    };

    assert.deepInclude(variables, expectedResult);
  });
});
<commit_msg>Add test of fallback function input and output<commit_after>import debugModule from "debug";
const debug = debugModule("debugger:test:data:calldata");

import {assert} from "chai";

import Ganache from "ganache-core";

import {prepareContracts, lineOf} from "../helpers";
import Debugger from "lib/debugger";

import * as Codec from "@truffle/codec";

import solidity from "lib/solidity/selectors";

const __CALLDATA = `
pragma solidity ^0.7.6;
pragma experimental ABIEncoderV2;

contract CalldataTest {

  event Done();

  struct Pair {
    uint x;
    uint y;
  }

  struct StringBox {
    string it;
  }

  function simpleTest(string calldata hello) external {
    emit Done(); //break simple
  }

  function staticTest(string calldata hello) external pure returns (string memory) {
    return hello; //break static
  }

  function staticTester() public {
    this.staticTest("hello world");
  }

  function delegateTester() public {
    CalldataLibrary.delegateTest("hello world");
  }

  function multiTest(
    string calldata hello,
    uint[] calldata someInts,
    Pair calldata pair)
  external {
    emit Done(); //break multi
  }

  function multiTester() public {
    uint[2] memory twoInts;
    uint[] memory someInts;
    someInts = new uint[](2);
    someInts[0] = 41;
    someInts[1] = 42;
    Pair memory pair;
    pair.x = 321;
    pair.y = 2049;
    this.multiTest("hello", someInts, pair);
  }

  function stringBoxTest(StringBox calldata stringBox) external returns (string memory) {
    return stringBox.it; //break stringBox
  }

  function sliceTest(uint[] calldata nums) external returns (uint[] memory) {
    uint[] calldata sliced = nums[1 : nums.length - 1];
    emit Done(); //break slice
  }

  fallback(bytes calldata input) external returns (bytes memory output) {
    output = input;
    emit Done(); //break fallback
  }

}

library CalldataLibrary {

  event Done();

  function delegateTest(string calldata hello) external {
    emit Done(); //break delegate
  }
}
`;

const __MIGRATION = `
var CalldataTest = artifacts.require("CalldataTest");
var CalldataLibrary = artifacts.require("CalldataLibrary");

module.exports = function(deployer) {
  deployer.deploy(CalldataLibrary);
  deployer.link(CalldataLibrary, CalldataTest);
  deployer.deploy(CalldataTest);
};
`;

let sources = {
  "CalldataTest.sol": __CALLDATA
};

let migrations = {
  "2_deploy_contracts.js": __MIGRATION
};

describe("Calldata Decoding", function () {
  var provider;

  var abstractions;
  var compilations;

  before("Create Provider", async function () {
    provider = Ganache.provider({seed: "debugger", gasLimit: 7000000});
  });

  before("Prepare contracts and artifacts", async function () {
    this.timeout(30000);

    let prepared = await prepareContracts(provider, sources, migrations);
    abstractions = prepared.abstractions;
    compilations = prepared.compilations;
  });

  it("Decodes various types correctly", async function () {
    this.timeout(9000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.multiTester();
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {provider, compilations});

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break multi", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      hello: "hello",
      someInts: [41, 42],
      pair: {x: 321, y: 2049}
    };

    assert.deepInclude(variables, expectedResult);
  });

  it("Decodes correctly in the initial call", async function () {
    this.timeout(6000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.simpleTest("hello world");
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {provider, compilations});

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break simple", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      hello: "hello world"
    };

    assert.include(variables, expectedResult);
  });

  it("Decodes dynamic structs correctly", async function () {
    this.timeout(6000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.stringBoxTest({it: "hello world"});
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {provider, compilations});

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break stringBox", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      stringBox: {
        it: "hello world"
      }
    };

    assert.deepInclude(variables, expectedResult);
  });

  it("Decodes correctly in a pure call", async function () {
    this.timeout(6000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.staticTester();
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {
      provider,
      compilations
    });

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break static", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      hello: "hello world"
    };

    assert.include(variables, expectedResult);
  });

  it("Decodes correctly in a library call", async function () {
    this.timeout(6000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.delegateTester();
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {
      provider,
      compilations
    });

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break delegate", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      hello: "hello world"
    };

    assert.include(variables, expectedResult);
  });

  it("Decodes array slices correctly", async function () {
    this.timeout(6000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.sliceTest([20, 21, 22, 23, 24]);
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {
      provider,
      compilations
    });

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break slice", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    const expectedResult = {
      sliced: [21, 22, 23]
    };

    assert.deepInclude(variables, expectedResult);
  });

  it("Decodes fallback function input and output", async function () {
    this.timeout(6000);
    let instance = await abstractions.CalldataTest.deployed();
    let receipt = await instance.sendTransaction({ data: "0xdeadbeef" });
    let txHash = receipt.tx;

    let bugger = await Debugger.forTx(txHash, {
      provider,
      compilations
    });

    let sourceId = bugger.view(solidity.current.source).id;
    let source = bugger.view(solidity.current.source).source;
    await bugger.addBreakpoint({
      sourceId,
      line: lineOf("break fallback", source)
    });

    await bugger.continueUntilBreakpoint();

    const variables = Codec.Format.Utils.Inspect.nativizeVariables(
      await bugger.variables()
    );

    debug("variables: %O", variables);

    const expectedResult = {
      input: "0xdeadbeef",
      output: "0xdeadbeef"
    };

    assert.deepInclude(variables, expectedResult);
  });
});
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

const colors = require('colors');
const Applesign = require('../');
const conf = require('minimist')(process.argv.slice(2), {
  boolean: ['replace', 'identities']
});

const options = {
  file: conf._[0] || 'undefined',
  outfile: conf.output || conf.o,
  entitlement: conf.entitlement || conf.e,
  bundleid: conf.bundleid || conf.b,
  identity: conf.identity || conf.i,
  mobileprovision: conf.mobileprovision || conf.m,
  replaceipa: conf.replace || conf.r,
  withoutWatchapp: !!conf['without-watchapp'] || !!conf.w,
  graphSortedBins: conf.d || conf.dependencies,
  keychain: conf.keychain || conf.k,
  verifyTwice: conf.verifyTwice || !!conf.v,
  unfairPlay: conf['without-fairplay'] || conf.f
};

colors.setTheme({
  error: 'red',
  warn: 'green',
  msg: 'yellow'
});

const cs = new Applesign(options);

if (conf.identities || conf.L) {
  cs.getIdentities((err, ids) => {
    if (err) {
      console.error(colors.error(err));
    } else {
      ids.forEach((id) => {
        console.log(id.hash, id.name);
      });
    }
  });
} else if (conf.h || conf.help || conf._.length === 0) {
  const cmd = process.argv[1].split('/').pop();
  console.error(
`Usage:

  ${cmd} [--options ...] [input-ipafile]

  -L, --identities              List local codesign identities
  -i, --identity 1C4D1A..       Specify hash-id of the identity to use
  -r, --replace                 Replace the input IPA file with the resigned one
  -d, --dependencies            Sign binaries in the correct dependency order
  -e, --entitlements [ENTITL]   Specify entitlements file (EXPERIMENTAL)
  -f, --without-fairplay        Resign encrypted applications
  -w, --without-watchapp        Remove the WatchApp from the IPA before resigning
  -k, --keychain [KEYCHAIN]     Specify alternative keychain file
  -o, --output [APP.IPA]        Path to the output IPA filename
  -b, --bundleid [BUNDLEID]     Change the bundleid when repackaging
  -m, --mobileprovision [FILE]  Specify the mobileprovision file to use
  -v, --verify-twice            Verify after signing every file and at the end
  [input-ipafile]               Path to the IPA file to resign

Example:

  ${cmd} --replace -identity AD71EB42BC289A2B9FD3C2D5C9F02D923495A23C \\
    --mobileprovision embedded.mobileprovision --bundleid com.nowsecure.TestApp ./foo.ipa
`);
} else {
  cs.signIPA(options.file, (error, data) => {
    if (error) {
      console.error(error, data);
      process.exit(1);
    }
    console.log('IPA is now signed.');
  }).on('message', (msg) => {
    console.log(colors.msg(msg));
  }).on('warning', (msg) => {
    console.log(colors.error('error'), msg);
  });
}
<commit_msg>Fix commandline parsing for flags that require no args<commit_after>#!/usr/bin/env node
'use strict';

const colors = require('colors');
const Applesign = require('../');
const conf = require('minimist')(process.argv.slice(2), {
  boolean: ['r', 'replace', 'L', 'identities', 'd', 'dependencies', 'v', 'verifyTwice', 'f', 'without-fairplay', 'w', 'without-watchapp']
});

const options = {
  file: conf._[0] || 'undefined',
  outfile: conf.output || conf.o,
  entitlement: conf.entitlement || conf.e,
  bundleid: conf.bundleid || conf.b,
  identity: conf.identity || conf.i,
  mobileprovision: conf.mobileprovision || conf.m,
  replaceipa: conf.replace || conf.r,
  withoutWatchapp: !!conf['without-watchapp'] || !!conf.w,
  graphSortedBins: conf.d || conf.dependencies,
  keychain: conf.keychain || conf.k,
  verifyTwice: conf.verifyTwice || !!conf.v,
  unfairPlay: conf['without-fairplay'] || conf.f
};

colors.setTheme({
  error: 'red',
  warn: 'green',
  msg: 'yellow'
});

const cs = new Applesign(options);

if (conf.identities || conf.L) {
  cs.getIdentities((err, ids) => {
    if (err) {
      console.error(colors.error(err));
    } else {
      ids.forEach((id) => {
        console.log(id.hash, id.name);
      });
    }
  });
} else if (conf.h || conf.help || conf._.length === 0) {
  const cmd = process.argv[1].split('/').pop();
  console.error(
`Usage:

  ${cmd} [--options ...] [input-ipafile]

  -L, --identities              List local codesign identities
  -i, --identity 1C4D1A..       Specify hash-id of the identity to use
  -r, --replace                 Replace the input IPA file with the resigned one
  -d, --dependencies            Sign binaries in the correct dependency order
  -e, --entitlements [ENTITL]   Specify entitlements file (EXPERIMENTAL)
  -f, --without-fairplay        Resign encrypted applications
  -w, --without-watchapp        Remove the WatchApp from the IPA before resigning
  -k, --keychain [KEYCHAIN]     Specify alternative keychain file
  -o, --output [APP.IPA]        Path to the output IPA filename
  -b, --bundleid [BUNDLEID]     Change the bundleid when repackaging
  -m, --mobileprovision [FILE]  Specify the mobileprovision file to use
  -v, --verify-twice            Verify after signing every file and at the end
  [input-ipafile]               Path to the IPA file to resign

Example:

  ${cmd} --replace -identity AD71EB42BC289A2B9FD3C2D5C9F02D923495A23C \\
    --mobileprovision embedded.mobileprovision --bundleid com.nowsecure.TestApp ./foo.ipa
`);
} else {
  cs.signIPA(options.file, (error, data) => {
    if (error) {
      console.error(error, data);
      process.exit(1);
    }
    console.log('IPA is now signed.');
  }).on('message', (msg) => {
    console.log(colors.msg(msg));
  }).on('warning', (msg) => {
    console.log(colors.error('error'), msg);
  });
}
<|endoftext|>


<commit_before>$( document ).ready( function() {

  $('.sortable').sortable({
    stop: function (event, ui) {
      reNumber();
    }
  });

  $('#add-new').click(function(){
    var newField = $('.row.padded-field').last().clone(true);
    appendField(newField, setDefaultValues)
  });

  $('.remove').click(function(){
    fields = $('.row.padded-field');
    parentField = $(this).parents('.row.padded-field')
    if(fields.length > 1) {
      parentField.remove();
    }
    // If they want to remove the last field, just empty it instead.
    else {
      setDefaultValues(parentField);
    }
    reNumber();
  });

  $('.data-type').change(function(){
    placeholder = $(this).parents('.padded-field').find('.placeholder');
    value = $(this).children('select').val()
    if(checkValues(value) == true) {
      if(placeholder.children().length == 0) {
        $('<input type="text" value="">').appendTo(placeholder);
      }
    } else {
      placeholder.children().remove();
    }
  });

  //haha formform

  $('form#form').on('ajax:before', function(event, xhr, settings){return false});

  $('form#form').submit(function(e){
    e.preventDefault;
    fields = $('.padded-field');
    var formData = {
      name: $('#name input').val(),
      email: $('#email input').val(),
      reply_to: $('#reply-to input').val(),
      fields: extractFieldData(fields)
    }
    var data = { form_draft: formData }
    var ID = $('form').data('id')
    var URL = '/form_drafts/'
    var method = 'POST' // create
    if(ID != undefined){
      URL = '/form_drafts/' + ID
      method = 'PUT' // update
    }
    $.ajax({
      url: URL,
      method: method,
      data: data
    }).done(function(){
      document.location.href = '/form_drafts/' + ID;
    });
  });

}); // END of document.ready

function checkValues(value){
  types = ['date', 'date/time', 'long-text', 'text', 'time']
  for (var i = 0; i < types.length; i++) {
    if(types[i] == value){
      return true;
    }
  }
}
function extractFieldData(fields) {
  var allFieldData = {}
  $('.padded-field').each( function (index) {
    var fieldData = {};
    fieldData['number'] = index + 1;
    fieldData['prompt'] = $(this).find('textarea').val();
    fieldData['placeholder'] = $(this).find('.placeholder').val();
    fieldData['required'] = $(this).find('.required :checkbox').prop('checked');
    fieldData['data_type'] = $(this).find('.data-type select').val();
    allFieldData[index] = fieldData;
    //TODO: $(this).find('.options')
  });
  return allFieldData
}
function newNumber() {
  return $('.grabbable-number').length + 1;
}
function reNumber() {
  $('.grabbable-number').each(function (index){
    $(this).text(index + 1);
  })
}
function setDefaultValues(field) {
  field.find('textarea').val('');
  field.find('.grabbable-number').text(newNumber());
  field.find('select').val('');
}
function appendField(field, callback){
  callback(field);
  field.appendTo('.container.sortable');
}

<commit_msg>rename function to something more appropriate. Use Array.prototype.includes because why wouldn't you do that.<commit_after>$( document ).ready( function() {

  $('.sortable').sortable({
    stop: function (event, ui) {
      reNumber();
    }
  });

  $('#add-new').click(function(){
    var newField = $('.row.padded-field').last().clone(true);
    appendField(newField, setDefaultValues)
  });

  $('.remove').click(function(){
    fields = $('.row.padded-field');
    parentField = $(this).parents('.row.padded-field')
    if(fields.length > 1) {
      parentField.remove();
    }
    // If they want to remove the last field, just empty it instead.
    else {
      setDefaultValues(parentField);
    }
    reNumber();
  });

  $('.data-type').change(function(){
    placeholder = $(this).parents('.padded-field').find('.placeholder');
    value = $(this).children('select').val()
    if(takesPlaceholder(value) == true) {
      if(placeholder.children().length == 0) {
        $('<input type="text" value="">').appendTo(placeholder);
      }
    } else {
      placeholder.children().remove();
    }
  });

  //haha formform

  $('form#form').on('ajax:before', function(event, xhr, settings){return false});

  $('form#form').submit(function(e){
    e.preventDefault;
    fields = $('.padded-field');
    var formData = {
      name: $('#name input').val(),
      email: $('#email input').val(),
      reply_to: $('#reply-to input').val(),
      fields: extractFieldData(fields)
    }
    var data = { form_draft: formData }
    var ID = $('form').data('id')
    var URL = '/form_drafts/'
    var method = 'POST' // create
    if(ID != undefined){
      URL = '/form_drafts/' + ID
      method = 'PUT' // update
    }
    $.ajax({
      url: URL,
      method: method,
      data: data
    }).done(function(){
      document.location.href = '/form_drafts/' + ID;
    });
  });

}); // END of document.ready

function takesPlaceholder(value){
  return ['date', 'date/time', 'long-text', 'text', 'time'].includes(value);
}

function extractFieldData(fields) {
  var allFieldData = {}
  $('.padded-field').each( function (index) {
    var fieldData = {};
    fieldData['number'] = index + 1;
    fieldData['prompt'] = $(this).find('textarea').val();
    fieldData['placeholder'] = $(this).find('.placeholder').val();
    fieldData['required'] = $(this).find('.required :checkbox').prop('checked');
    fieldData['data_type'] = $(this).find('.data-type select').val();
    allFieldData[index] = fieldData;
    //TODO: $(this).find('.options')
  });
  return allFieldData
}
function newNumber() {
  return $('.grabbable-number').length + 1;
}
function reNumber() {
  $('.grabbable-number').each(function (index){
    $(this).text(index + 1);
  })
}
function setDefaultValues(field) {
  field.find('textarea').val('');
  field.find('.grabbable-number').text(newNumber());
  field.find('select').val('');
}
function appendField(field, callback){
  callback(field);
  field.appendTo('.container.sortable');
}

<|endoftext|>


<commit_before>/**
 * A single socket connection
 * @constructor
 */
function NWTSocketInstance(params) {
	var mythis = this;

	this.resource = params[0];
	this.resource += ( this.resource.substring(0, this.resource.length - 1) == '/' ? '' : '/' ) + 'ajax/1/';

	this.config = params[1] || {};

	// Default some stuff
	this.config.postData = this.config.postData || '';
	this.config.failure = this.config.failure || function(){alert('fail');};

	if( this.config.form !== undefined ) {
		this.config.postData = this.config.form.serialize();
	}

	var request = new XMLHttpRequest();

	request.open("POST", this.resource, true);
	//request.setRequestHeader('Content-type','application/x-www-form-urlencoded');

	request.onreadystatechange = function () {
		if (request.readyState != 4) return;
		if (request.status != 200 && request.status != 304) {
			config.callback.failure();
			return;
		}

		var response = JSON.parse(request.responseText);

		// Handle special response keys
		// Scripts are included if they don't exist in the dom
		if( response.scripts !== undefined ) {
			for( var i in response.scripts  ) {
				if( !nwt.one('script#' +i)  ) {
				   var head= document.getElementsByTagName('head')[0];
				   var script= document.createElement('script');
				   script.type= 'text/javascript';
				   script.src= response.scripts[i];
				   script.id = i;
				   head.appendChild(script);
				}
			}
		}

		mythis.config.success(response);
	}
	if (request.readyState == 4) { return; }
	request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
	request.send(this.config.postData);
}

/**
 * Socket wrapper
 * @constructor
 */
function NWTSocket() {
}

/**
 * Makes a connection to the backend
 */
NWTSocket.prototype.send = function() {
	return new NWTSocketInstance(arguments);
};

nwt.socket = new NWTSocket();
<commit_msg>Fix config callback.<commit_after>/**
 * A single socket connection
 * @constructor
 */
function NWTSocketInstance(params) {
	var mythis = this;

	this.resource = params[0];
	this.resource += ( this.resource.substring(0, this.resource.length - 1) == '/' ? '' : '/' ) + 'ajax/1/';

	this.config = params[1] || {};

	// Default some stuff
	this.config.postData = this.config.postData || '';
	this.config.failure = this.config.failure || function(){alert('fail');};

	if( this.config.form !== undefined ) {
		this.config.postData = this.config.form.serialize();
	}

	var request = new XMLHttpRequest();

	request.open("POST", this.resource, true);
	//request.setRequestHeader('Content-type','application/x-www-form-urlencoded');

	request.onreadystatechange = function () {
		if (request.readyState != 4) return;
		if (request.status != 200 && request.status != 304) {
			mythis.config.callback.failure();
			return;
		}

		var response = JSON.parse(request.responseText);

		// Handle special response keys
		// Scripts are included if they don't exist in the dom
		if( response.scripts !== undefined ) {
			for( var i in response.scripts  ) {
				if( !nwt.one('script#' +i)  ) {
				   var head= document.getElementsByTagName('head')[0];
				   var script= document.createElement('script');
				   script.type= 'text/javascript';
				   script.src= response.scripts[i];
				   script.id = i;
				   head.appendChild(script);
				}
			}
		}

		mythis.config.success(response);
	}
	if (request.readyState == 4) { return; }
	request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
	request.send(this.config.postData);
}

/**
 * Socket wrapper
 * @constructor
 */
function NWTSocket() {
}

/**
 * Makes a connection to the backend
 */
NWTSocket.prototype.send = function() {
	return new NWTSocketInstance(arguments);
};

nwt.socket = new NWTSocket();
<|endoftext|>


<commit_before>'use strict';

var Stryker = require('stryker').default;

module.exports = function(grunt) {

  grunt.registerMultiTask('stryker', 'The extendable JavaScript mutation testing framework.', function() {
    var target = this.name + "." + this.target + ".";
    var filesProperty = target + 'files';
    var mutateProperty = target + 'mutate';

    grunt.config.requires(filesProperty);
    grunt.config.requires(mutateProperty);

    var files = grunt.file.expand(grunt.util.toArray(grunt.config.get(filesProperty)));
    var mutate = grunt.file.expand(grunt.util.toArray(grunt.config.get(mutateProperty)));

    var done = this.async();
    var stryker = new Stryker(mutate, files, this.options());
    stryker.runMutationTest(function() {
      done();
    });

  });

};
<commit_msg>fix(stryker) Catch Stryker reject and use Stryker config<commit_after>'use strict';

var Stryker = require('stryker').default;

module.exports = function (grunt) {

  grunt.registerMultiTask('stryker', 'The extendable JavaScript mutation testing framework.', function () {
    var target = this.name + "." + this.target + ".";
    var filesProperty = target + 'files';
    var mutateProperty = target + 'mutate';

    grunt.config.requires(filesProperty);
    grunt.config.requires(mutateProperty);

    var files = grunt.file.expand(grunt.util.toArray(grunt.config.get(filesProperty)));
    var mutate = grunt.file.expand(grunt.util.toArray(grunt.config.get(mutateProperty)));

    var strykerConfig = {
      files: files,
      mutate: mutate,
      logLevel: this.options().logLevel,
      testFramework: this.options().testFramework,
      testRunner: this.options().testRunner,
      timeoutMs: this.options().timeoutMs,
      timeoutFactor: this.options().timeoutFactor,
      plugins: this.options().plugins,
      port: this.options().port
    };

    var done = this.async();
    var stryker = new Stryker(strykerConfig);
    stryker.runMutationTest().then(function () {
      done();
    }, function () {
      grunt.fail.fatal("Stryker was unable to run the mutation test");
    });
  });

};
<|endoftext|>


<commit_before>/*
 ---

 script: require.js

 description: core css and js asset loading functionality, builds on mootools ASSET

 copyright: (c) 2010 Contributors in (/AUTHORS.txt).

 license: MIT-style license in (/MIT-LICENSE.txt).

 requires:
 - MochaUI/MUI
 - Core/Request
 - More/Hash
 - More/Assets

 provides: [MUI.Require, Asset.css ]

 ...
 */

MUI.Require = new Class({

	Implements: [Options],

	options: {
		css: [],
		images: [],
		js: []
		//onload: null
	},

	initialize: function(options){
		this.setOptions(options);
		options = this.options;

		this.assetsToLoad = options.css.length + options.images.length + options.js.length;
		this.assetsLoaded = 0;

		var cssLoaded = 0;

		// Load CSS before images and JavaScript

		if (options.css.length){
			options.css.each(function(sheet){

				this.getAsset(sheet, function(){
					if (cssLoaded == options.css.length - 1){
						if (this.assetsLoaded == this.assetsToLoad - 1) this.requireOnload();
						else {
							// Add a little delay since we are relying on cached CSS from XHR request.
							this.assetsLoaded++;
							this.requireContinue.delay(50, this);
						}
					} else {
						cssLoaded++;
						this.assetsLoaded++;
					}
				}.bind(this));
			}.bind(this));
		} else if (!options.js.length && !options.images.length){
			this.options.onload();
			return true;
		} else this.requireContinue.delay(50, this); // Delay is for Safari
	},

	requireOnload: function(){
		this.assetsLoaded++;
		if (this.assetsLoaded == this.assetsToLoad){
			this.options.onload();
			return true;
		}
	},

	requireContinue: function(){
		var options = this.options;
		if (options.images.length){
			options.images.each(function(image){
				this.getAsset(image, this.requireOnload.bind(this));
			}.bind(this));
		}

		if (options.js.length){
			options.js.each(function(script){
				this.getAsset(script, this.requireOnload.bind(this));
			}.bind(this));
		}
	},

	getAsset: function(source, onload){
		// If the asset is loaded, fire the onload function.
		if (MUI.files[source] == 'loaded'){
			if (typeof onload == 'function'){
				onload();
			}
			return true;
		}

		// If the asset is loading, wait until it is loaded and then fire the onload function.
		// If asset doesn't load by a number of tries, fire onload anyway.
		else if (MUI.files[source] == 'loading'){
			var tries = 0;
			var checker = (function(){
				tries++;
				if (MUI.files[source] == 'loading' && tries < '100') return;
				clearInterval(checker);
				if (typeof onload == 'function'){
					onload();
				}
			}).periodical(50);
		} else {  // If the asset is not yet loaded or loading, start loading the asset.
			MUI.files[source] = 'loading';

			properties = {
				'onload': onload != 'undefined' ? onload : null
			};

			// Add to the onload function
			var oldonload = properties.onload;
			properties.onload = function(){
				MUI.files[source] = 'loaded';
				if (oldonload) oldonload();
			}.bind(this);

			var sourcePath = MUI.replacePaths(source);
			switch (sourcePath.match(/\.\w+$/)[0]){
				case '.js': return Asset.javascript(sourcePath, properties);
				case '.css': return Asset.css(sourcePath, properties);
				case '.jpg':
				case '.png':
				case '.gif': return Asset.image(sourcePath, properties);
			}

			alert('The required file "' + source + '" could not be loaded');
		}
	}
});

Object.append(Asset, {
	// Get the CSS with XHR before appending it to document.head so that we can have an onload callback.
	css: function(source, properties){
		properties = Object.append({
			id: null,
			media: 'screen',
			onload: null
		}, properties);

		new Request({
			method: 'get',
			url: source,
			onComplete: function(){
				newSheet = new Element('link', {
					'id': properties.id,
					'rel': 'stylesheet',
					'media': properties.media,
					'type': 'text/css',
					'href': source
				}).inject(document.head);
				properties.onload();
			}.bind(this),
			onFailure: function(){
			},
			onSuccess: function(){
			}.bind(this)
		}).send();
	},

	getCSSRule: function(selector){
		for (var ii = 0; ii < document.styleSheets.length; ii++){
			var mySheet = document.styleSheets[ii];
			var myRules = mySheet.cssRules ? mySheet.cssRules : mySheet.rules;
			for (var i = 0; i < myRules.length; i++){
				if (myRules[i].selectorText == selector){
					return myRules[i];
				}
			}
		}
		return false;
	}
});<commit_msg>class not being found in chrome because of casing<commit_after>/*
 ---

 script: require.js

 description: core css and js asset loading functionality, builds on mootools ASSET

 copyright: (c) 2010 Contributors in (/AUTHORS.txt).

 license: MIT-style license in (/MIT-LICENSE.txt).

 requires:
 - MochaUI/MUI
 - Core/Request
 - More/Hash
 - More/Assets

 provides: [MUI.Require, Asset.css ]

 ...
 */

MUI.Require = new Class({

	Implements: [Options],

	options: {
		css: [],
		images: [],
		js: []
		//onload: null
	},

	initialize: function(options){
		this.setOptions(options);
		options = this.options;

		this.assetsToLoad = options.css.length + options.images.length + options.js.length;
		this.assetsLoaded = 0;

		var cssLoaded = 0;

		// Load CSS before images and JavaScript

		if (options.css.length){
			options.css.each(function(sheet){

				this.getAsset(sheet, function(){
					if (cssLoaded == options.css.length - 1){
						if (this.assetsLoaded == this.assetsToLoad - 1) this.requireOnload();
						else {
							// Add a little delay since we are relying on cached CSS from XHR request.
							this.assetsLoaded++;
							this.requireContinue.delay(50, this);
						}
					} else {
						cssLoaded++;
						this.assetsLoaded++;
					}
				}.bind(this));
			}.bind(this));
		} else if (!options.js.length && !options.images.length){
			this.options.onload();
			return true;
		} else this.requireContinue.delay(50, this); // Delay is for Safari
	},

	requireOnload: function(){
		this.assetsLoaded++;
		if (this.assetsLoaded == this.assetsToLoad){
			this.options.onload();
			return true;
		}
	},

	requireContinue: function(){
		var options = this.options;
		if (options.images.length){
			options.images.each(function(image){
				this.getAsset(image, this.requireOnload.bind(this));
			}.bind(this));
		}

		if (options.js.length){
			options.js.each(function(script){
				this.getAsset(script, this.requireOnload.bind(this));
			}.bind(this));
		}
	},

	getAsset: function(source, onload){
		// If the asset is loaded, fire the onload function.
		if (MUI.files[source] == 'loaded'){
			if (typeof onload == 'function'){
				onload();
			}
			return true;
		}

		// If the asset is loading, wait until it is loaded and then fire the onload function.
		// If asset doesn't load by a number of tries, fire onload anyway.
		else if (MUI.files[source] == 'loading'){
			var tries = 0;
			var checker = (function(){
				tries++;
				if (MUI.files[source] == 'loading' && tries < '100') return;
				clearInterval(checker);
				if (typeof onload == 'function'){
					onload();
				}
			}).periodical(50);
		} else {  // If the asset is not yet loaded or loading, start loading the asset.
			MUI.files[source] = 'loading';

			properties = {
				'onload': onload != 'undefined' ? onload : null
			};

			// Add to the onload function
			var oldonload = properties.onload;
			properties.onload = function(){
				MUI.files[source] = 'loaded';
				if (oldonload) oldonload();
			}.bind(this);

			var sourcePath = MUI.replacePaths(source);
			switch (sourcePath.match(/\.\w+$/)[0]){
				case '.js': return Asset.javascript(sourcePath, properties);
				case '.css': return Asset.css(sourcePath, properties);
				case '.jpg':
				case '.png':
				case '.gif': return Asset.image(sourcePath, properties);
			}

			alert('The required file "' + source + '" could not be loaded');
		}
	}
});

Object.append(Asset, {
	// Get the CSS with XHR before appending it to document.head so that we can have an onload callback.
	css: function(source, properties){
		properties = Object.append({
			id: null,
			media: 'screen',
			onload: null
		}, properties);

		new Request({
			method: 'get',
			url: source,
			onComplete: function(){
				newSheet = new Element('link', {
					'id': properties.id,
					'rel': 'stylesheet',
					'media': properties.media,
					'type': 'text/css',
					'href': source
				}).inject(document.head);
				properties.onload();
			}.bind(this),
			onFailure: function(){
			},
			onSuccess: function(){
			}.bind(this)
		}).send();
	},

	getCSSRule: function(selector){
		for (var ii = 0; ii < document.styleSheets.length; ii++){
			var mySheet = document.styleSheets[ii];
			var myRules = mySheet.cssRules ? mySheet.cssRules : mySheet.rules;
			selector=selector.toLowerCase();
			for (var i = 0; i < myRules.length; i++){
				if (myRules[i].selectorText.toLowerCase() == selector){
					return myRules[i];
				}
			}
		}
		return false;
	}
});<|endoftext|>


<commit_before>import React from 'react';

class Header extends React.PureComponent {
  render() {
    const { background, color } = this.props;
    return (

{this.props.title}

        {this.props.subtitle && (

{this.props.subtitle}

        )}
        {this.props.author && (

            By: {this.props.author}

        )}
        {this.props.authors ? (

            By:{' '}
            {this.props.authors.map((author, i) => {
              if (typeof author === 'string') {
                return author;
              }
              return author.link ? (

                  {author.name}
                  {i < this.props.authors.length - 1
                    ? i === this.props.authors.length - 2
                      ? ' and '
                      : ', '
                    : ''}

              ) : (
                author.name
              );
            })}
            {}

        ) : null}
        {this.props.date && (

{this.props.date}

        )}

    );
  }
}

Header._idyll = {
  name: 'Header',
  tagType: 'closed',
  props: [
    {
      name: 'title',
      type: 'string',
      example: '"Article Title"'
    },
    {
      name: 'subtitle',
      type: 'string',
      example: '"Article subtitle."'
    },
    {
      name: 'author',
      type: 'string',
      example: '"Author Name"'
    },
    {
      name: 'authorLink',
      type: 'string',
      example: '"author.website"'
    },
    {
      name: 'authors',
      type: 'array',
      example: "`[{name: 'Jane Doe', link: 'https://website.com'}]`",
      description:
        'An array of authors. Each element of the array can be an object or a string.'
    },
    {
      name: 'date',
      type: 'string',
      example: '"December 25, 2018"',
      description: 'The publication date.'
    },
    {
      name: 'background',
      type: 'string',
      example: '"blue"',
      defaultValue: '"#222"',
      description: 'The background of the header. Can pass a color or a url().'
    },
    {
      name: 'color',
      type: 'string',
      example: '"#000"',
      defaultValue: '"#fff"',
      description: 'The text color of the header.'
    }
  ]
};

export default Header;
<commit_msg>Add byline template<commit_after>import React from 'react';

const byLineDefault = { prefix: 'By:', joint: ',', suffix: 'and' };

class Header extends React.PureComponent {
  render() {
    const { background, color, byLineTemplate } = this.props;
    const { joint, prefix, suffix } = { ...byLineDefault, ...byLineTemplate };

    return (

{this.props.title}

        {this.props.subtitle && (

{this.props.subtitle}

        )}
        {this.props.author && (

            {`${prefix} `}
            {this.props.author}

        )}
        {this.props.authors ? (

            {`${prefix} `}
            {this.props.authors.map((author, i) => {
              if (typeof author === 'string') {
                return author;
              }
              return author.link ? (

                  {author.name}
                  {i < this.props.authors.length - 1
                    ? i === this.props.authors.length - 2
                      ? ` ${suffix} `
                      : `${joint} `
                    : ''}

              ) : (
                author.name
              );
            })}
            {}

        ) : null}
        {this.props.date && (

{this.props.date}

        )}

    );
  }
}

Header._idyll = {
  name: 'Header',
  tagType: 'closed',
  props: [
    {
      name: 'title',
      type: 'string',
      example: '"Article Title"'
    },
    {
      name: 'subtitle',
      type: 'string',
      example: '"Article subtitle."'
    },
    {
      name: 'author',
      type: 'string',
      example: '"Author Name"'
    },
    {
      name: 'authorLink',
      type: 'string',
      example: '"author.website"'
    },
    {
      name: 'authors',
      type: 'array',
      example: "`[{name: 'Jane Doe', link: 'https://website.com'}]`",
      description:
        'An array of authors. Each element of the array can be an object or a string.'
    },
    {
      name: 'date',
      type: 'string',
      example: '"December 25, 2018"',
      description: 'The publication date.'
    },
    {
      name: 'background',
      type: 'string',
      example: '"blue"',
      defaultValue: '"#222"',
      description: 'The background of the header. Can pass a color or a url().'
    },
    {
      name: 'byLineTemplate',
      type: 'object',
      example: "{ prefix: 'Made by', joint: ' -', suffix: '&' }",
      description: 'Optional template to use in by line.'
    },
    {
      name: 'color',
      type: 'string',
      example: '"#000"',
      defaultValue: '"#fff"',
      description: 'The text color of the header.'
    }
  ]
};

export default Header;
<|endoftext|>


<commit_before>var color = d3.scale.ordinal()
    .range(["#1abc9c","#ecf0f1","#95a5a6"]);
var w = 300,
    h = 200,
    radius = Math.min(w, h) / 2;

var params = d3.select("h1");
if (!params.empty()) {
    var api_key = params.attr('data-api_key');
    var name = params.attr('data-name');
    var query = encodeURI("/api/v5/sources/" + name + "?api_key=" + api_key);
}

d3.json(query, function(error, json) {
    if (error) return console.warn(error);

    SourceViz(json);
    StatusDonutViz(json);
    dayDonutViz(json);
    monthDonutViz(json);
});

// add data to page
function sourceViz(json) {
    data = json['data'];

    d3.select("#update_date").html(formatTime(inputTime.parse(data["update_date"])));

    // Summary table
    d3.select("#response_count").html(numberWithDelimiter(data["responses"]["count"]));

    d3.select("#average_count").html(numberWithDelimiter(data["responses"]["average"]));
    d3.select("#maximum_count").html(numberWithDelimiter(data["responses"]["maximum"]));

    d3.select("#article_count").html(numberWithDelimiter(data["article_count"]));
    d3.select("#event_count").html(numberWithDelimiter(data["event_count"]));
};

// Status donut chart
function statusDonutViz(json) {
    data = d3.entries(json["data"]["status"]);

    var chart = d3.select("div#chart_status").append("svg")
        .data([data])
        .attr("width", w)
        .attr("height", h)
        .attr("class", "chart")
        .append("svg:g")
        .attr("transform", "translate(150,100)")

    var arc = d3.svg.arc()
        .outerRadius(radius - 10)
        .innerRadius(radius - 40);

    var pie = d3.layout.pie()
        .sort(null)
        .value(function(d) { return d.value; });

    var arcs = chart.selectAll("g.slice")
        .data(pie)
        .enter()
        .append("svg:g")
        .attr("class", "slice");

    arcs.append("svg:path")
        .attr("fill", function(d, i) { return color(i); } )
        .attr("d", arc);

    arcs.each(
        function(d,i){ $(this).tooltip({title: formatFixed(d.data.value) + " articles " + d.data.key, container: "body"});
    });

    chart.append("text")
        .attr("dy", 0)
        .attr("text-anchor", "middle")
        .attr("class", "title")
        .text("Status");

    chart.append("text")
        .attr("dy", 21)
        .attr("text-anchor", "middle")
        .attr("class", "subtitle")
        .text("of articles");

};

// Events today donut chart
function dayDonutViz(json) {
    data = d3.entries(json["data"]["by_day"]);

    var chart = d3.select("div#chart_day").append("svg")
      .data([data])
      .attr("width", w)
      .attr("height", h)
      .attr("class", "chart")
      .append("svg:g")
      .attr("transform", "translate(150,100)")

    var arc = d3.svg.arc()
      .outerRadius(radius - 10)
      .innerRadius(radius - 40);

    var pie = d3.layout.pie()
      .sort(null)
      .value(function(d) { return d.value; });

    var arcs = chart.selectAll("g.slice")
      .data(pie)
      .enter()
      .append("svg:g")
      .attr("class", "slice");

    arcs.append("svg:path")
      .attr("fill", function(d, i) { return color(i); } )
      .attr("d", arc);
    arcs.each(
      function(d,i){ $(this).tooltip({title: formatFixed(d.data.value) + " articles " + d.data.key.replace("_", " "), container: "body"});
    });

    chart.append("text")
      .attr("dy", 0)
      .attr("text-anchor", "middle")
      .attr("class", "title")
      .text("Events");

    chart.append("text")
      .attr("dy", 21)
      .attr("text-anchor", "middle")
      .attr("class", "subtitle")
      .text("last 24 hours");

    // return chart object
    return chart;
};

// Events this month donut chart
function monthDonutViz(json) {
    data = d3.entries(json["data"]["by_month"]);

    var chart = d3.select("div#chart_month").append("svg")
      .data([data])
      .attr("width", w)
      .attr("height", h)
      .attr("class", "chart")
      .append("svg:g")
      .attr("transform", "translate(150,100)");

    var arc = d3.svg.arc()
      .outerRadius(radius - 10)
      .innerRadius(radius - 40);

    var pie = d3.layout.pie()
      .sort(null)
      .value(function(d) { return d.value; });

    var arcs = chart.selectAll("g.slice")
      .data(pie)
      .enter()
      .append("svg:g")
      .attr("class", "slice");

    arcs.append("svg:path")
      .attr("fill", function(d, i) { return color(i); } )
      .attr("d", arc);
    arcs.each(
    function(d,i){ $(this).tooltip({title: formatFixed(d.data.value) + " articles " + d.data.key.replace("_", " "), container: "body"});
    });

    chart.append("text")
      .attr("dy", 0)
      .attr("text-anchor", "middle")
      .attr("class", "title")
      .text("Events");

    chart.append("text")
      .attr("dy", 21)
      .attr("text-anchor", "middle")
      .attr("class", "subtitle")
      .text("last 31 days");

    // return chart object
    return chart;
};

// add delimiters for large numbers
function numberWithDelimiter(number) {
    if(number !== 0) {
        return formatFixed(number);
    } else {
        return null;
    }
};

var formatFixed = d3.format(",.0f");
var inputTime = d3.time.format.iso;
var formatTime = d3.time.format.utc("%d %b %H:%M UTC");
<commit_msg>ALM-640 fixed typo<commit_after>var color = d3.scale.ordinal()
    .range(["#1abc9c","#ecf0f1","#95a5a6"]);
var w = 300,
    h = 200,
    radius = Math.min(w, h) / 2;

var params = d3.select("h1");
if (!params.empty()) {
    var api_key = params.attr('data-api_key');
    var name = params.attr('data-name');
    var query = encodeURI("/api/v5/sources/" + name + "?api_key=" + api_key);
}

d3.json(query, function(error, json) {
    if (error) return console.warn(error);

    sourceViz(json);
    statusDonutViz(json);
    dayDonutViz(json);
    monthDonutViz(json);
});

// add data to page
function sourceViz(json) {
    data = json['data'];

    d3.select("#update_date").html(formatTime(inputTime.parse(data["update_date"])));

    // Summary table
    d3.select("#response_count").html(numberWithDelimiter(data["responses"]["count"]));

    d3.select("#average_count").html(numberWithDelimiter(data["responses"]["average"]));
    d3.select("#maximum_count").html(numberWithDelimiter(data["responses"]["maximum"]));

    d3.select("#article_count").html(numberWithDelimiter(data["article_count"]));
    d3.select("#event_count").html(numberWithDelimiter(data["event_count"]));
};

// Status donut chart
function statusDonutViz(json) {
    data = d3.entries(json["data"]["status"]);

    var chart = d3.select("div#chart_status").append("svg")
        .data([data])
        .attr("width", w)
        .attr("height", h)
        .attr("class", "chart")
        .append("svg:g")
        .attr("transform", "translate(150,100)")

    var arc = d3.svg.arc()
        .outerRadius(radius - 10)
        .innerRadius(radius - 40);

    var pie = d3.layout.pie()
        .sort(null)
        .value(function(d) { return d.value; });

    var arcs = chart.selectAll("g.slice")
        .data(pie)
        .enter()
        .append("svg:g")
        .attr("class", "slice");

    arcs.append("svg:path")
        .attr("fill", function(d, i) { return color(i); } )
        .attr("d", arc);

    arcs.each(
        function(d,i){ $(this).tooltip({title: formatFixed(d.data.value) + " articles " + d.data.key, container: "body"});
    });

    chart.append("text")
        .attr("dy", 0)
        .attr("text-anchor", "middle")
        .attr("class", "title")
        .text("Status");

    chart.append("text")
        .attr("dy", 21)
        .attr("text-anchor", "middle")
        .attr("class", "subtitle")
        .text("of articles");

};

// Events today donut chart
function dayDonutViz(json) {
    data = d3.entries(json["data"]["by_day"]);

    var chart = d3.select("div#chart_day").append("svg")
      .data([data])
      .attr("width", w)
      .attr("height", h)
      .attr("class", "chart")
      .append("svg:g")
      .attr("transform", "translate(150,100)")

    var arc = d3.svg.arc()
      .outerRadius(radius - 10)
      .innerRadius(radius - 40);

    var pie = d3.layout.pie()
      .sort(null)
      .value(function(d) { return d.value; });

    var arcs = chart.selectAll("g.slice")
      .data(pie)
      .enter()
      .append("svg:g")
      .attr("class", "slice");

    arcs.append("svg:path")
      .attr("fill", function(d, i) { return color(i); } )
      .attr("d", arc);
    arcs.each(
      function(d,i){ $(this).tooltip({title: formatFixed(d.data.value) + " articles " + d.data.key.replace("_", " "), container: "body"});
    });

    chart.append("text")
      .attr("dy", 0)
      .attr("text-anchor", "middle")
      .attr("class", "title")
      .text("Events");

    chart.append("text")
      .attr("dy", 21)
      .attr("text-anchor", "middle")
      .attr("class", "subtitle")
      .text("last 24 hours");

    // return chart object
    return chart;
};

// Events this month donut chart
function monthDonutViz(json) {
    data = d3.entries(json["data"]["by_month"]);

    var chart = d3.select("div#chart_month").append("svg")
      .data([data])
      .attr("width", w)
      .attr("height", h)
      .attr("class", "chart")
      .append("svg:g")
      .attr("transform", "translate(150,100)");

    var arc = d3.svg.arc()
      .outerRadius(radius - 10)
      .innerRadius(radius - 40);

    var pie = d3.layout.pie()
      .sort(null)
      .value(function(d) { return d.value; });

    var arcs = chart.selectAll("g.slice")
      .data(pie)
      .enter()
      .append("svg:g")
      .attr("class", "slice");

    arcs.append("svg:path")
      .attr("fill", function(d, i) { return color(i); } )
      .attr("d", arc);
    arcs.each(
    function(d,i){ $(this).tooltip({title: formatFixed(d.data.value) + " articles " + d.data.key.replace("_", " "), container: "body"});
    });

    chart.append("text")
      .attr("dy", 0)
      .attr("text-anchor", "middle")
      .attr("class", "title")
      .text("Events");

    chart.append("text")
      .attr("dy", 21)
      .attr("text-anchor", "middle")
      .attr("class", "subtitle")
      .text("last 31 days");

    // return chart object
    return chart;
};

// add delimiters for large numbers
function numberWithDelimiter(number) {
    if(number !== 0) {
        return formatFixed(number);
    } else {
        return null;
    }
};

var formatFixed = d3.format(",.0f");
var inputTime = d3.time.format.iso;
var formatTime = d3.time.format.utc("%d %b %H:%M UTC");
<|endoftext|>


<commit_before>/*
 ---

 script: require.js

 description: core css and js asset loading functionality, builds on mootools ASSET

 copyright: (c) 2011 Contributors in (/AUTHORS.txt).

 license: MIT-style license in (/MIT-LICENSE.txt).

 requires:
 - MochaUI/MUI
 - Core/Request
 - More/Hash
 - More/Assets

 provides: [MUI.Require, Asset.css ]

 ...
 */

MUI.Require = new Class({

	Implements: [Options],

	options: {
		css: [],
		images: [],
		js: []
		//onload: null
	},

	initialize: function(options){
		this.setOptions(options);
		options = this.options;

		this.assetsToLoad = options.css.length + options.images.length + options.js.length;
		this.assetsLoaded = 0;

		var cssLoaded = 0;

		// Load CSS before images and JavaScript

		if (options.css.length){
			options.css.each(function(sheet){

				this.getAsset(sheet, function(){
					if (cssLoaded == options.css.length - 1){
						if (this.assetsLoaded == this.assetsToLoad - 1) this.requireOnload();
						else {
							// Add a little delay since we are relying on cached CSS from XHR request.
							this.assetsLoaded++;
							this.requireContinue.delay(50, this);
						}
					} else {
						cssLoaded++;
						this.assetsLoaded++;
					}
				}.bind(this));
			}.bind(this));
		} else if (!options.js.length && !options.images.length){
			this.options.onload();
			return true;
		} else this.requireContinue.delay(50, this); // Delay is for Safari
	},

	requireOnload: function(){
		this.assetsLoaded++;
		if (this.assetsLoaded == this.assetsToLoad){
			if(this.options.onload) this.options.onload();
			return true;
		}
	},

	requireContinue: function(){
		var options = this.options;
		if (options.images.length){
			options.images.each(function(image){
				this.getAsset(image, this.requireOnload.bind(this));
			}.bind(this));
		}

		if (options.js.length){
			options.js.each(function(script){
				this.getAsset(script, this.requireOnload.bind(this));
			}.bind(this));
		}
	},

	getAsset: function(source, onload){
		// If the asset is loaded, fire the onload function.
		if (MUI.files[source] == 'loaded'){
			if (typeof onload == 'function'){
				onload();
			}
			return true;
		}

		// If the asset is loading, wait until it is loaded and then fire the onload function.
		// If asset doesn't load by a number of tries, fire onload anyway.
		else if (MUI.files[source] == 'loading'){
			var tries = 0;
			var checker = (function(){
				tries++;
				if (MUI.files[source] == 'loading' && tries < 100) return;
				clearInterval(checker);
				if (typeof onload == 'function'){
					onload();
				}
			}).periodical(50);
		} else {  // If the asset is not yet loaded or loading, start loading the asset.
			MUI.files[source] = 'loading';

			properties = {
				'onload': onload != 'undefined' ? onload : null
			};

			// Add to the onload function
			var oldonload = properties.onload;
			properties.onload = function(){
				MUI.files[source] = 'loaded';
				if (oldonload) oldonload();
			}.bind(this);

			var sourcePath = MUI.replacePaths(source);
			switch (sourcePath.match(/\.\w+$/)[0]){
				case '.js': return Asset.javascript(sourcePath, properties);
				case '.css': return Asset.css(sourcePath, properties);
				case '.jpg':
				case '.png':
				case '.gif': return Asset.image(sourcePath, properties);
			}

			alert('The required file "' + source + '" could not be loaded');
		}
	}
});

Object.append(Asset, {
	// Get the CSS with XHR before appending it to document.head so that we can have an onload callback.
	css: function(source, properties){
		properties = Object.append({
			id: null,
			media: 'screen',
			onload: null
		}, properties);

		new Request({
			method: 'get',
			url: source,
			onComplete: function(){
				newSheet = new Element('link', {
					'id': properties.id,
					'rel': 'stylesheet',
					'media': properties.media,
					'type': 'text/css',
					'href': source
				}).inject(document.head);
				if (typeOf(properties.onload) == 'function') properties.onload();
			}.bind(this),
			onFailure: function(){
			},
			onSuccess: function(){
			}.bind(this)
		}).send();
	},

	getCSSRule: function(selector){
		for (var ii = 0; ii < document.styleSheets.length; ii++){
			var mySheet = document.styleSheets[ii];
			var myRules = mySheet.cssRules ? mySheet.cssRules : mySheet.rules;
			selector=selector.toLowerCase();
			for (var i = 0; i < myRules.length; i++){
				if (myRules[i].selectorText.toLowerCase() == selector){
					return myRules[i];
				}
			}
		}
		return false;
	}
});<commit_msg>manual merge of https://github.com/GerHobbelt/mochaui/commit/b06ae0fafd9ffbee1e7633a4000a5b66666531f2<commit_after>/*
 ---

 script: require.js

 description: core css and js asset loading functionality, builds on mootools ASSET

 copyright: (c) 2011 Contributors in (/AUTHORS.txt).

 license: MIT-style license in (/MIT-LICENSE.txt).

 requires:
 - MochaUI/MUI
 - Core/Request
 - More/Hash
 - More/Assets

 provides: [MUI.Require, Asset.css ]

 ...
 */

MUI.Require = new Class({

	Implements: [Options],

	options: {
		css: [],
		images: [],
		js: []
		//onload: null
	},

	initialize: function(options){
		this.setOptions(options);
		options = this.options;

		this.assetsToLoad = options.css.length + options.images.length + options.js.length;
		this.assetsLoaded = 0;

		var cssLoaded = 0;

		// Load CSS before images and JavaScript

		if (options.css.length){
			options.css.each(function(sheet){

				this.getAsset(sheet, function(){
					if (cssLoaded == options.css.length - 1){
						if (this.assetsLoaded == this.assetsToLoad - 1) this.requireOnload();
						else {
							// Add a little delay since we are relying on cached CSS from XHR request.
							this.assetsLoaded++;
							this.requireContinue.delay(50, this);
						}
					} else {
						cssLoaded++;
						this.assetsLoaded++;
					}
				}.bind(this));
			}.bind(this));
		} else if (!options.js.length && !options.images.length){
			if (typeof this.options.onload == 'function'){
				this.options.onload();
			}
			return true;
		} else this.requireContinue.delay(50, this); // Delay is for Safari
	},

	requireOnload: function(){
		this.assetsLoaded++;
		if (this.assetsLoaded == this.assetsToLoad){
			if (typeof this.options.onload == 'function'){
				this.options.onload();
			}
			return true;
		}
	},

	requireContinue: function(){
		var options = this.options;
		if (options.images.length){
			options.images.each(function(image){
				this.getAsset(image, this.requireOnload.bind(this));
			}.bind(this));
		}

		if (options.js.length){
			options.js.each(function(script){
				this.getAsset(script, this.requireOnload.bind(this));
			}.bind(this));
		}
	},

	getAsset: function(source, onload){
		// If the asset is loaded, fire the onload function.
		if (MUI.files[source] == 'loaded'){
			if (typeof onload == 'function'){
				onload(source);
			}
			return true;
		}

		// If the asset is loading, wait until it is loaded and then fire the onload function.
		// If asset doesn't load by a number of tries, fire onload anyway.
		else if (MUI.files[source] == 'loading'){
			var tries = 0;
			var checker = (function(){
				tries++;
				if (MUI.files[source] == 'loading' && tries < 100) return;
				clearInterval(checker);
				if (typeof onload == 'function'){
					onload(source);
				}
			}).periodical(50);
		} else {  // If the asset is not yet loaded or loading, start loading the asset.
			MUI.files[source] = 'loading';

			properties = {
				'onload': onload != 'undefined' ? onload : null
			};

			// Add to the onload function
			var oldonload = properties.onload;
			properties.onload = function(/* source */){
				MUI.files[source] = 'loaded';
				if (typeof oldonload == 'function') {
					oldonload(source);
				}
			}.bind(this);

			var sourcePath = MUI.replacePaths(source);
			switch (sourcePath.match(/\.\w+$/)[0]){
				case '.js': return Asset.javascript(sourcePath, properties);
				case '.css': return Asset.css(sourcePath, properties);
				case '.jpg':
				case '.png':
				case '.gif': return Asset.image(sourcePath, properties);
			}

			alert('The required file "' + source + '" could not be loaded');
		}
	}
});

Object.append(Asset, {
	// Get the CSS with XHR before appending it to document.head so that we can have an onload callback.
	css: function(source, properties){
		properties = Object.append({
			id: null,
			media: 'screen',
			onload: null
		}, properties);

		new Request({
			method: 'get',
			url: source,
			onComplete: function(){
				newSheet = new Element('link', {
					'id': properties.id,
					'rel': 'stylesheet',
					'media': properties.media,
					'type': 'text/css',
					'href': source
				}).inject(document.head);
				if (typeOf(properties.onload) == 'function') properties.onload();
			}.bind(this),
			onFailure: function(){
			},
			onSuccess: function(){
			}.bind(this)
		}).send();
	},

	getCSSRule: function(selector){
		for (var ii = 0; ii < document.styleSheets.length; ii++){
			var mySheet = document.styleSheets[ii];
			var myRules = mySheet.cssRules ? mySheet.cssRules : mySheet.rules;
			selector=selector.toLowerCase();
			for (var i = 0; i < myRules.length; i++){
				if (myRules[i].selectorText.toLowerCase() == selector){
					return myRules[i];
				}
			}
		}
		return false;
	}
});<|endoftext|>


<commit_before>Template.IMonBarchartWidget.onCreated(function() {
  var template = this;
  template.autorun(function() {
    var mode = Template.currentData().mode;
    var indicators = mode === 'single' ? [ Template.currentData().y.single.indicator ] :  Template.currentData().x.multi.indicator ;
    template.subscribe('imon_data', 'all', indicators,'id');
    template.subscribe('imon_indicators');
    template.subscribe('imon_countries');
  });
});

Template.IMonBarchartWidget.onRendered(function() {
  var template = this;
  var node = template.find('.barchart');
  var widgetNode = template.firstNode.parentNode.parentNode;
  var $widgetBody = $(widgetNode).find('.widget-body');
  var mode = Template.currentData().mode;
  var chart = d3.select(node).chart('Compose', function(options) {
    var xs = _.pluck(options.data, 'x'), ys = _.pluck(options.data, 'y');

    var scales = mode === 'single' ? {
      x: { domain: xs, type: 'ordinal', adjacent: true },
      y: { domain: [0, _.max(ys)] }
    } : {
      x: { domain: xs, type: 'ordinal', adjacent: true },
      y: { domain: [0, 100] }
    };

    var charts = [{
      type: 'Bars',
      id: 'bars',
      data: options.data,
      xScale: scales.x,
      yScale: scales.y,
      labels: {
        offset: 3
      }
    }];

    var title = d3c.title('Custom Chart');
    var xAxis = d3c.axis('xAxis', {scale: scales.x, ticks: 3});
    var yAxis = d3c.axis('yAxis', {scale: scales.y, ticks: 3});
    var xAxisTitle = d3c.axisTitle(options.xAxisTitle);
    var yAxisTitle = d3c.axisTitle(options.yAxisTitle);

    return [
      [yAxisTitle, yAxis, d3c.layered(charts)],
      xAxis,
      xAxisTitle
    ];
  });

  var setChartDims = function() {
    var width = $widgetBody.outerWidth() - Settings.chart.padding.right;
    var height = $widgetBody.outerHeight() - Settings.chart.padding.bottom;
    chart.width(width);
    chart.height(height);
  };

  $(widgetNode).on('gridster:resizestop', function() {
    setChartDims();
    chart.redraw();
  });

  var redrawn = false;
  template.autorun(function() {
    if (!template.subscriptionsReady()) { return; }
    var yIndicator;
    var xTitle;
    var yTitle;

    var data = [];
    var mode_reactive = Template.currentData().mode;
    if(mode_reactive === 'single'){
      yIndicator = Template.currentData().y.single.indicator;
      xTitle = 'Countries';
      yTitle = IMonIndicators.findOne({ id: yIndicator }).shortName;
      IMonCountries.find({ code: {$in: Template.currentData().x.single.indicator } }).forEach(function(country) {
        var y = IMonData.findOne({ countryCode: country.code, sourceId: yIndicator });
        if (_.isUndefined(y)) { return; }

        var xValue = country.name, yValue = y.value;

        data.push({
          x: xValue,
          y: yValue,
          code: country.code,
          key: country.code,
          label: yValue
        });
      });
    }
    else{
      yIndicator = Template.currentData().y.multi.indicator;
      yTitle = IMonCountries.findOne({ code: yIndicator }).name;
      IMonData.find({ countryCode: yIndicator, sourceId: { $in: Template.currentData().x.multi.indicator } }).forEach(function(field){
        var yValue = Math.round(field.percent * 100).toFixed(2);
        var xValue = IMonIndicators.findOne({ id: field.sourceId }).shortName;

        data.push({
          x: xValue,
          y: yValue,
          code: field.id,
          key: field.id,
          label: yValue
        });
      });
    }

    chart.margins(Settings.chart.margins);
    chart.responsive(false);

    chart.draw({
      data: data,
      xAxisTitle: xTitle,
      yAxisTitle: yTitle
    });

    // This is a hacky way to get the chart to fit the widget on first draw
    // because it wouldn't throw the draw event correctly.
    if (!redrawn) {
      setChartDims();
      chart.redraw();
      redrawn = true;
    }
  });
});
<commit_msg>Fix scale problem<commit_after>Template.IMonBarchartWidget.onCreated(function() {
  var template = this;
  template.autorun(function() {
    var mode = Template.currentData().mode;
    var indicators = mode === 'single' ? [ Template.currentData().y.single.indicator ] :  Template.currentData().x.multi.indicator ;
    template.subscribe('imon_data', 'all', indicators,'id');
    template.subscribe('imon_indicators');
    template.subscribe('imon_countries');
  });
});

Template.IMonBarchartWidget.onRendered(function() {
  var template = this;
  var node = template.find('.barchart');
  var widgetNode = template.firstNode.parentNode.parentNode;
  var $widgetBody = $(widgetNode).find('.widget-body');
  //var mode = Template.currentData().mode;
  var chart = d3.select(node).chart('Compose', function(options) {
    var xs = _.pluck(options.data, 'x'), ys = _.pluck(options.data, 'y');

    var scales = options.mode === 'single'? {
      x: { domain: xs, type: 'ordinal', adjacent: true },
      y: { domain: [0, _.max(ys)] }
    } : {
      x: { domain: xs, type: 'ordinal', adjacent: true},
      y: { domain: [0, 100] }
    };

    var charts = [{
      type: 'Bars',
      id: 'bars',
      data: options.data,
      xScale: scales.x,
      yScale: scales.y,
      labels: {
        offset: 3
      }
    }];

    var title = d3c.title('Custom Chart');
    var xAxis = d3c.axis('xAxis', {scale: scales.x, ticks: 3});
    var yAxis = d3c.axis('yAxis', {scale: scales.y, ticks: 3});
    var xAxisTitle = d3c.axisTitle(options.xAxisTitle);
    var yAxisTitle = d3c.axisTitle(options.yAxisTitle);

    return [
      [yAxisTitle, yAxis, d3c.layered(charts)],
      xAxis,
      xAxisTitle
    ];
  });

  var setChartDims = function() {
    var width = $widgetBody.outerWidth() - Settings.chart.padding.right;
    var height = $widgetBody.outerHeight() - Settings.chart.padding.bottom;
    chart.width(width);
    chart.height(height);
  };

  $(widgetNode).on('gridster:resizestop', function() {
    setChartDims();
    chart.redraw();
  });

  var redrawn = false;
  template.autorun(function() {
    if (!template.subscriptionsReady()) { return; }
    var yIndicator;
    var xTitle;
    var yTitle;

    var data = [];
    var mode_reactive = Template.currentData().mode;
    if(mode_reactive === 'single'){
      yIndicator = Template.currentData().y.single.indicator;
      xTitle = 'Countries';
      yTitle = IMonIndicators.findOne({ id: yIndicator }).shortName;
      IMonCountries.find({ code: {$in: Template.currentData().x.single.indicator } }).forEach(function(country) {
        var y = IMonData.findOne({ countryCode: country.code, sourceId: yIndicator });
        if (_.isUndefined(y)) { return; }

        var xValue = country.name, yValue = y.value;

        data.push({
          x: xValue,
          y: yValue,
          code: country.code,
          key: country.code,
          label: yValue
        });
      });
    }
    else{
      yIndicator = Template.currentData().y.multi.indicator;
      yTitle = IMonCountries.findOne({ code: yIndicator }).name;
      IMonData.find({ countryCode: yIndicator, sourceId: { $in: Template.currentData().x.multi.indicator } }).forEach(function(field){
        var yValue = Math.round(field.percent * 100).toFixed(2);
        var xValue = IMonIndicators.findOne({ id: field.sourceId }).shortName;

        data.push({
          x: xValue,
          y: yValue,
          code: field.id,
          key: field.id,
          label: yValue
        });
      });
    }

    chart.margins(Settings.chart.margins);
    chart.responsive(false);

    chart.draw({
      data: data,
      mode: mode_reactive,
      xAxisTitle: xTitle,
      yAxisTitle: yTitle
    });

    // This is a hacky way to get the chart to fit the widget on first draw
    // because it wouldn't throw the draw event correctly.
    if (!redrawn) {
      setChartDims();
      chart.redraw();
      redrawn = true;
    }
  });
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

var path = require( 'path' )
var fs = require( 'fs' )
var prompt = require( 'inquirer' ).prompt
var readdir = require( 'readdirp' )
var config = require( 'npmconf' )
var lookup = require( 'dotty' )

var target = process.cwd()

function render( template, data ) {
  return template.replace(
    /\{\{([^\}]+)\}\}/g,
    function( _, selector ) {
      selector = selector.replace( /^\s+|\s+$/g, '' )
      return lookup.get( data, selector ) || ''
    }
  ).replace( /^\s+|\s+$/, '' ) + '\n'
}

function askQuestions( data, callback ) {

  var questions = prompt([{
    name: 'name',
    message: 'Module name',
    default: data.module.name
  },{
    name: 'prefix',
    type: 'input',
    message: 'Repository prefix',
    default: '',
    filter: function( input ) {
      return input && input.length ?
        input + '-' : ''
    },
  },{
    name: 'version',
    type: 'input',
    message: 'Version',
    default: data.module.version,
  },{
    name: 'description',
    type: 'input',
    message: 'Description',
    default: '',
  },{
    name: 'keywords',
    type: 'input',
    message: 'Keywords',
    default: '',
    filter: function( input ) {
      var words = !input || !input.length ? [] :
        input.replace( /^\s+|\s+$/g, '' ).split( /[,\s]+/g )
      return JSON.stringify( words )
    },
  },{
    name: 'license',
    type: 'list',
    message: 'License',
    default: data.module.licenseType,
    choices: [
      'MIT',
      'ISC',
      'BSD-3-Clause',
      'BSD-2-Clause',
      'GPL-3.0',
      'Apache-2.0',
      'Unlicense',
    ],
    filter: function( input ) {
      var filename = __dirname + '/../licenses/' + input + '.md'
      return {
        type: input,
        text: fs.readFileSync( filename, 'utf8' )
      }
    }
  },{
    name: 'main',
    type: 'input',
    message: 'Entry point',
    default: 'lib/'+data.module.name,
  },{
    name: 'test',
    type: 'input',
    message: 'Tests',
    default: 'echo \\"Error: no test specified\\" && exit 1',
  }])

  questions.then( function( results ) {

    data.module.name = results.name
    data.repo.prefix = results.prefix
    data.module.version = results.version
    data.module.description = results.description
    data.module.keywords = results.keywords
    data.module.licenseType = results.license.type
    data.module.main = results.main
    data.module.test = results.test

    data.module.license = render( results.license.text, data )

    callback( data )

  })

}

function writePackage( data, callback ) {

  var dirstream = readdir({
    root: __dirname + '/../templates',
  })

  dirstream.on( 'data', function( file ) {

    var dest = path.resolve( target, file.path )

    if( fs.existsSync( dest ) )
      return console.log( 'IGNORING', file.path )

    fs.readFile( file.fullPath, 'utf8', function( error, content ) {

      if( error != null )
        throw error

      content = render( content, data )

      if( /\.json$/i.test( file.name ) ) {
        content = JSON.stringify( JSON.parse( content ), null, 2 )
      }

      fs.writeFile( dest, content, function( error ) {
        if( error != null )
          throw error
      })

    })

  })

  // Write out .npmignore manually here,
  // because having it in the templates folder
  // causes dotfiles to be ignored (issue #1)
  dirstream.on( 'end', function() {

    var dest = path.resolve( target, '.npmignore' )
    // TODO: Add CI config files, such as 'appveyor.yml' (?)
    var npmignore = [
      '.*',
      '*.md',
      '*.log',
      'doc',
      'docs',
      'test',
      'example',
      'benchmark',
    ].join()

    // Don't overwrite existing .npmignore
    try { fs.statSync( dest ) } catch( error ) {
      fs.writeFileSync( dest, npmignore )
    }

  })

}

config.load( {}, function( error, npm ) {

  if( error != null )
    throw error

  var data = {
    date: {
      year: new Date().getFullYear()
    },
    author: {
      name: npm.get( 'init.author.name' ),
      url: npm.get( 'init.author.url' ),
      email: npm.get( 'init.author.email' ),
      github: npm.get( 'init.author.github' ),
    },
    module: {
      name: path.basename( target ),
      version: npm.get( 'init.version' ),
      licenseType: npm.get( 'init.license' ),
      license: '',
    },
    repo: {
      prefix: '',
    }
  }

  console.log( '' )
  askQuestions( data, writePackage )

})
<commit_msg>Update bin: Fix missing newlines in npmignore<commit_after>#!/usr/bin/env node

var path = require( 'path' )
var fs = require( 'fs' )
var prompt = require( 'inquirer' ).prompt
var readdir = require( 'readdirp' )
var config = require( 'npmconf' )
var lookup = require( 'dotty' )

var target = process.cwd()

function render( template, data ) {
  return template.replace(
    /\{\{([^\}]+)\}\}/g,
    function( _, selector ) {
      selector = selector.replace( /^\s+|\s+$/g, '' )
      return lookup.get( data, selector ) || ''
    }
  ).replace( /^\s+|\s+$/, '' ) + '\n'
}

function askQuestions( data, callback ) {

  var questions = prompt([{
    name: 'name',
    message: 'Module name',
    default: data.module.name
  },{
    name: 'prefix',
    type: 'input',
    message: 'Repository prefix',
    default: '',
    filter: function( input ) {
      return input && input.length ?
        input + '-' : ''
    },
  },{
    name: 'version',
    type: 'input',
    message: 'Version',
    default: data.module.version,
  },{
    name: 'description',
    type: 'input',
    message: 'Description',
    default: '',
  },{
    name: 'keywords',
    type: 'input',
    message: 'Keywords',
    default: '',
    filter: function( input ) {
      var words = !input || !input.length ? [] :
        input.replace( /^\s+|\s+$/g, '' ).split( /[,\s]+/g )
      return JSON.stringify( words )
    },
  },{
    name: 'license',
    type: 'list',
    message: 'License',
    default: data.module.licenseType,
    choices: [
      'MIT',
      'ISC',
      'BSD-3-Clause',
      'BSD-2-Clause',
      'GPL-3.0',
      'Apache-2.0',
      'Unlicense',
    ],
    filter: function( input ) {
      var filename = __dirname + '/../licenses/' + input + '.md'
      return {
        type: input,
        text: fs.readFileSync( filename, 'utf8' )
      }
    }
  },{
    name: 'main',
    type: 'input',
    message: 'Entry point',
    default: 'lib/'+data.module.name,
  },{
    name: 'test',
    type: 'input',
    message: 'Tests',
    default: 'echo \\"Error: no test specified\\" && exit 1',
  }])

  questions.then( function( results ) {

    data.module.name = results.name
    data.repo.prefix = results.prefix
    data.module.version = results.version
    data.module.description = results.description
    data.module.keywords = results.keywords
    data.module.licenseType = results.license.type
    data.module.main = results.main
    data.module.test = results.test

    data.module.license = render( results.license.text, data )

    callback( data )

  })

}

function writePackage( data, callback ) {

  var dirstream = readdir({
    root: __dirname + '/../templates',
  })

  dirstream.on( 'data', function( file ) {

    var dest = path.resolve( target, file.path )

    if( fs.existsSync( dest ) )
      return console.log( 'IGNORING', file.path )

    fs.readFile( file.fullPath, 'utf8', function( error, content ) {

      if( error != null )
        throw error

      content = render( content, data )

      if( /\.json$/i.test( file.name ) ) {
        content = JSON.stringify( JSON.parse( content ), null, 2 )
      }

      fs.writeFile( dest, content, function( error ) {
        if( error != null )
          throw error
      })

    })

  })

  // Write out .npmignore manually here,
  // because having it in the templates folder
  // causes dotfiles to be ignored (issue #1)
  dirstream.on( 'end', function() {

    var dest = path.resolve( target, '.npmignore' )
    // TODO: Add CI config files, such as 'appveyor.yml' (?)
    var npmignore = [
      '.*',
      '*.md',
      '*.log',
      'doc',
      'docs',
      'test',
      'example',
      'benchmark',
    ].join( '\n' ) + '\n'

    // Don't overwrite existing .npmignore
    try { fs.statSync( dest ) } catch( error ) {
      fs.writeFileSync( dest, npmignore )
    }

  })

}

config.load( {}, function( error, npm ) {

  if( error != null )
    throw error

  var data = {
    date: {
      year: new Date().getFullYear()
    },
    author: {
      name: npm.get( 'init.author.name' ),
      url: npm.get( 'init.author.url' ),
      email: npm.get( 'init.author.email' ),
      github: npm.get( 'init.author.github' ),
    },
    module: {
      name: path.basename( target ),
      version: npm.get( 'init.version' ),
      licenseType: npm.get( 'init.license' ),
      license: '',
    },
    repo: {
      prefix: '',
    }
  }

  console.log( '' )
  askQuestions( data, writePackage )

})
<|endoftext|>


<commit_before>'use strict';

/* SDK Modules */
const ss = require('sdk/simple-storage');

/* Modules */
const chromecast = require('chromecast.js').NewTabChromecast;
const logger = require('logger.js').NewTabLogger;
const utils = require('utils.js').NewTabUtils;
var newtab; //load on initialization to ensure main module is loaded

/* Constants */
//messages
const IMAGES_DISPLAY_MSG = 'images_display';
//simple storage
const IMAGES_CHOSEN_ID_SS = 'images_chosen_id';
const IMAGES_FALLBACK_ID_SS = 'images_fallback_id';
const IMAGES_LASTCHOSEN_SS = 'images_lastchosen';
const IMAGES_LASTUPDATED_SS = 'images_lastupdated';
const IMAGES_METADATA_SS = 'images_metadata';
//others
const IMAGES_CHOOSE_INTERVAL_MILLIS = 60 * 1000; //1 minute
const IMAGES_FALLBACKS = ['images/0.jpg', 'images/1.jpg', 'images/2.jpg',
                          'images/3.jpg', 'images/4.jpg', 'images/5.jpg',
                          'images/6.jpg', 'images/7.jpg', 'images/8.jpg',
                          'images/9.jpg', 'images/10.jpg'];
const IMAGES_NUM_PER_UPDATE = 15;
const IMAGES_UPDATE_INTERVAL_MILLIS = 24 * 60 * 60 * 1000; //24 hours
const IMAGES_UPDATE_WAIT_MILLIS = 50 * 1000; //10 seconds

/**
 * Images module.
 */
 var NewTabImages = {

    /**
     * Initializes images by requesting new images (if needed), saving them
     * to disk, and sending a random image to the content scripts.
     */
    initImages: function(worker) {
        newtab = require('main.js').NewTabMain;
        logger.log('Initializing images.');

        //immediately display an image
        NewTabImages.displayImage(worker);

        //request new images
        if(NewTabImages.shouldUpdate()) {
            NewTabImages.getImages(worker).
                then(NewTabImages.displayImage).
                then(null, logger.error);
        }
    },

    /**
     * Choose an image and notifies content scripts to display it.
     */
     displayImage: function(worker) {
        var image = NewTabImages.getSavedImage();
        image.fallback = NewTabImages.getFallbackImage();
        if(image) {
            utils.emit(newtab.workers, worker, IMAGES_DISPLAY_MSG, image);
        }
     },

     /**
      * Chooses and displays an image that is different from the current image.
      */
    displayNextImage: function(worker) {
        //force a new image to be chosen, but don't delete the current chosen
        //image id as it is needed to cycle the next image
        ss.storage[IMAGES_LASTCHOSEN_SS] = null;
        NewTabImages.displayImage(worker);
    },

    /**
     * Clears chosen image.
     */
    clearChosenImage: function() {
        ss.storage[IMAGES_CHOSEN_ID_SS] = null;
        ss.storage[IMAGES_LASTCHOSEN_SS] = null;
    },

    /**
     * Returns one of the saved images to display.
     */
    getSavedImage: function() {
        //no image displayed
        var lastChosen = ss.storage[IMAGES_LASTCHOSEN_SS];
        var chosenId = ss.storage[IMAGES_CHOSEN_ID_SS];
        if(!lastChosen || !chosenId) {
            chosenId = NewTabImages.getNewImageId();
        } else {
            //check when the last image was chosen
            var now = Date.now();
            var elapsed = now - lastChosen;
            //choose new image
            if(elapsed >= IMAGES_CHOOSE_INTERVAL_MILLIS) {
                chosenId = NewTabImages.getNewImageId();
            }
        }
        return ss.storage[IMAGES_METADATA_SS][chosenId];
    },

    /**
     * Chooses a new image to be displayed and returns its id.
     */
    getNewImageId: function() {
        logger.log('Choosing new image.');
        var images = ss.storage[IMAGES_METADATA_SS];
        if(!images) {
            NewTabImages.clearChosenImage();
            return null;
        }
        var chosenId = ss.storage[IMAGES_CHOSEN_ID_SS];
        //choose next image or choose a random image if this is the first
        //time choosing
        chosenId = chosenId ? (parseInt(chosenId, 10) + 1) % images.length
            : Math.floor(Math.random() * images.length);
        ss.storage[IMAGES_CHOSEN_ID_SS] = chosenId.toString();
        ss.storage[IMAGES_LASTCHOSEN_SS] = Date.now();
        return chosenId;
    },

    /**
     * Returns a fallback image to be displayed in case the original image
     * fails to load.
     */
    getFallbackImage: function() {
        var fallbackId = ss.storage[IMAGES_FALLBACK_ID_SS];
        fallbackId = fallbackId ? (parseInt(fallbackId, 10) + 1) % IMAGES_FALLBACKS.length
            : Math.floor(Math.random() * IMAGES_FALLBACKS.length);
        ss.storage[IMAGES_FALLBACK_ID_SS] = fallbackId.toString();
        return IMAGES_FALLBACKS[fallbackId];
    },

    /**
     * Returns whether new images should be requested.
     */
    shouldUpdate: function() {
        //no images exist
        var lastUpdated = ss.storage[IMAGES_LASTUPDATED_SS];
        if(!lastUpdated) {
            return true;
        }

        //check when the images were last updated
        var now = Date.now();
        var elapsed = now - lastUpdated;

        return (elapsed >= IMAGES_UPDATE_INTERVAL_MILLIS);
    },

    /**
     * Returns a promise that is fulfilled with the images requested from
     * the image sources.
     */
    getImages: function(worker) {
        logger.log('Requesting images.');
        //set last updated time to in the future so no other updates will
        //happen during this update
        ss.storage[IMAGES_LASTUPDATED_SS] = Date.now() + IMAGES_UPDATE_WAIT_MILLIS;
        //clear current chosen image
        NewTabImages.clearChosenImage();
        //request images
        return chromecast.getImages(IMAGES_NUM_PER_UPDATE).
            then(function(images) {
                //save images
                ss.storage[IMAGES_METADATA_SS] = images;
                ss.storage[IMAGES_LASTUPDATED_SS] = Date.now();
                return worker;
            });
    }
 };

exports.NewTabImages = NewTabImages;
<commit_msg>Tweak image choosing behavior so that it always starts with the first image instead of starting with a random one<commit_after>'use strict';

/* SDK Modules */
const ss = require('sdk/simple-storage');

/* Modules */
const chromecast = require('chromecast.js').NewTabChromecast;
const logger = require('logger.js').NewTabLogger;
const utils = require('utils.js').NewTabUtils;
var newtab; //load on initialization to ensure main module is loaded

/* Constants */
//messages
const IMAGES_DISPLAY_MSG = 'images_display';
//simple storage
const IMAGES_CHOSEN_ID_SS = 'images_chosen_id';
const IMAGES_FALLBACK_ID_SS = 'images_fallback_id';
const IMAGES_LASTCHOSEN_SS = 'images_lastchosen';
const IMAGES_LASTUPDATED_SS = 'images_lastupdated';
const IMAGES_METADATA_SS = 'images_metadata';
//others
const IMAGES_CHOOSE_INTERVAL_MILLIS = 60 * 1000; //1 minute
const IMAGES_FALLBACKS = ['images/0.jpg', 'images/1.jpg', 'images/2.jpg',
                          'images/3.jpg', 'images/4.jpg', 'images/5.jpg',
                          'images/6.jpg', 'images/7.jpg', 'images/8.jpg',
                          'images/9.jpg', 'images/10.jpg'];
const IMAGES_NUM_PER_UPDATE = 15;
const IMAGES_UPDATE_INTERVAL_MILLIS = 24 * 60 * 60 * 1000; //24 hours
const IMAGES_UPDATE_WAIT_MILLIS = 50 * 1000; //10 seconds

/**
 * Images module.
 */
 var NewTabImages = {

    /**
     * Initializes images by requesting new images (if needed), saving them
     * to disk, and sending a random image to the content scripts.
     */
    initImages: function(worker) {
        newtab = require('main.js').NewTabMain;
        logger.log('Initializing images.');

        //immediately display an image
        NewTabImages.displayImage(worker);

        //request new images
        if(NewTabImages.shouldUpdate()) {
            NewTabImages.getImages(worker).
                then(NewTabImages.displayImage).
                then(null, logger.error);
        }
    },

    /**
     * Choose an image and notifies content scripts to display it.
     */
    displayImage: function(worker) {
        var image = NewTabImages.getSavedImage();
        image.fallback = NewTabImages.getFallbackImage();
        if(image) {
            utils.emit(newtab.workers, worker, IMAGES_DISPLAY_MSG, image);
        }
     },

     /**
      * Chooses and displays an image that is different from the current image.
      */
    displayNextImage: function(worker) {
        clearChosenImage();
        NewTabImages.displayImage(worker);
    },

    /**
     * Clears chosen image.
     */
    clearChosenImage: function() {
        ss.storage[IMAGES_LASTCHOSEN_SS] = null;
    },

    /**
     * Returns one of the saved images to display.
     */
    getSavedImage: function() {
        //no image displayed
        var lastChosen = ss.storage[IMAGES_LASTCHOSEN_SS];
        var chosenId = ss.storage[IMAGES_CHOSEN_ID_SS];
        if(!lastChosen || !chosenId) {
            return NewTabImages.getNewImage();
        } else {
            //check when the last image was chosen
            var now = Date.now();
            var elapsed = now - lastChosen;
            //choose new image
            if(elapsed >= IMAGES_CHOOSE_INTERVAL_MILLIS) {
                return NewTabImages.getNewImage();
            }
        }
        return ss.storage[IMAGES_IMAGE_SET_SS][chosenId];
    },

    /**
     * Chooses and returns a new image to be displayed.
     */
    getNewImage: function() {
        logger.log('Choosing new image.');
        var imageSet = ss.storage[IMAGES_IMAGE_SET_SS];
        if(!imageSet || !imageSet.images) {
            return null;
        }
        var images = imageSet.images;
        var chosenId = ss.storage[IMAGES_CHOSEN_ID_SS];
        chosenId = chosenId ? (parseInt(chosenId, 10) + 1) % images.length : 0;
        ss.storage[IMAGES_CHOSEN_ID_SS] = chosenId.toString();
        ss.storage[IMAGES_LASTCHOSEN_SS] = Date.now();
        return ss.storage[IMAGES_IMAGE_SET_SS][chosenId];
    },

    /**
     * Returns a fallback image to be displayed in case the original image
     * fails to load.
     */
    getFallbackImage: function() {
        var fallbackId = ss.storage[IMAGES_FALLBACK_ID_SS];
        fallbackId = fallbackId ? (parseInt(fallbackId, 10) + 1) % IMAGES_FALLBACKS.length : 0;
        ss.storage[IMAGES_FALLBACK_ID_SS] = fallbackId.toString();
        return IMAGES_FALLBACKS[fallbackId];
    },

    /**
     * Returns whether new images should be requested.
     */
    shouldUpdate: function() {
        //no images exist
        var lastUpdated = ss.storage[IMAGES_LASTUPDATED_SS];
        if(!lastUpdated) {
            return true;
        }

        //check when the images were last updated
        var now = Date.now();
        var elapsed = now - lastUpdated;

        return (elapsed >= IMAGES_UPDATE_INTERVAL_MILLIS);
    },

    /**
     * Returns a promise that is fulfilled with the images requested from
     * the image sources.
     */
    getImages: function(worker) {
        logger.log('Requesting images.');
        //set last updated time to in the future so no other updates will
        //happen during this update
        ss.storage[IMAGES_LASTUPDATED_SS] = Date.now() + IMAGES_UPDATE_WAIT_MILLIS;
        //clear current chosen image
        NewTabImages.clearChosenImage();
        //request images
        return chromecast.getImages(IMAGES_NUM_PER_UPDATE).
            then(function(images) {
                //save images
                ss.storage[IMAGES_METADATA_SS] = images;
                ss.storage[IMAGES_LASTUPDATED_SS] = Date.now();
                return worker;
            });
    }
 };

exports.NewTabImages = NewTabImages;
<|endoftext|>