<commit_before>const {
  FuseBox,
  Sparky,
  CSSPlugin,
  CopyPlugin,
  EnvPlugin,
} = require('fuse-box');
const { spawn } = require('child_process');

const DEV_PORT = 4444;
const ASSETS = ['*.jpg', '*.png', '*.jpeg', '*.gif', '*.svg'];

const isProduction = process.env.NODE_ENV === 'production';

// Copy the renderer html file to dist
Sparky.task('copy-html', () => {
  return Sparky.src('src/renderer/index.html').dest('dist/$name');
});

Sparky.task('default', ['copy-html'], () => {
  const fuse = FuseBox.init({
    homeDir: 'src/',
    output: 'dist/$name.js',
    target: 'electron',
    log: isProduction,
    hash: isProduction,
    cache: !isProduction,
    sourceMaps: !isProduction,
    tsConfig: 'tsconfig.json',
    shim: {
      electron: { exports: "global.require('electron')" },
    },
    plugins: [
      EnvPlugin({ NODE_ENV: isProduction ? 'production' : 'development' }),
    ]
  });

  // Start the hot-reload server
  if (!isProduction) {
    fuse.dev({ port: DEV_PORT, httpServer: false });
  }

  // Bundle main electron code
  const appBundle = fuse.bundle('app').instructions('> [index.ts]');

  // Watch
  if (!isProduction) {
    appBundle.watch();
  }

  // Bundle electron renderer code
  const rendererBundle = fuse
    .bundle('renderer')
    .instructions('> [renderer/index.tsx] +fuse-box-css')
    .plugin(CSSPlugin())
    .plugin(CopyPlugin({
        useDefault: false,
        files: ASSETS,
        dest: 'assets',
        resolve: 'assets/',
    }));

  // Watch and hot-reload
  if (!isProduction) {
    rendererBundle.watch();
    rendererBundle.hmr();
  }

  return fuse.run().then(() => {
    if (!isProduction) {
      spawn('node', [`${__dirname}/node_modules/electron/cli.js`, __dirname], {
        stdio: 'inherit',
      });
    }
  });
});

Sparky.task('clean', () => {
  return Sparky.src('dist/*').clean('dist/');
});
<commit_msg>Add bundle task<commit_after>const {
  FuseBox,
  Sparky,
  CSSPlugin,
  CopyPlugin,
  EnvPlugin,
} = require('fuse-box');
const { spawn } = require('child_process');

const DEV_PORT = 4444;
const ASSETS = ['*.jpg', '*.png', '*.jpeg', '*.gif', '*.svg'];

const isProduction = process.env.NODE_ENV === 'production';

// Copy the renderer html file to dist
Sparky.task('copy-html', () => {
  return Sparky.src('src/renderer/index.html').dest('dist/$name');
});

const fuse = FuseBox.init({
  homeDir: 'src/',
  output: 'dist/$name.js',
  target: 'electron',
  log: isProduction,
  hash: isProduction,
  cache: !isProduction,
  sourceMaps: !isProduction,
  tsConfig: 'tsconfig.json',
  shim: {
    electron: { exports: "global.require('electron')" },
  },
  plugins: [
    EnvPlugin({ NODE_ENV: isProduction ? 'production' : 'development' }),
  ]
});

function bundle() {
    // Bundle main electron code
    const appBundle = fuse.bundle('app').instructions('> [index.ts]');

    // Bundle electron renderer code
    const rendererBundle = fuse
    .bundle('renderer')
    .instructions('> [renderer/index.tsx] +fuse-box-css')
    .plugin(CSSPlugin())
    .plugin(CopyPlugin({
        useDefault: false,
        files: ASSETS,
        dest: 'assets',
        resolve: 'assets/',
    }));

    return {
      appBundle,
      rendererBundle,
    };
}

Sparky.task('bundle', ['copy-html'], () => {
  bundle();
  fuse.run();
});

Sparky.task('default', ['copy-html'], () => {
  // Start the hot-reload server
  if (!isProduction) {
    fuse.dev({ port: DEV_PORT, httpServer: false });
  }

  const { appBundle, rendererBundle } = bundle();

  // Watch and hot-reload
  if (!isProduction) {
    appBundle.watch();

    rendererBundle.watch();
    rendererBundle.hmr();
  }

  return fuse.run().then(() => {
    if (!isProduction) {
      spawn('node', [`${__dirname}/node_modules/electron/cli.js`, __dirname], {
        stdio: 'inherit',
      });
    }
  });
});

Sparky.task('clean', () => {
  return Sparky.src('dist/*').clean('dist/');
});
<|endoftext|>


<commit_before>/*
	Load.js - JavaScript js/css, jsonp/ajax, sync/async loader
	Docs and source: https://github.com/articobandurini/load.js
	Distributed under MIT license.
*/
(function(b){var a=b.load=function(d){if(typeof d!=="object"||d instanceof Array){var c=a.args(arguments);d={url:c.url,callback:c.callback}}if(d.url&&d.url.length){if(typeof d.async==="undefined"){d.async=true}if(!d.type){d.type="js"}if(!(d.url instanceof Array)){d.url=[d.url]}a.sequence(d)}return a};a.sequence=function(e){var d=e.url.length,c=function(h){if(!h){h=1}d=d-h;if(!d&&typeof e.callback==="function"){e.callback.call(a)}},g=function(h){return h.length?(function(){c(h.length);a.sequence({url:h,async:e.async,type:e.type,callback:c})}):c};for(var f=0;f<e.url.length;f++){if(e.url[f] instanceof Array){a.sequence({url:e.url[f],async:e.async,type:e.type,callback:g(e.url.slice(f+1))});break}else{a.one({url:e.url[f],async:e.async,type:e.type,callback:c})}}return a};a.one=function(d){var c,f=false,e=document.getElementsByTagName("head")[0]||document.body;if(d.type==="css"||d.url.toLowerCase().match(/\.css$/)){f=true;c=document.createElement("link");c.rel="stylesheet";c.href=a.path(d.url+(d.url.toLowerCase().match(/\.css$/)?"":".css"))}else{c=document.createElement("script");c.async=d.async;c.src=a.path(d.url+(d.type==="jsonp"||d.url.toLowerCase().match(/\.js$/)?"":".js"))}e.appendChild(c);var g=function(h){if(typeof a.ready==="function"){a.ready.call(a,d.url)}if(typeof d.callback==="function"){d.callback.call(a)}if(!f&&h&&h.parentNode){h.parentNode.removeChild(h)}};if(navigator.userAgent.indexOf("MSIE")>=0){c.onreadystatechange=function(){if(this.readyState==="loaded"||this.readyState==="complete"){g(this)}}}else{c.onload=function(){g(this)}}return a};a.js=a.async=function(){var c=a.args(arguments);return a({url:c.url,callback:c.callback})};a.css=function(){var c=a.args(arguments);return a({url:c.url,callback:c.callback,type:"css"})};a.sync=function(){var c=a.args(arguments);return a({url:c.url,callback:c.callback,async:false})};a.jsonp=function(c,e,d){if(typeof e==="function"){if(!a.jsonp.index){a.jsonp.index=1}else{a.jsonp.index++}window["loadCallback"+a.jsonp.index]=e;c=c.replace("=?","=loadCallback"+a.jsonp.index)}return a.one({url:c,async:d!==false,type:"jsonp"})};a.ajax=function(c,h,d){var g;if(window.XMLHttpRequest){g=new XMLHttpRequest()}else{if(window.ActiveXObject){try{g=new ActiveXObject("Msxml2.XMLHTTP")}catch(f){try{g=new ActiveXObject("Microsoft.XMLHTTP")}catch(f){}}}}if(!g){return null}g.onreadystatechange=function(){if(g.readyState===4&&typeof h==="function"){h.call(g,g.responseText)}};g.open("GET",a.path(c),d);g.send();return a};a.args=function(c){var d=Array.prototype.slice.call(c);return{url:d,callback:(typeof d[d.length-1]==="function")?d.pop():undefined}};a.path=function(c){return c.match(/^(https?\:|file\:|\/)/i)?c:a.root+c};a.init=function(){a.root="";var f=document.getElementsByTagName("script"),d,e;for(var c=0;c<f.length;c++){if(f[c].src.match(/(^|\/)load(\.min)?\.js$/)){d=f[c].getAttribute("data-load");if(d){e=d.lastIndexOf("/")+1;a.root=e?d.substring(0,e):"";a({url:d.substring(e),async:f[c].getAttribute("data-async")!=="false"})}break}}};a.init()})(window);
<commit_msg>update minified version<commit_after>/*
	Load.js - JavaScript js/css, jsonp/ajax, sync/async loader
	Docs and source: https://github.com/articobandurini/load.js
	Distributed under MIT license.
*/
(function(b){var a=b.load=function(d){if(typeof d!=="object"||d instanceof Array){var c=a.args(arguments);d={url:c.url,callback:c.callback}}if(d.url&&d.url.length){if(typeof d.async==="undefined"){d.async=true}if(!d.type){d.type="js"}if(!(d.url instanceof Array)){d.url=[d.url]}a.sequence(d)}return a};a.sequence=function(e){var d=e.url.length,c=function(h){if(!h){h=1}d=d-h;if(!d&&typeof e.callback==="function"){e.callback.call(a)}},g=function(h){return h.length?(function(){c(h.length);a.sequence({url:h,async:e.async,type:e.type,callback:c})}):c};for(var f=0;f<e.url.length;f++){if(e.url[f] instanceof Array){a.sequence({url:e.url[f],async:e.async,type:e.type,callback:g(e.url.slice(f+1))});break}else{a.one({url:e.url[f],async:e.async,type:e.type,callback:c})}}return a};a.one=function(d){var c,f=false,e=document.getElementsByTagName("head")[0]||document.body;if(d.type==="css"||d.url.toLowerCase().match(/\.css$/)){f=true;c=document.createElement("link");c.rel="stylesheet";c.href=a.path(d.url+(d.url.toLowerCase().match(/\.css$/)?"":".css"))}else{c=document.createElement("script");c.async=d.async;c.src=a.path(d.url+(d.type==="jsonp"||d.url.toLowerCase().match(/\.js$/)?"":".js"))}e.appendChild(c);var g=function(h){if(typeof a.ready==="function"){a.ready.call(a,d.url)}if(typeof d.callback==="function"){d.callback.call(a)}if(!f&&h&&h.parentNode){h.parentNode.removeChild(h)}};if(navigator.userAgent.indexOf("MSIE")>=0){c.onreadystatechange=function(){if(this.readyState==="loaded"||this.readyState==="complete"){g(this)}}}else{c.onload=function(){g(this)}}if(typeof d.errorHandler==="function"){c.onerror=function(h){d.errorHandler.call(a,h)}}return a};a.js=a.async=function(){var c=a.args(arguments);return a({url:c.url,callback:c.callback})};a.css=function(){var c=a.args(arguments);return a({url:c.url,callback:c.callback,type:"css"})};a.sync=function(){var c=a.args(arguments);return a({url:c.url,callback:c.callback,async:false})};a.jsonp=function(d,f,e,c){if(typeof f==="function"){if(!a.jsonp.index){a.jsonp.index=1}else{a.jsonp.index++}window["loadCallback"+a.jsonp.index]=f;d=d.replace("=?","=loadCallback"+a.jsonp.index)}return a.one({url:d,async:e!==false,type:"jsonp",errorHandler:c})};a.ajax=function(d,i,f,c){var h;if(window.XMLHttpRequest){h=new XMLHttpRequest()}else{if(window.ActiveXObject){try{h=new ActiveXObject("Msxml2.XMLHTTP")}catch(g){try{h=new ActiveXObject("Microsoft.XMLHTTP")}catch(g){}}}}if(!h){return null}h.onreadystatechange=function(){if(h.readyState===4&&typeof i==="function"){i.call(h,h.responseText)}};if(typeof c==="function"){h.onerror=function(j){c.call(a,j)}}h.open("GET",a.path(d),f);h.send();return a};a.args=function(c){var d=Array.prototype.slice.call(c);return{url:d,callback:(typeof d[d.length-1]==="function")?d.pop():undefined}};a.path=function(c){return c.match(/^(https?\:|file\:|\/)/i)?c:a.root+c};a.init=function(){a.root="";var f=document.getElementsByTagName("script"),d,e;for(var c=0;c<f.length;c++){if(f[c].src.match(/(^|\/)load(\.min)?\.js$/)||f[c].id==="load.js"){d=f[c].getAttribute("data-load");if(d){e=d.lastIndexOf("/")+1;a.root=e?d.substring(0,e):"";a({url:d.substring(e),async:f[c].getAttribute("data-async")!=="false"})}break}}};a.init()})(window);
<|endoftext|>


<commit_before>import * as nodes from '../../../networks/types';
import store from 'store';
import derivationPaths from './derivationPaths';

function getDerivationPath(networkName) {
  if (!networkName) {
    if (store.get('network') !== undefined) {
      networkName = store.get('network').type.name;
    }
  }
  if (paths[networkName]) {
    return {
      dpath: derivationPaths[networkName],
      label: derivationPaths[networkName].name_long
    };
  }
  return {
    dpath: derivationPaths[nodes.ETH.name],
    label: nodes[nodes.ETH.name].name_long
  };
}

function buildPathsObject() {
  const paths = {};

  Object.keys(derivationPaths).forEach(key => {
    paths[derivationPaths[key]] = {
      dpath: derivationPaths[key],
      label: nodes[key].name_long
    };
  });
  return paths;
}

const paths = buildPathsObject();

export { paths, getDerivationPath };
<commit_msg>FIX: bug with default paths<commit_after>import * as nodes from '../../../networks/types';
import store from 'store';
import derivationPaths from './derivationPaths';

function getDerivationPath(networkName) {
  if (!networkName) {
    if (store.get('network') !== undefined) {
      networkName = store.get('network').type.name;
    }
  }
  if (paths[networkName]) {
    return {
      dpath: derivationPaths[networkName],
      label: derivationPaths[networkName].name_long
    };
  }
  return {
    dpath: derivationPaths[nodes.ETH.name],
    label: nodes[nodes.ETH.name].name_long
  };
}

function buildPathsObject() {
  const paths = {};

  Object.keys(derivationPaths).forEach(key => {
    paths[key] = {
      dpath: derivationPaths[key],
      label: nodes[key].name_long
    };
  });
  return paths;
}

const paths = buildPathsObject();

export { paths, getDerivationPath };
<|endoftext|>


<commit_before>var
    expect = require('chai').expect,
    sinon = require('sinon'),
    lodown = require('../index'),
    customers = require('./fixtures/customers.json');

describe('lodown', function() {
    describe('each', function() {
        it('should iterate an Array, applying action to each element, index of the element, and the collection', function() {
            var action = sinon.spy();
            lodown.each(customers, action);
            expect(action.callCount).to.equal(customers.length);
            customers.forEach(function(customer, index){
               expect(action.calledWith(customer, index, customers)).to.be.true;
            });
        });

        it('should iterate an Object, applying action for each value, key of value, and Object', function() {
            var action = sinon.spy();
            var customer = customers[0];
            lodown.each(customer, action);
            expect(action.callCount).to.equal(Object.keys(customer).length);
            for(var key in customer) {
              expect(action.calledWith(customer[key], key, customer)).to.be.true;
            }
        });
    });

    describe('filter', function() {
        it('filter should filter Array items based on test provided', function () {
            expect(lodown.filter([1, 2, 3], function(value) { return value > 2; } )).to.eql([3]);
        });
        it('filter should filter Object values based on test provided', function() {
            expect(lodown.filter({one: 'one', two: 'two', three: 'three'}, function(value) { return value[0] === 't' })).to.eql(['two', 'three']);
        });
    });

    describe('map', function() {
        it('map should create an Array of transformations for each value in an Array', function () {
            expect(lodown.map([1, 2, 3], function(value) { return value + 1; } )).to.eql([2, 3, 4]);
        });
        it('map should create an Array of transformations for each value in an Object', function() {
            expect(lodown.map({one: 'one', two: 'two', three: 'three'}, function(value) { return value.toUpperCase(); })).to.eql(['ONE', 'TWO', 'THREE']);
        });
    });

    describe("identity", function() {
        it('identity should return the value passed to it, including types Number, String, Boolean, Array, Object, Function', function(){
            expect(lodown.identity(1)).to.equal(1);
            expect(lodown.identity('identity')).to.equal('identity');
            expect(lodown.identity({a: "one"})).to.eql({a: "one"});
            expect(lodown.identity([1,2,3])).to.eql([1,2,3]);
            var fn = function() {  };
            expect(lodown.identity(fn)).to.eql(fn);
        });
    });
});<commit_msg>* update ld l.spec.js<commit_after>var
    expect = require('chai').expect,
    sinon = require('sinon'),
    lodown = require('../../index'),
    customers = require('./fixtures/customers.json');

describe('lodown', function() {
    describe('each', function() {
        it('should iterate an Array, applying action to each element, index of the element, and the collection', function() {
            var action = sinon.spy();
            lodown.each(customers, action);
            expect(action.callCount).to.equal(customers.length);
            customers.forEach(function(customer, index){
               expect(action.calledWith(customer, index, customers)).to.be.true;
            });
        });

        it('should iterate an Object, applying action for each value, key of value, and Object', function() {
            var action = sinon.spy();
            var customer = customers[0];
            lodown.each(customer, action);
            expect(action.callCount).to.equal(Object.keys(customer).length);
            for(var key in customer) {
              expect(action.calledWith(customer[key], key, customer)).to.be.true;
            }
        });
    });

    describe('filter', function() {
        it('filter should filter Array items based on test provided', function () {
            expect(lodown.filter([1, 2, 3], function(value) { return value > 2; } )).to.eql([3]);
        });
        it('filter should filter Object values based on test provided', function() {
            expect(lodown.filter({one: 'one', two: 'two', three: 'three'}, function(value) { return value[0] === 't' })).to.eql(['two', 'three']);
        });
    });

    describe('map', function() {
        it('map should create an Array of transformations for each value in an Array', function () {
            expect(lodown.map([1, 2, 3], function(value) { return value + 1; } )).to.eql([2, 3, 4]);
        });
        it('map should create an Array of transformations for each value in an Object', function() {
            expect(lodown.map({one: 'one', two: 'two', three: 'three'}, function(value) { return value.toUpperCase(); })).to.eql(['ONE', 'TWO', 'THREE']);
        });
    });

    describe("identity", function() {
        it('identity should return the value passed to it, including types Number, String, Boolean, Array, Object, Function', function(){
            expect(lodown.identity(1)).to.equal(1);
            expect(lodown.identity('identity')).to.equal('identity');
            expect(lodown.identity({a: "one"})).to.eql({a: "one"});
            expect(lodown.identity([1,2,3])).to.eql([1,2,3]);
            var fn = function() {  };
            expect(lodown.identity(fn)).to.eql(fn);
        });
    });
});<|endoftext|>


<commit_before>var list = [
  {
    "dir_name": "chart.js-test",
    "files": [
      "bar.html",
      "doughnut.html",
      "line.html",
      "pie.html",
      "radar.html"
    ]
  },
  {
    "dir_name": "check-num-only",
    "files": [
      "index.html"
    ]
  },
  {
    "dir_name": "google-maps-api-test",
    "files": [
      "index.html",
      "utf8.html"
    ]
  },
  {
    "dir_name": "particle-universe",
    "files": [
      "index.html"
    ]
  },
  {
    "dir_name": "start-javascript",
    "files": [
      "numgame/index.html",
      "omikuji/index.html",
      "slotmachine/index.html",
      "stoptime/index.html",
      "stopwatch/index.html",
      "timejs/index.html",
      "warikandentaku/index.html"
    ]
  },
  {
    "dir_name": "kaomoji-javascript",
    "files": [
      "index.html"
    ]
  },
  {
    "dir_name": "stickybox",
    "files": [
      "index.html"
    ]
  },
  {
    "dir_name": "table-total-sum",
    "files": [
      "index.html"
    ]
  },
  {
    "dir_name": "wow-animate",
    "files": [
      "index.html"
    ]
  },
  {
    "dir_name": "yubinbango",
    "files": [
      "index.html",
      "ajaxzip3.html"
    ]
  }
]
<commit_msg>add highlight.js list<commit_after>var list = [
  {
    "dir_name": "chart.js-test",
    "files": [
      "bar.html",
      "doughnut.html",
      "line.html",
      "pie.html",
      "radar.html"
    ]
  },
  {
    "dir_name": "check-num-only",
    "files": [
      "index.html"
    ]
  },
  {
    "dir_name": "google-maps-api-test",
    "files": [
      "index.html",
      "utf8.html"
    ]
  },
  {
    "dir_name": "highlight.js",
    "files": [
      "index.html",
    ]
  },
  {
    "dir_name": "particle-universe",
    "files": [
      "index.html"
    ]
  },
  {
    "dir_name": "start-javascript",
    "files": [
      "numgame/index.html",
      "omikuji/index.html",
      "slotmachine/index.html",
      "stoptime/index.html",
      "stopwatch/index.html",
      "timejs/index.html",
      "warikandentaku/index.html"
    ]
  },
  {
    "dir_name": "kaomoji-javascript",
    "files": [
      "index.html"
    ]
  },
  {
    "dir_name": "stickybox",
    "files": [
      "index.html"
    ]
  },
  {
    "dir_name": "table-total-sum",
    "files": [
      "index.html"
    ]
  },
  {
    "dir_name": "wow-animate",
    "files": [
      "index.html"
    ]
  },
  {
    "dir_name": "yubinbango",
    "files": [
      "index.html",
      "ajaxzip3.html"
    ]
  }
]
<|endoftext|>


<commit_before>/*==================================================
 *  Exhibit.JSONPImporter
 *==================================================
 */

Exhibit.JSONPImporter = {
    _callbacks: {}
};
Exhibit.importers["application/jsonp"] = Exhibit.JSONPImporter;

// cont gets called with the original feed (so you can pick up details from the
// feed from user code that were of interest to you but not the exhibit itself,
// for instance). load returns the callback that the JSONP payload should call,
// so that even partial static JSONP implementations (with a fixed callback
// name) can assign that variable with the return value, and things will
// work out, as much as they can (i e concurrent requests can get mixed up).
Exhibit.JSONPImporter.load = function(
    link, database, cont, fConvert, staticJSONPCallback, charset
) {
    var url = link;
    if (typeof link != "string") {
        url = Exhibit.Persistence.resolveURL(link.href);
        fConvert = Exhibit.getAttribute(link, "converter");
        staticJSONPCallback = Exhibit.getAttribute(link, "jsonp-callback");
        charset = Exhibit.getAttribute(link, "charset");
    }
    if (typeof fConvert == "string") {
        var name = fConvert;
        name = name.charAt(0).toLowerCase() + name.substring(1) + "Converter";
        if (name in Exhibit.JSONPImporter) {
            fConvert = Exhibit.JSONPImporter[name];
        } else {
            try {
                fConvert = eval(fConvert);
            } catch (e) {
                fConvert = null;
                // silent
            }
        }
    }
    if (fConvert != null && "preprocessURL" in fConvert) {
        url = fConvert.preprocessURL(url);
    }

    var next = Exhibit.JSONPImporter._callbacks.next || 1;
    Exhibit.JSONPImporter._callbacks.next = next + 1;

    var callbackName = "cb" + next.toString(36);
    var callbackURL = url;
    if (callbackURL.indexOf("?") == -1)
        callbackURL += "?";

    var lastChar = callbackURL.charAt(callbackURL.length - 1);
    if (lastChar != "=") {
        if (lastChar != "&" && lastChar != "?")
            callbackURL += "&";
        callbackURL += "callback=";
    }

    var callbackFull = "Exhibit.JSONPImporter._callbacks." + callbackName;
    callbackURL += callbackFull;
    var cleanup = function( failedURL ) {
        try {
            Exhibit.UI.hideBusyIndicator();

            delete Exhibit.JSONPImporter._callbacks[callbackName+"_fail"];
            delete Exhibit.JSONPImporter._callbacks[callbackName];
            if (script && script.parentNode) {
                script.parentNode.removeChild(script);
            }
        } finally {
            if (failedURL) {
                prompt("Failed to load javascript file:", failedURL);
                cont && cont(undefined); // got no json! signal with undefined
            }
        }
    };

    Exhibit.JSONPImporter._callbacks[callbackName+"_fail"] = cleanup;
    Exhibit.JSONPImporter._callbacks[callbackName] = function(json) {
        try {
            cleanup(null);
            database.loadData(fConvert ? fConvert(json, url, link) : json,
                              Exhibit.Persistence.getBaseURL(url));
        } finally {
            if (cont) cont(json);
        }
    };
    if (staticJSONPCallback) { // fallback for partial JSONP support feeds
        callbackURL = url; // url callback parameter not supported; do not pass
        eval(staticJSONPCallback + "=" + callbackFull);
    }

    var fail = callbackFull + "_fail('"+ callbackURL +"');";
    var script = SimileAjax.includeJavascriptFile(document,
                                                  callbackURL,
                                                  fail,
                                                  charset);
    Exhibit.UI.showBusyIndicator();
    return Exhibit.JSONPImporter._callbacks[callbackName];
};

// Does 90% of the feed conversion for 90% of all (well designed) JSONP feeds.
// Pass the raw json object, an optional index to drill into to get at the
// array of items ("feed.entry", in the case of Google Spreadsheets -- pass
// null, if the array is already the top container, as in a Del.icio.us feed),
// an object mapping the wanted item property name to the properties to pick
// them up from, and an optional similar mapping with conversion callbacks to
// perform on the data value before storing it in the item property. These
// callback functions are invoked with the value, the object it was picked up
// from, its index in the items array, the items array and the feed as a whole
// (for the cases where you need to look up properties from the surroundings).
// Returning the undefined value your converter means the property is not set.
Exhibit.JSONPImporter.transformJSON = function(json, index, mapping, converters) {
    var objects = json, items = [];
    if (index) {
        index = index.split(".");
        while (index.length) {
            objects = objects[index.shift()];
        }
    }
    for (var i = 0, object; object = objects[i]; i++) {
        var item = {};
        for (var name in mapping) {
            var index = mapping[name];
            if (!mapping.hasOwnProperty(name) || // gracefully handle poisoned
                !object.hasOwnProperty(index)) continue; // Object.prototype
            var property = object[index];
            if (converters && converters.hasOwnProperty(name)) {
                property = converters[name](property, object, i, objects, json);
            }
            if (typeof property != "undefined") {
                item[name] = property;
            }
        }
        items.push(item);
    }
    return items;
};

Exhibit.JSONPImporter.deliciousConverter = function(json, url) {
    var items = Exhibit.JSONPImporter.transformJSON(json, null,
        { label:"u", note:"n", description:"d", tags:"t" });
    return { items:items, properties:{ url:{ valueType:"url" } } };
};

Exhibit.JSONPImporter.googleSpreadsheetsConverter = function(json, url, link) {
    var separator = ";";
    if ((link) && (typeof link != "string")) {
        var s = Exhibit.getAttribute(link, "separator");
        if (s != null && s.length > 0) {
            separator = s;
        }
    }

    var items = [];
    var properties = {};
    var types = {};
    var valueTypes = { "text" : true, "number" : true, "item" : true, "url" : true, "boolean" : true, "date" : true };

    var entries = json.feed.entry || []; // if no entries in feed
    for (var i = 0; i < entries.length; i++) {
        var entry = entries[i];
        var id = entry.id.$t;
        var c = id.lastIndexOf("C");
        var r = id.lastIndexOf("R");

        entries[i] = {
            row: parseInt(id.substring(r + 1, c)) - 1,
            col: parseInt(id.substring(c + 1)) - 1,
            val: entry.content.$t
        };
    };

    var cellIndex = 0;
    var getNextRow = function() {
        if (cellIndex < entries.length) {
            var firstEntry = entries[cellIndex++];
            var row = [ firstEntry ];
            while (cellIndex < entries.length) {
                var nextEntry = entries[cellIndex];
                if (nextEntry.row == firstEntry.row) {
                    row.push(nextEntry);
                    cellIndex++;
                } else {
                    break;
                }
            }
            return row;
        }
        return null;
    };

    var propertyRow = getNextRow();
    if (propertyRow != null) {
        var propertiesByColumn = [];
        for (var i = 0; i < propertyRow.length; i++) {
            var cell = propertyRow[i];

            var fieldSpec = cell.val.trim().replace(/^\{/g, "").replace(/\}$/g, "").split(":");
            var fieldName = fieldSpec[0].trim();
            var fieldDetails = fieldSpec.length > 1 ? fieldSpec[1].split(",") : [];

            var property = { single: false };

            for (var d = 0; d < fieldDetails.length; d++) {
                var detail = fieldDetails[d].trim();
                if (detail in valueTypes) {
                    property.valueType = detail;
                } else if (detail == "single") {
                    property.single = true;
                }
            }

            propertiesByColumn[cell.col] = fieldName;
            properties[fieldName] = property;
        }

        var row = null;
        while ((row = getNextRow()) != null) {
            var item = {};

            for (var i = 0; i < row.length; i++) {
                var cell = row[i];
                var fieldName = propertiesByColumn[cell.col];
                if (typeof fieldName == "string") {

                    // ensure round-trip iso8601 date strings through google docs
                    var googleDocsDateRegex = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
                    if (googleDocsDateRegex.exec(cell.val)) {
                        cell.val = Exhibit.Database.makeISO8601DateString(new Date(cell.val));
                    }

                    item[fieldName] = cell.val;

                    var property = properties[fieldName];
                    if (!property.single) {
                        var fieldValues = cell.val.split(separator);
                        for (var v = 0; v < fieldValues.length; v++) {
                            fieldValues[v] = fieldValues[v].trim();
                        }
                        item[fieldName] = fieldValues;
                    } else {
                        item[fieldName] = cell.val.trim();
                    }
                }
            }

            items.push(item);
        }
    }

    return { types:types, properties:properties, items:items };
};

Exhibit.JSONPImporter.googleSpreadsheetsConverter.preprocessURL = function(url) {
    return url.replace(/\/list\//g, "/cells/");
};
<commit_msg>minor bug in json transformer.<commit_after>/*==================================================
 *  Exhibit.JSONPImporter
 *==================================================
 */

Exhibit.JSONPImporter = {
    _callbacks: {}
};
Exhibit.importers["application/jsonp"] = Exhibit.JSONPImporter;

// cont gets called with the original feed (so you can pick up details from the
// feed from user code that were of interest to you but not the exhibit itself,
// for instance). load returns the callback that the JSONP payload should call,
// so that even partial static JSONP implementations (with a fixed callback
// name) can assign that variable with the return value, and things will
// work out, as much as they can (i e concurrent requests can get mixed up).
Exhibit.JSONPImporter.load = function(
    link, database, cont, fConvert, staticJSONPCallback, charset
) {
    var url = link;
    if (typeof link != "string") {
        url = Exhibit.Persistence.resolveURL(link.href);
        fConvert = Exhibit.getAttribute(link, "converter");
        staticJSONPCallback = Exhibit.getAttribute(link, "jsonp-callback");
        charset = Exhibit.getAttribute(link, "charset");
    }
    if (typeof fConvert == "string") {
        var name = fConvert;
        name = name.charAt(0).toLowerCase() + name.substring(1) + "Converter";
        if (name in Exhibit.JSONPImporter) {
            fConvert = Exhibit.JSONPImporter[name];
        } else {
            try {
                fConvert = eval(fConvert);
            } catch (e) {
                fConvert = null;
                // silent
            }
        }
    }
    if (fConvert != null && "preprocessURL" in fConvert) {
        url = fConvert.preprocessURL(url);
    }

    var next = Exhibit.JSONPImporter._callbacks.next || 1;
    Exhibit.JSONPImporter._callbacks.next = next + 1;

    var callbackName = "cb" + next.toString(36);
    var callbackURL = url;
    if (callbackURL.indexOf("?") == -1)
        callbackURL += "?";

    var lastChar = callbackURL.charAt(callbackURL.length - 1);
    if (lastChar != "=") {
        if (lastChar != "&" && lastChar != "?")
            callbackURL += "&";
        callbackURL += "callback=";
    }

    var callbackFull = "Exhibit.JSONPImporter._callbacks." + callbackName;
    callbackURL += callbackFull;
    var cleanup = function( failedURL ) {
        try {
            Exhibit.UI.hideBusyIndicator();

            delete Exhibit.JSONPImporter._callbacks[callbackName+"_fail"];
            delete Exhibit.JSONPImporter._callbacks[callbackName];
            if (script && script.parentNode) {
                script.parentNode.removeChild(script);
            }
        } finally {
            if (failedURL) {
                prompt("Failed to load javascript file:", failedURL);
                cont && cont(undefined); // got no json! signal with undefined
            }
        }
    };

    Exhibit.JSONPImporter._callbacks[callbackName+"_fail"] = cleanup;
    Exhibit.JSONPImporter._callbacks[callbackName] = function(json) {
        try {
            cleanup(null);
            database.loadData(fConvert ? fConvert(json, url, link) : json,
                              Exhibit.Persistence.getBaseURL(url));
        } finally {
            if (cont) cont(json);
        }
    };
    if (staticJSONPCallback) { // fallback for partial JSONP support feeds
        callbackURL = url; // url callback parameter not supported; do not pass
        eval(staticJSONPCallback + "=" + callbackFull);
    }

    var fail = callbackFull + "_fail('"+ callbackURL +"');";
    var script = SimileAjax.includeJavascriptFile(document,
                                                  callbackURL,
                                                  fail,
                                                  charset);
    Exhibit.UI.showBusyIndicator();
    return Exhibit.JSONPImporter._callbacks[callbackName];
};

// Does 90% of the feed conversion for 90% of all (well designed) JSONP feeds.
// Pass the raw json object, an optional index to drill into to get at the
// array of items ("feed.entry", in the case of Google Spreadsheets -- pass
// null, if the array is already the top container, as in a Del.icio.us feed),
// an object mapping the wanted item property name to the properties to pick
// them up from, and an optional similar mapping with conversion callbacks to
// perform on the data value before storing it in the item property. These
// callback functions are invoked with the value, the object it was picked up
// from, its index in the items array, the items array and the feed as a whole
// (for the cases where you need to look up properties from the surroundings).
// Returning the undefined value your converter means the property is not set.
Exhibit.JSONPImporter.transformJSON = function(json, index, mapping, converters) {
    var objects = json, items = [];
    if (index) {
        index = index.split(".");
        while (index.length) {
            objects = objects[index.shift()];
        }
    }
    for (var i = 0, object; object = objects[i]; i++) {
        var item = {};
        for (var name in mapping) {
	    if (mapping.hasOwnProperty(name)) { // gracefully handle poisoned
		var index = mapping[name].split(".");      // Object.prototype
		for (var property=object; index.length && property;
		     property=property[index.shift()]) {}
		if (property && converters && converters.hasOwnProperty(name)) {
                    property = converters[name](property, object, i, objects, json);
		}
		if (typeof property != "undefined") {
                    item[name] = property;
		}
	    }
        }
        items.push(item);
    }
    return items;
};

Exhibit.JSONPImporter.deliciousConverter = function(json, url) {
    var items = Exhibit.JSONPImporter.transformJSON(json, null,
        { label:"u", note:"n", description:"d", tags:"t" });
    return { items:items, properties:{ url:{ valueType:"url" } } };
};

Exhibit.JSONPImporter.googleSpreadsheetsConverter = function(json, url, link) {
    var separator = ";";
    if ((link) && (typeof link != "string")) {
        var s = Exhibit.getAttribute(link, "separator");
        if (s != null && s.length > 0) {
            separator = s;
        }
    }

    var items = [];
    var properties = {};
    var types = {};
    var valueTypes = { "text" : true, "number" : true, "item" : true, "url" : true, "boolean" : true, "date" : true };

    var entries = json.feed.entry || []; // if no entries in feed
    for (var i = 0; i < entries.length; i++) {
        var entry = entries[i];
        var id = entry.id.$t;
        var c = id.lastIndexOf("C");
        var r = id.lastIndexOf("R");

        entries[i] = {
            row: parseInt(id.substring(r + 1, c)) - 1,
            col: parseInt(id.substring(c + 1)) - 1,
            val: entry.content.$t
        };
    };

    var cellIndex = 0;
    var getNextRow = function() {
        if (cellIndex < entries.length) {
            var firstEntry = entries[cellIndex++];
            var row = [ firstEntry ];
            while (cellIndex < entries.length) {
                var nextEntry = entries[cellIndex];
                if (nextEntry.row == firstEntry.row) {
                    row.push(nextEntry);
                    cellIndex++;
                } else {
                    break;
                }
            }
            return row;
        }
        return null;
    };

    var propertyRow = getNextRow();
    if (propertyRow != null) {
        var propertiesByColumn = [];
        for (var i = 0; i < propertyRow.length; i++) {
            var cell = propertyRow[i];

            var fieldSpec = cell.val.trim().replace(/^\{/g, "").replace(/\}$/g, "").split(":");
            var fieldName = fieldSpec[0].trim();
            var fieldDetails = fieldSpec.length > 1 ? fieldSpec[1].split(",") : [];

            var property = { single: false };

            for (var d = 0; d < fieldDetails.length; d++) {
                var detail = fieldDetails[d].trim();
                if (detail in valueTypes) {
                    property.valueType = detail;
                } else if (detail == "single") {
                    property.single = true;
                }
            }

            propertiesByColumn[cell.col] = fieldName;
            properties[fieldName] = property;
        }

        var row = null;
        while ((row = getNextRow()) != null) {
            var item = {};

            for (var i = 0; i < row.length; i++) {
                var cell = row[i];
                var fieldName = propertiesByColumn[cell.col];
                if (typeof fieldName == "string") {

                    // ensure round-trip iso8601 date strings through google docs
                    var googleDocsDateRegex = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
                    if (googleDocsDateRegex.exec(cell.val)) {
                        cell.val = Exhibit.Database.makeISO8601DateString(new Date(cell.val));
                    }

                    item[fieldName] = cell.val;

                    var property = properties[fieldName];
                    if (!property.single) {
                        var fieldValues = cell.val.split(separator);
                        for (var v = 0; v < fieldValues.length; v++) {
                            fieldValues[v] = fieldValues[v].trim();
                        }
                        item[fieldName] = fieldValues;
                    } else {
                        item[fieldName] = cell.val.trim();
                    }
                }
            }

            items.push(item);
        }
    }

    return { types:types, properties:properties, items:items };
};

Exhibit.JSONPImporter.googleSpreadsheetsConverter.preprocessURL = function(url) {
    return url.replace(/\/list\//g, "/cells/");
};
<|endoftext|>


<commit_before>//test-name.spec.js

/* global casper */

casper.test.begin('About us page test', 3,
  function suite(test){
    casper.start('http://localhost/neukinnis/client/aboutus.html', function(){
    test.assertTitle('About Us', 'open about us success');
    test.assertExists('a[href="index.html"]', 'found link home');
  });
  casper.then(function(){
    this.click('a[href="index.html"]');
  });
  casper.then(function(){
    test.assertTitle('Neukinnis', 'open home success');
  });
  casper.thenOpen('http://localhost/neukinnis/client/aboutus.html').then(function(){
    test.assertTitle('About Us', 'return to about us');
    test.assertExists('a[href="privacy.html"]', 'found link privacy');
  });
  casper.then(function(){
    this.click('a[href="privacy.html"]');
  });
  casper.then(function(){
    test.assertTitle('Privacy', 'open privacy success');
  });
  casper.thenOpen('http://localhost/neukinnis/client/aboutus.html').then(function(){
    test.assertTitle('About Us', 'return to about us');
    test.assertExists('a[href="contactus.html"]', 'found link contactus');
  });
  casper.then(function(){
    this.click('a[href="contactus.html"]');
  });
  casper.then(function(){
    test.assertTitle('Contact Us', 'open contact us success');
  });
  casper.thenOpen('http://localhost/neukinnis/client/aboutus.html').then(function(){
    test.assertTitle('About Us', 'return to about us');
    test.assertExists('a[href="courses.html"]', 'found link courses');
  });
  casper.then(function(){
    this.click('a[href="courses.html"]');
  });
  casper.then(function(){
    test.assertTitle('Courses', 'open courses success');
  });
  casper.thenOpen('http://localhost/neukinnis/client/aboutus.html').then(function(){
    test.assertTitle('About Us', 'return to about us');
    test.assertExists('a[href="instructors.html"]', 'found instructors link');
  });
  casper.then(function(){
    this.click('a[href="instructors.html"]');
  });
  casper.then(function(){
    test.assertTitle('Instructors', 'open instructors success');
  });
  casper.run(function(){
    test.done();
  });
});<commit_msg>rewrite output messages<commit_after>//test-name.spec.js

/* global casper */

casper.test.begin('About us page test', 3,
  function suite(test){
    casper.start('http://localhost/neukinnis/client/index.html', function(){
    test.assertTitle('Neukinnis', 'Finds the main page with title: Neukinnis');
    test.assertExists('a[href="aboutus.html"]', 'Checks existence link to about us page');
  });
  casper.then(function(){
    this.click('a[href="aboutus.html"]', 'Navigates and clicks on link to about us page');
  });
  casper.then(function(){
    test.assertTitle('About Us', 'Finds page title About Us');
    test.assertExists('a[href="privacy.html"]', 'Check existence of link to privacy page');
  });
  casper.then(function(){
    this.click('a[href="privacy.html"]', "Navigates and clicks on link to privage page");
  });
  casper.then(function(){
    test.assertTitle('Privacy', 'Finds page title Privacy');
    test.assertExists('a[href="index.html"]', 'Check existence of link to home page');
  });
  casper.then(function(){
    this.click('a[href="index.html"]', "Navigates and clicks on link to home page");
  });
    casper.then(function(){
    test.assertTitle('Neukinnis', 'Finds page title Neukinnis');
    test.assertExists('a[href="courses.html"]', 'Check existence of link to courses page');
  });
    casper.then(function(){
    this.click('a[href="courses.html"]', "Navigates and clicks on link to courses page");
  });
    casper.then(function(){
    test.assertTitle('Courses', 'Finds page title Courses');
  casper.run(function(){
    test.done();
  });
});<|endoftext|>


<commit_before>var Camera = require('Camera.js');

class Game {
  tick() {
    window.requestAnimationFrame(this.tick.bind(this));

    var currentTime = Date.now();
    var elapsed = currentTime - this.lastUpdate;

    if (this.desiredFPS) {
      if (elapsed > this.desiredInterval) {
        this.lastUpdate = currentTime - (elapsed % this.desiredInterval);

        this.currentState.dt = elapsed * 0.001;
        this.currentState.update();
        this.currentState.draw();
      }
    } else {
      this.lastUpdate = currentTime;

      this.currentState.dt = elapsed * 0.001;
      this.currentState.update();
      this.currentState.draw();
    }
  }

  init() {
    this.lastUpdate = Date.now();

    if (this.desiredFPS) {
      this.desiredInterval = 1000 / this.desiredFPS;
    }

    var myInterval = window.requestAnimationFrame(this.tick.bind(this));
  }

  handleKeyDown(e) {
    var event = (e) ? e : window.event;
    var name = this.keyCodeToString[event.keyCode];
    this.pressedKeys[name] = true;

    if (this.preventedKeys.indexOf(name) > -1) {
      e.preventDefault();
    }
  }

  handleKeyUp(e) {
    var event = (e) ? e : window.event;
    var name = this.keyCodeToString[event.keyCode];
    this.pressedKeys[name] = false;

    if (this.preventedKeys.indexOf(name) > -1) {
      e.preventDefault();
    }
  }

  handleTouchStart(e) {
    var event = (e) ? e : window.event;

    mouse.x = event.targetTouches[0].pageX;
    mouse.y = event.targetTouches[0].pageY;

    this.pressedButtons['left'] = true;
  }

  handleTouchEnd(e) {
    var event = (e) ? e : window.event;

    this.pressedButtons['left'] = false;
  }

  handleMouseDown(e) {
    var event = (e) ? e : window.event;
    var humanName = this.convertMouseButtonToString[event.button];

    this.pressedButtons[humanName] = true;
  }

  handleMouseUp(e) {
    var event = (e) ? e : window.event;
    var humanName = this.convertMouseButtonToString[event.button];

    this.pressedButtons[humanName] = false;
  }

  handleMouseMove(e) {
    if (e.offsetX) {
      this.mouse.x = e.offsetX;
      this.mouse.y = e.offsetY;
    } else if (e.layerX) {
      this.mouse.x = e.layerX;
      this.mouse.y = e.layerY;
    }

    if (this.currentState !== null) {
      this.mouse.x += this.currentState.camera.x;
      this.mouse.y += this.currentState.camera.y;
    }
  }

  handleTouchMove(e) {
    var event = (e) ? e : window.event;
    e.stopPropagation();
    e.preventDefault();

    /* Tanslate to mouse event */
    var clickEvent = document.createEvent('MouseEvent');
    clickEvent.initMouseEvent('mousemove', true, true, window, e.detail,
                              e.touches[0].screenX, e.touches[0].screenY,
                              e.touches[0].clientX, e.touches[0].clientY,
                              false, false, false, false, 0, null);

    window.dispatchEvent(clickEvent);
  }

  constructor () {
    this.desiredFPS = null;
    this.desiredInterval = null;
    this.lastUpdate = null;
    this.currentState = null;

    this.pressedKeys = [ ];
    this.preventedKeys = [ ];

    this.degToRad = Math.PI / 180;
    this.keyCodeToString = [ ];
    this.keyCodeToString[8] = 'backspace';
    this.keyCodeToString[9] = 'tab';
    this.keyCodeToString[13] = 'return';
    this.keyCodeToString[16] = 'shift';
    this.keyCodeToString[17] = 'ctrl';
    this.keyCodeToString[18] = 'alt';
    this.keyCodeToString[19] = 'pause';
    this.keyCodeToString[20] = 'capslock';
    this.keyCodeToString[27] = 'escape';
    this.keyCodeToString[32] = 'space';
    this.keyCodeToString[33] = 'pageup';
    this.keyCodeToString[34] = 'pagedown';
    this.keyCodeToString[35] = 'end';
    this.keyCodeToString[36] = 'home';
    this.keyCodeToString[37] = 'left';
    this.keyCodeToString[38] = 'up';
    this.keyCodeToString[39] = 'right';
    this.keyCodeToString[40] = 'down';
    this.keyCodeToString[45] = 'insert';
    this.keyCodeToString[46] = 'delete';

    this.keyCodeToString[91] = 'leftwindowkey';
    this.keyCodeToString[92] = 'rightwindowkey';
    this.keyCodeToString[93] = 'selectkey';
    this.keyCodeToString[106] = 'multiply';
    this.keyCodeToString[107] = 'add';
    this.keyCodeToString[109] = 'subtract';
    this.keyCodeToString[110] = 'decimalpoint';
    this.keyCodeToString[111] = 'divide';

    this.keyCodeToString[144] = 'numlock';
    this.keyCodeToString[145] = 'scrollock';
    this.keyCodeToString[186] = 'semicolon';
    this.keyCodeToString[187] = 'equalsign';
    this.keyCodeToString[188] = 'comma';
    this.keyCodeToString[189] = 'dash';
    this.keyCodeToString[190] = 'period';
    this.keyCodeToString[191] = 'forwardslash';
    this.keyCodeToString[192] = 'graveaccent';
    this.keyCodeToString[219] = 'openbracket';
    this.keyCodeToString[220] = 'backslash';
    this.keyCodeToString[221] = 'closebracket';
    this.keyCodeToString[222] = 'singlequote';

    var numpadKeys = ['numpad1', 'numpad2', 'numpad3', 'numpad4', 'numpad5',
                      'numpad6', 'numpad7', 'numpad8', 'numpad9'];

    var numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
    var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
                   'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
                   'u', 'v', 'w', 'x', 'y', 'z'];

    _.each(numbers, (el, index) => this.keyCodeToString[48 + index] = el);
    _.each(letters, (el, index) => this.keyCodeToString[65 + index] = el);
    _.each(numpadKeys, (el, index) => this.keyCodeToString[48 + index] = el);

    window.addEventListener('keydown', this.handleKeyDown.bind(this));
    window.addEventListener('keyup', this.handleKeyUp.bind(this));

    window.addEventListener('mousedown', this.handleMouseDown.bind(this), false);
    window.addEventListener('mouseup', this.handleMouseUp.bind(this), false);
    window.addEventListener('mousemove', this.handleMouseMove.bind(this), false);

    window.addEventListener('touchstart', this.handleTouchStart.bind(this), false);
    window.addEventListener('touchmove', this.handleTouchMove.bind(this), false);
    window.addEventListener('touchend', this.handleTouchEnd.bind(this), false);

    this.pressedButtons = [ ];
    this.mouse = { };

    this.convertMouseButtonToString = [ ];
    this.convertMouseButtonToString[0] = 'left';
    this.convertMouseButtonToString[1] = 'center';
    this.convertMouseButtonToString[2] = 'right';

    this.pauseKey = 'p';
    this.canPauseOrResume = true;
    this.gamePaused = false;

    this.currentFont = '10px serif';
  }

  setup(options) {
    /* Load the canvas */
    this.canvas = document.getElementById('canvas');

    if (options.desiredFPS) {
      this.desiredFPS = options.desiredFPS;
    }

    if (options.preventedKeys) {
      this.preventedKeys = options.preventedKeys;
    }

    if (typeof this.canvas !== 'undefined') {
      this.canvas.width = options.width;
      this.canvas.height = options.height;

      this.context = this.canvas.getContext('2d');

      this.context.width = options.width;
      this.context.height = options.height;
    }

    this.switchState(options.firstState);

    return this;
  }

  drawCircle(x, y, radius, color) {
    this.context.fillStyle = color;
    this.context.beginPath();
    this.context.arc(x, y, radius, 0, Math.PI * 2, false);
    this.context.fill();
  }

  drawRectangle(x, y, width, height, color) {
    if (color) {
      this.context.fillStyle = color;
    }

    this.context.fillRect(x, y, width, height);
  }

  drawLine(x1, y1, x2, y2, color) {
    if (color) {
      this.context.strokeStyle = color;
    }

    this.context.beginPath();
    this.context.moveTo(x1, y1);
    this.context.lineTo(x2, y2);
    this.context.stroke();
  }

  drawString(text, x, y, color, alignment) {
    if (!alignment) {
      this.context.textAlign = 'left';
    } else {
      this.context.textAlign = alignment;
    }

    this.context.textBaseline = 'top';
    this.context.font = this.currentFont;
    this.context.fillStyle = color;
    this.context.fillText(text, x, y);
  }

  clearCanvas(backgroundColor) {
    this.context.clearRect(0, 0, this.context.width, this.context.height);

    if (backgroundColor) {
      this.drawRectangle(0, 0, this.context.width, this.context.height, backgroundColor);
    }
  }

  isOutsideOfScreen(x, y) {
    return x < 0 || x > this.context.width || y < 0 || y > this.context.height;
  }

  getpressedKeys() {
    return this.pressedKeys;
  }

  getPressedButtons() {
    return this.pressedButtons;
  }

  isDown(name) {
    if (this.pressedKeys[name]) {
      return true;
    }

    return false;
  }

  isMouseDown(name) {
    if (this.pressedButtons[name]) {
      return true;
    }

    return false;
  }

  switchState(newState) {
    if (!this.currentState) {
      this.currentState = newState;
      this.init();
    }

    if (!newState.camera) {
      newState.camera = new Camera(0, 0, this.context.width, this.context.height);
    }

    newState.setup();

    this.currentState = newState;

    return this.currentState;
  }
}

class SpriteList {
  constructor() {
    this.sprites = [];
  }

  draw() {
    for (var i = 0; i < this.sprites.length; i++) {
      if (this.sprites[i]) {
        this.sprites[i].draw();
      }
    }
  }

  push(newSprite) {
    this.sprites.push(newSprite);
  }

  remove(sprite) {
    var index = this.sprites.indexOf(sprite);
    this.sprites.splice(index, 1);
  }

  getLength() {
    return this.sprites.length;
  }
}

module.exports = Game;<commit_msg>Replaces a require call with the new ES6 import statement.<commit_after>import Camera from 'Camera';

class Game {
  tick() {
    window.requestAnimationFrame(this.tick.bind(this));

    var currentTime = Date.now();
    var elapsed = currentTime - this.lastUpdate;

    if (this.desiredFPS) {
      if (elapsed > this.desiredInterval) {
        this.lastUpdate = currentTime - (elapsed % this.desiredInterval);

        this.currentState.dt = elapsed * 0.001;
        this.currentState.update();
        this.currentState.draw();
      }
    } else {
      this.lastUpdate = currentTime;

      this.currentState.dt = elapsed * 0.001;
      this.currentState.update();
      this.currentState.draw();
    }
  }

  init() {
    this.lastUpdate = Date.now();

    if (this.desiredFPS) {
      this.desiredInterval = 1000 / this.desiredFPS;
    }

    var myInterval = window.requestAnimationFrame(this.tick.bind(this));
  }

  handleKeyDown(e) {
    var event = (e) ? e : window.event;
    var name = this.keyCodeToString[event.keyCode];
    this.pressedKeys[name] = true;

    if (this.preventedKeys.indexOf(name) > -1) {
      e.preventDefault();
    }
  }

  handleKeyUp(e) {
    var event = (e) ? e : window.event;
    var name = this.keyCodeToString[event.keyCode];
    this.pressedKeys[name] = false;

    if (this.preventedKeys.indexOf(name) > -1) {
      e.preventDefault();
    }
  }

  handleTouchStart(e) {
    var event = (e) ? e : window.event;

    mouse.x = event.targetTouches[0].pageX;
    mouse.y = event.targetTouches[0].pageY;

    this.pressedButtons['left'] = true;
  }

  handleTouchEnd(e) {
    var event = (e) ? e : window.event;

    this.pressedButtons['left'] = false;
  }

  handleMouseDown(e) {
    var event = (e) ? e : window.event;
    var humanName = this.convertMouseButtonToString[event.button];

    this.pressedButtons[humanName] = true;
  }

  handleMouseUp(e) {
    var event = (e) ? e : window.event;
    var humanName = this.convertMouseButtonToString[event.button];

    this.pressedButtons[humanName] = false;
  }

  handleMouseMove(e) {
    if (e.offsetX) {
      this.mouse.x = e.offsetX;
      this.mouse.y = e.offsetY;
    } else if (e.layerX) {
      this.mouse.x = e.layerX;
      this.mouse.y = e.layerY;
    }

    if (this.currentState !== null) {
      this.mouse.x += this.currentState.camera.x;
      this.mouse.y += this.currentState.camera.y;
    }
  }

  handleTouchMove(e) {
    var event = (e) ? e : window.event;
    e.stopPropagation();
    e.preventDefault();

    /* Tanslate to mouse event */
    var clickEvent = document.createEvent('MouseEvent');
    clickEvent.initMouseEvent('mousemove', true, true, window, e.detail,
                              e.touches[0].screenX, e.touches[0].screenY,
                              e.touches[0].clientX, e.touches[0].clientY,
                              false, false, false, false, 0, null);

    window.dispatchEvent(clickEvent);
  }

  constructor () {
    this.desiredFPS = null;
    this.desiredInterval = null;
    this.lastUpdate = null;
    this.currentState = null;

    this.pressedKeys = [ ];
    this.preventedKeys = [ ];

    this.degToRad = Math.PI / 180;
    this.keyCodeToString = [ ];
    this.keyCodeToString[8] = 'backspace';
    this.keyCodeToString[9] = 'tab';
    this.keyCodeToString[13] = 'return';
    this.keyCodeToString[16] = 'shift';
    this.keyCodeToString[17] = 'ctrl';
    this.keyCodeToString[18] = 'alt';
    this.keyCodeToString[19] = 'pause';
    this.keyCodeToString[20] = 'capslock';
    this.keyCodeToString[27] = 'escape';
    this.keyCodeToString[32] = 'space';
    this.keyCodeToString[33] = 'pageup';
    this.keyCodeToString[34] = 'pagedown';
    this.keyCodeToString[35] = 'end';
    this.keyCodeToString[36] = 'home';
    this.keyCodeToString[37] = 'left';
    this.keyCodeToString[38] = 'up';
    this.keyCodeToString[39] = 'right';
    this.keyCodeToString[40] = 'down';
    this.keyCodeToString[45] = 'insert';
    this.keyCodeToString[46] = 'delete';

    this.keyCodeToString[91] = 'leftwindowkey';
    this.keyCodeToString[92] = 'rightwindowkey';
    this.keyCodeToString[93] = 'selectkey';
    this.keyCodeToString[106] = 'multiply';
    this.keyCodeToString[107] = 'add';
    this.keyCodeToString[109] = 'subtract';
    this.keyCodeToString[110] = 'decimalpoint';
    this.keyCodeToString[111] = 'divide';

    this.keyCodeToString[144] = 'numlock';
    this.keyCodeToString[145] = 'scrollock';
    this.keyCodeToString[186] = 'semicolon';
    this.keyCodeToString[187] = 'equalsign';
    this.keyCodeToString[188] = 'comma';
    this.keyCodeToString[189] = 'dash';
    this.keyCodeToString[190] = 'period';
    this.keyCodeToString[191] = 'forwardslash';
    this.keyCodeToString[192] = 'graveaccent';
    this.keyCodeToString[219] = 'openbracket';
    this.keyCodeToString[220] = 'backslash';
    this.keyCodeToString[221] = 'closebracket';
    this.keyCodeToString[222] = 'singlequote';

    var numpadKeys = ['numpad1', 'numpad2', 'numpad3', 'numpad4', 'numpad5',
                      'numpad6', 'numpad7', 'numpad8', 'numpad9'];

    var numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
    var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
                   'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
                   'u', 'v', 'w', 'x', 'y', 'z'];

    _.each(numbers, (el, index) => this.keyCodeToString[48 + index] = el);
    _.each(letters, (el, index) => this.keyCodeToString[65 + index] = el);
    _.each(numpadKeys, (el, index) => this.keyCodeToString[48 + index] = el);

    window.addEventListener('keydown', this.handleKeyDown.bind(this));
    window.addEventListener('keyup', this.handleKeyUp.bind(this));

    window.addEventListener('mousedown', this.handleMouseDown.bind(this), false);
    window.addEventListener('mouseup', this.handleMouseUp.bind(this), false);
    window.addEventListener('mousemove', this.handleMouseMove.bind(this), false);

    window.addEventListener('touchstart', this.handleTouchStart.bind(this), false);
    window.addEventListener('touchmove', this.handleTouchMove.bind(this), false);
    window.addEventListener('touchend', this.handleTouchEnd.bind(this), false);

    this.pressedButtons = [ ];
    this.mouse = { };

    this.convertMouseButtonToString = [ ];
    this.convertMouseButtonToString[0] = 'left';
    this.convertMouseButtonToString[1] = 'center';
    this.convertMouseButtonToString[2] = 'right';

    this.pauseKey = 'p';
    this.canPauseOrResume = true;
    this.gamePaused = false;

    this.currentFont = '10px serif';
  }

  setup(options) {
    /* Load the canvas */
    this.canvas = document.getElementById('canvas');

    if (options.desiredFPS) {
      this.desiredFPS = options.desiredFPS;
    }

    if (options.preventedKeys) {
      this.preventedKeys = options.preventedKeys;
    }

    if (typeof this.canvas !== 'undefined') {
      this.canvas.width = options.width;
      this.canvas.height = options.height;

      this.context = this.canvas.getContext('2d');

      this.context.width = options.width;
      this.context.height = options.height;
    }

    this.switchState(options.firstState);

    return this;
  }

  drawCircle(x, y, radius, color) {
    this.context.fillStyle = color;
    this.context.beginPath();
    this.context.arc(x, y, radius, 0, Math.PI * 2, false);
    this.context.fill();
  }

  drawRectangle(x, y, width, height, color) {
    if (color) {
      this.context.fillStyle = color;
    }

    this.context.fillRect(x, y, width, height);
  }

  drawLine(x1, y1, x2, y2, color) {
    if (color) {
      this.context.strokeStyle = color;
    }

    this.context.beginPath();
    this.context.moveTo(x1, y1);
    this.context.lineTo(x2, y2);
    this.context.stroke();
  }

  drawString(text, x, y, color, alignment) {
    if (!alignment) {
      this.context.textAlign = 'left';
    } else {
      this.context.textAlign = alignment;
    }

    this.context.textBaseline = 'top';
    this.context.font = this.currentFont;
    this.context.fillStyle = color;
    this.context.fillText(text, x, y);
  }

  clearCanvas(backgroundColor) {
    this.context.clearRect(0, 0, this.context.width, this.context.height);

    if (backgroundColor) {
      this.drawRectangle(0, 0, this.context.width, this.context.height, backgroundColor);
    }
  }

  isOutsideOfScreen(x, y) {
    return x < 0 || x > this.context.width || y < 0 || y > this.context.height;
  }

  getpressedKeys() {
    return this.pressedKeys;
  }

  getPressedButtons() {
    return this.pressedButtons;
  }

  isDown(name) {
    if (this.pressedKeys[name]) {
      return true;
    }

    return false;
  }

  isMouseDown(name) {
    if (this.pressedButtons[name]) {
      return true;
    }

    return false;
  }

  switchState(newState) {
    if (!this.currentState) {
      this.currentState = newState;
      this.init();
    }

    if (!newState.camera) {
      newState.camera = new Camera(0, 0, this.context.width, this.context.height);
    }

    newState.setup();

    this.currentState = newState;

    return this.currentState;
  }
}

class SpriteList {
  constructor() {
    this.sprites = [];
  }

  draw() {
    for (var i = 0; i < this.sprites.length; i++) {
      if (this.sprites[i]) {
        this.sprites[i].draw();
      }
    }
  }

  push(newSprite) {
    this.sprites.push(newSprite);
  }

  remove(sprite) {
    var index = this.sprites.indexOf(sprite);
    this.sprites.splice(index, 1);
  }

  getLength() {
    return this.sprites.length;
  }
}

module.exports = Game;<|endoftext|>


<commit_before>/**
 * Grid
 * A generic object that carries core grid properties. All grids appearing in a scene should inherit from the Grid object.
 *
 * Default iPhone viewport 320px X 356px
 * Status bar (cannot hide) 20px
 * Url bar 60px
 * Button bar 44px
 *
 * iPhone viewport running in full screen mode (installation on home screen) 320px X 480px
 *
 * Full Grid running in iPhone mode 320px X 368px (40 cols X 46 cols)
 *
 * @author Vince Allen 7-15-2010
 *
 * Big Block Framework
 * Copyright (C) 2011 Foldi, LLC
 *
 */

BigBlock.Grid = (function () {

	return {

		alias : 'Grid',

		blk_dim : 8, // the pixel dimensions; width & height; pixels are square
		width : 320, // global grid width
		height : 368, // global grid height

		x : 0, // will be set when grid divs are added to the dom
		y : 0,

		//cols : Math.round(320/8), // number of GLOBAL grid columns // replaced w Math.round(BigBlock.Grid.width/BigBlock.Grid.blk_dim)
		//rows : Math.round(368/8), // number of GLOBAL grid rows // replaced w Math.round(BigBlock.Grid.height/BigBlock.Grid.blk_dim)

		//quad_width : 160, // replaced w BigBlock.Grid.width/2
		//quad_height : 184, // replaced w BigBlock.Grid.height/2
		//quad_cols : Math.round(160/8), // number of QUAD grid columns // replaced w Math.round((BigBlock.Grid.width/2)/BigBlock.Grid.blk_dim)
		//quad_rows : Math.round(184/8), // number of QUAD grid rows // replaced w Math.round((BigBlock.Grid.height/2)/BigBlock.Grid.blk_dim)

		total_global_cols : false, // set in Timer
		total_quad_cols : false, // set in Timer

		//

		build_start_time : new Date().getTime(),
		build_end_time : new Date().getTime(),
		build_offset : 0,
		build_section_count : 0,
		//build_section_total : Math.round((184/8))/2, // replaced w Math.round(((BigBlock.Grid.width/2)/8))/2
		build_rowNum : 0,
		char_width : 8,
		char_height : 8,
		styles : {},

		configure : function (params) {
			var key;
			if (typeof(params) !== "undefined") {
				for (key in params) {
					if (params.hasOwnProperty(key)) {
						this[key] = params[key];
					}
				}
			}
		},
		setProps : function (params) {
			var i;
			if (typeof(params) !== "undefined") { // loop thru passed params to override above defaults
				for (i in params) {
					if (params.hasOwnProperty(i)) {
						this[i] = params[i];
					}
				}
			}
		},
		/**
		 * Allows setting specific styles after GridActive has been created and div has been added to the dom.
		 * @param key
		 * @param value
		 *
		 */
		setStyle : function (key, value) {
			var i, max;
			try {
				if (typeof(key) === "undefined") {
					throw new Error("BigBlock.Grid.setStyle(): BigBlock.Grid.setStyle(key, value) requires a style key.");
				}
				if (typeof(value) === "undefined") {
					throw new Error("BigBlock.Grid.setStyle(): BigBlock.Grid.setStyle(key, value) requires a style value.");
				}
			} catch(e) {
					BigBlock.Log.display(e.name + ": " + e.message);
			}
			for (i = 0, max = this.quads.length; i < max; i++) {
				document.getElementById(this.quads[i].id).style[key] = value;
			}
			this.styles[key] = value; // save new value

		},
		add: function(){

			var win_dim, s, i, grid_quad, key, max;

			this.build_start_time = new Date().getTime();

			win_dim = BigBlock.getWindowDim();

			try {
				if (win_dim.width === false || win_dim.height === false) {
					win_dim.width = 800;
					win_dim.height = 600;
					throw new Error("BigBlock.Grid.setStyle(): Detecting window size failed. Browser does not support window.innerWidth or document.documentElement.clientWidth. Using 800 x 600.");
				}
			} catch(e) {
				BigBlock.Log.display(e.name + ': ' + e.message);
			}

			 s = document.styleSheets[document.styleSheets.length - 1];

			for (i = 0, max = this.quads.length; i < max; i++) {
				try {
					if (s.insertRule) { // Mozilla
						s.insertRule("div#" + this.quads[i].id + " {background-color:transparent;width: " + this.quads[i].width + "px;height: " + this.quads[i].height + "px;position: absolute;left: " + ((win_dim.width / 2) + this.quads[i].left - this.width/2) + "px;top: " + ((win_dim.height / 2) + this.quads[i].top - this.height/2) + "px;z-index: " + this.quads[i].zIndex + "}", 0);
					} else if (s.addRule) { // IE
						s.addRule("div#" + this.quads[i].id, "background-color:transparent;width: " + this.quads[i].width + "px;height: " + this.quads[i].height + "px;position: absolute;left: " + ((win_dim.width / 2) + this.quads[i].left - this.width/2) + "px;top: " + ((win_dim.height / 2) + this.quads[i].top - this.height/2) + "px;z-index: " + this.quads[i].zIndex);
					} else {
						throw new Error('Err: GA002');
					}
				} catch(e) {
					BigBlock.Log.display(e.name + ': ' + e.message);
				}
			}

			this.x = ((win_dim.width / 2) - (this.quads[0].left)); // set the Grid x, y to the first quad's x, y
			this.y = ((win_dim.height / 2) - (this.quads[0].top));

			// grid_quad
			for (i = 0, max = this.quads.length; i < max; i++) {

				grid_quad = document.createElement('div');
				grid_quad.setAttribute('id', this.quads[i].id);

				for (key in this.styles) {
					if (this.styles.hasOwnProperty(key)) {
						grid_quad.style[key] = this.styles[key];
					}
				}

				document.body.appendChild(grid_quad);
			}

		},
		/**
		 * Creates a css rule for every position in the grid
		 * @param key
		 * @param value
		 *
		 */
		build : function () {

			var colNum, quad_width, quad_height, build_section_total, s, i, total_rules, max;

			colNum = 0;
			quad_width = BigBlock.Grid.width/2;
			quad_height = BigBlock.Grid.height/2;
			build_section_total = Math.round((quad_height/BigBlock.Grid.blk_dim))/2;

			s = document.styleSheets[document.styleSheets.length - 1];

			for (i = 0, max = ((Math.round(quad_width/BigBlock.Grid.blk_dim) * Math.round(quad_height/BigBlock.Grid.blk_dim)) / build_section_total); i < max; i++) {
				if (colNum < Math.round(quad_width/BigBlock.Grid.blk_dim)) {
					colNum++;
				} else {
					colNum = 1;
				}

				if (i % Math.round(quad_width/BigBlock.Grid.blk_dim) === 0) {
					this.build_rowNum++;
				}

				if (s.insertRule) { // Mozilla
					s.insertRule("." + BigBlock.CSSid_position + (i + this.build_offset) + " {left:" + ((colNum - 1) * this.blk_dim) + "px;top:" + ((this.build_rowNum - 1) * this.blk_dim) + "px;}", 0); // setup pos rules
				} else if (s.addRule) { // IE
					s.addRule("." + BigBlock.CSSid_position + (i + this.build_offset), " left:" + ((colNum - 1) * this.blk_dim) + "px;top:" + ((this.build_rowNum - 1) * this.blk_dim) + "px"); // setup pos rules
				}

			}

			// total_rules;
			try {

				if (s.cssRules) { // Mozilla
					total_rules = s.cssRules.length;
				} else if (s.rules) { // IE
					total_rules = s.rules.length;
				} else {
					throw new Error("BigBlock.Grid.build(): document.styleSheets rule count failed. Browser does not support cssRules.length() or rules.length().");
				}

			} catch(e) {
				BigBlock.Log.display(e.name + ": " + e.message);
			}

			this.build_offset = total_rules;

			BigBlock.Loader.update({
				"total" : Math.round((total_rules / (Math.round(quad_width/BigBlock.Grid.blk_dim) * Math.round(quad_height/BigBlock.Grid.blk_dim))) * 100)
			});

			if (total_rules < (Math.round(quad_width/BigBlock.Grid.blk_dim) * Math.round(quad_height/BigBlock.Grid.blk_dim))) { // if all styles are not complete, send false back to Timer; Timer will call build again
				return false;
			} else {
				return true;
			}
		},
		buildCharStyles : function () {

			var s, i, col_count, max;

			s = document.styleSheets[document.styleSheets.length - 1];

			if (s.insertRule) { // Mozilla
				s.insertRule("."+BigBlock.CSSid_text_bg+"{background-color: transparent;}", 0);
				s.insertRule("."+BigBlock.CSSid_char+"{width : 1px;height : 1px;position: absolute;float: left;line-height:0px;font-size:1%;}", 0);
			} else if (s.addRule) { // IE
				s.addRule("."+BigBlock.CSSid_text_bg, "background-color: transparent");
				s.addRule("."+BigBlock.CSSid_char, "width : 1px;height : 1px;position: absolute;float: left;line-height:0px;font-size:1%;");
			}

			col_count = 1;
			for (i = 0, max = this.char_width * this.char_height; i < max; i++) {

				if (s.insertRule) { // Mozilla
					s.insertRule("." + BigBlock.CSSid_char_pos + (i + 1) + "{left:" + col_count + "px;top:" + (Math.floor((i/8))+1) + "px;}", 0);
				} else if (s.addRule) { // IE
					s.addRule("." + BigBlock.CSSid_char_pos + (i + 1), "left:" + col_count + "px;top:" + (Math.floor((i/8))+1) + "px;");
				}

				if (col_count + 1 <= this.char_width) {
					col_count++;
				} else {
					col_count = 1;
				}
			}

			return true;
		}

	};

})();<commit_msg>Grid: updated calculation for quad x, y<commit_after>/**
 * Grid
 * A generic object that carries core grid properties. All grids appearing in a scene should inherit from the Grid object.
 *
 * Default iPhone viewport 320px X 356px
 * Status bar (cannot hide) 20px
 * Url bar 60px
 * Button bar 44px
 *
 * iPhone viewport running in full screen mode (installation on home screen) 320px X 480px
 *
 * Full Grid running in iPhone mode 320px X 368px (40 cols X 46 cols)
 *
 * @author Vince Allen 7-15-2010
 *
 * Big Block Framework
 * Copyright (C) 2011 Foldi, LLC
 *
 */

BigBlock.Grid = (function () {

	return {

		alias : 'Grid',

		blk_dim : 8, // the pixel dimensions; width & height; pixels are square
		width : 320, // global grid width
		height : 368, // global grid height

		x : 0, // will be set when grid divs are added to the dom
		y : 0,

		//cols : Math.round(320/8), // number of GLOBAL grid columns // replaced w Math.round(BigBlock.Grid.width/BigBlock.Grid.blk_dim)
		//rows : Math.round(368/8), // number of GLOBAL grid rows // replaced w Math.round(BigBlock.Grid.height/BigBlock.Grid.blk_dim)

		//quad_width : 160, // replaced w BigBlock.Grid.width/2
		//quad_height : 184, // replaced w BigBlock.Grid.height/2
		//quad_cols : Math.round(160/8), // number of QUAD grid columns // replaced w Math.round((BigBlock.Grid.width/2)/BigBlock.Grid.blk_dim)
		//quad_rows : Math.round(184/8), // number of QUAD grid rows // replaced w Math.round((BigBlock.Grid.height/2)/BigBlock.Grid.blk_dim)

		total_global_cols : false, // set in Timer
		total_quad_cols : false, // set in Timer

		//

		build_start_time : new Date().getTime(),
		build_end_time : new Date().getTime(),
		build_offset : 0,
		build_section_count : 0,
		//build_section_total : Math.round((184/8))/2, // replaced w Math.round(((BigBlock.Grid.width/2)/8))/2
		build_rowNum : 0,
		char_width : 8,
		char_height : 8,
		styles : {},

		configure : function (params) {
			var key;
			if (typeof(params) !== "undefined") {
				for (key in params) {
					if (params.hasOwnProperty(key)) {
						this[key] = params[key];
					}
				}
			}
		},
		setProps : function (params) {
			var i;
			if (typeof(params) !== "undefined") { // loop thru passed params to override above defaults
				for (i in params) {
					if (params.hasOwnProperty(i)) {
						this[i] = params[i];
					}
				}
			}
		},
		/**
		 * Allows setting specific styles after GridActive has been created and div has been added to the dom.
		 * @param key
		 * @param value
		 *
		 */
		setStyle : function (key, value) {
			var i, max;
			try {
				if (typeof(key) === "undefined") {
					throw new Error("BigBlock.Grid.setStyle(): BigBlock.Grid.setStyle(key, value) requires a style key.");
				}
				if (typeof(value) === "undefined") {
					throw new Error("BigBlock.Grid.setStyle(): BigBlock.Grid.setStyle(key, value) requires a style value.");
				}
			} catch(e) {
					BigBlock.Log.display(e.name + ": " + e.message);
			}
			for (i = 0, max = this.quads.length; i < max; i++) {
				document.getElementById(this.quads[i].id).style[key] = value;
			}
			this.styles[key] = value; // save new value

		},
		add: function(){

			var win_dim, s, i, grid_quad, key, max;

			this.build_start_time = new Date().getTime();

			win_dim = BigBlock.getWindowDim();

			try {
				if (win_dim.width === false || win_dim.height === false) {
					win_dim.width = 800;
					win_dim.height = 600;
					throw new Error("BigBlock.Grid.setStyle(): Detecting window size failed. Browser does not support window.innerWidth or document.documentElement.clientWidth. Using 800 x 600.");
				}
			} catch(e) {
				BigBlock.Log.display(e.name + ': ' + e.message);
			}

			 s = document.styleSheets[document.styleSheets.length - 1];

			for (i = 0, max = this.quads.length; i < max; i++) {
				try {
					if (s.insertRule) { // Mozilla
						s.insertRule("div#" + this.quads[i].id + " {background-color:transparent;width: " + this.quads[i].width + "px;height: " + this.quads[i].height + "px;position: absolute;left: " + ((win_dim.width / 2) + this.quads[i].left - this.width/2) + "px;top: " + ((win_dim.height / 2) + this.quads[i].top - this.height/2) + "px;z-index: " + this.quads[i].zIndex + "}", 0);
					} else if (s.addRule) { // IE
						s.addRule("div#" + this.quads[i].id, "background-color:transparent;width: " + this.quads[i].width + "px;height: " + this.quads[i].height + "px;position: absolute;left: " + ((win_dim.width / 2) + this.quads[i].left - this.width/2) + "px;top: " + ((win_dim.height / 2) + this.quads[i].top - this.height/2) + "px;z-index: " + this.quads[i].zIndex);
					} else {
						throw new Error('Err: GA002');
					}
				} catch(e) {
					BigBlock.Log.display(e.name + ': ' + e.message);
				}
			}

			this.x = ((win_dim.width / 2) - this.width/2); // set the Grid x, y to the first quad's x, y
			this.y = ((win_dim.height / 2) - this.height/2);

			// grid_quad
			for (i = 0, max = this.quads.length; i < max; i++) {

				grid_quad = document.createElement('div');
				grid_quad.setAttribute('id', this.quads[i].id);

				for (key in this.styles) {
					if (this.styles.hasOwnProperty(key)) {
						grid_quad.style[key] = this.styles[key];
					}
				}

				document.body.appendChild(grid_quad);
			}

		},
		/**
		 * Creates a css rule for every position in the grid
		 * @param key
		 * @param value
		 *
		 */
		build : function () {

			var colNum, quad_width, quad_height, build_section_total, s, i, total_rules, max;

			colNum = 0;
			quad_width = BigBlock.Grid.width/2;
			quad_height = BigBlock.Grid.height/2;
			build_section_total = Math.round((quad_height/BigBlock.Grid.blk_dim))/2;

			s = document.styleSheets[document.styleSheets.length - 1];

			for (i = 0, max = ((Math.round(quad_width/BigBlock.Grid.blk_dim) * Math.round(quad_height/BigBlock.Grid.blk_dim)) / build_section_total); i < max; i++) {
				if (colNum < Math.round(quad_width/BigBlock.Grid.blk_dim)) {
					colNum++;
				} else {
					colNum = 1;
				}

				if (i % Math.round(quad_width/BigBlock.Grid.blk_dim) === 0) {
					this.build_rowNum++;
				}

				if (s.insertRule) { // Mozilla
					s.insertRule("." + BigBlock.CSSid_position + (i + this.build_offset) + " {left:" + ((colNum - 1) * this.blk_dim) + "px;top:" + ((this.build_rowNum - 1) * this.blk_dim) + "px;}", 0); // setup pos rules
				} else if (s.addRule) { // IE
					s.addRule("." + BigBlock.CSSid_position + (i + this.build_offset), " left:" + ((colNum - 1) * this.blk_dim) + "px;top:" + ((this.build_rowNum - 1) * this.blk_dim) + "px"); // setup pos rules
				}

			}

			// total_rules;
			try {

				if (s.cssRules) { // Mozilla
					total_rules = s.cssRules.length;
				} else if (s.rules) { // IE
					total_rules = s.rules.length;
				} else {
					throw new Error("BigBlock.Grid.build(): document.styleSheets rule count failed. Browser does not support cssRules.length() or rules.length().");
				}

			} catch(e) {
				BigBlock.Log.display(e.name + ": " + e.message);
			}

			this.build_offset = total_rules;

			BigBlock.Loader.update({
				"total" : Math.round((total_rules / (Math.round(quad_width/BigBlock.Grid.blk_dim) * Math.round(quad_height/BigBlock.Grid.blk_dim))) * 100)
			});

			if (total_rules < (Math.round(quad_width/BigBlock.Grid.blk_dim) * Math.round(quad_height/BigBlock.Grid.blk_dim))) { // if all styles are not complete, send false back to Timer; Timer will call build again
				return false;
			} else {
				return true;
			}
		},
		buildCharStyles : function () {

			var s, i, col_count, max;

			s = document.styleSheets[document.styleSheets.length - 1];

			if (s.insertRule) { // Mozilla
				s.insertRule("."+BigBlock.CSSid_text_bg+"{background-color: transparent;}", 0);
				s.insertRule("."+BigBlock.CSSid_char+"{width : 1px;height : 1px;position: absolute;float: left;line-height:0px;font-size:1%;}", 0);
			} else if (s.addRule) { // IE
				s.addRule("."+BigBlock.CSSid_text_bg, "background-color: transparent");
				s.addRule("."+BigBlock.CSSid_char, "width : 1px;height : 1px;position: absolute;float: left;line-height:0px;font-size:1%;");
			}

			col_count = 1;
			for (i = 0, max = this.char_width * this.char_height; i < max; i++) {

				if (s.insertRule) { // Mozilla
					s.insertRule("." + BigBlock.CSSid_char_pos + (i + 1) + "{left:" + col_count + "px;top:" + (Math.floor((i/8))+1) + "px;}", 0);
				} else if (s.addRule) { // IE
					s.addRule("." + BigBlock.CSSid_char_pos + (i + 1), "left:" + col_count + "px;top:" + (Math.floor((i/8))+1) + "px;");
				}

				if (col_count + 1 <= this.char_width) {
					col_count++;
				} else {
					col_count = 1;
				}
			}

			return true;
		}

	};

})();<|endoftext|>


<commit_before>'use strict';

const WorldstateObject = require('./WorldstateObject.js');

const updateReg = /(update|hotfix)/i;
const primeAccessReg = /(access)/i;
const streamReg = /(devstream|prime-time|warframeinternational)/i;

/**
 * Represents a game news item
 * @extends {WorldstateObject}
 */
class News extends WorldstateObject {
  /**
   * @param   {Object}             data            The news data
   * @param   {Object}             deps            The dependencies object
   * @param   {MarkdownSettings}   deps.mdConfig   The markdown settings
   * @param   {TimeDateFunctions}  deps.timeDate   The time and date functions
   */
  constructor(data, { mdConfig, timeDate }) {
    super(data);

    /**
     * The markdown settings
     * @type {MarkdownSettings}
     * @private
     */
    this.mdConfig = mdConfig;
    Object.defineProperty(this, 'mdConfig', { enumerable: false, configurable: false });

    /**
     * The time and date functions
     * @type {TimeDateFunctions}
     * @private
     */
    this.timeDate = timeDate;
    Object.defineProperty(this, 'timeDate', { enumerable: false, configurable: false });

    /**
     * The news message
     * @type {string}
     */
    this.message = data.Messages[0].Message;

    /**
     * The link to the forum post
     * @type {string}
     */
    this.link = data.Prop;

    /**
     * The news's image link
     * @type {string}
     */
    this.imageLink = data.ImageUrl || 'https://i.imgur.com/CNrsc7V.png';

    /**
     * Whether this has priority over other news or not
     * @type {boolean}
     */
    this.priority = data.Priority;

    /**
     * The date at which the post was published
     * @type {Date}
     */
    this.date = timeDate.parseDate(data.Date);

    /**
     * The date at which the event starts
     * @type {?Date}
     */
    this.startDate = data.EventStartDate
      ? timeDate.parseDate(data.EventStartDate)
      : undefined;

    /**
     * The date at which the event ends
     * @type {?Date}
     */
    this.endDate = data.EventEndDate
      ? timeDate.parseDate(data.EventEndDate)
      : undefined;

    /**
     * ETA string (at time of object creation)
     * @type {String}
     */
    this.eta = this.getETAString();

    /**
     * Whther or not this is an update news item
     * @type {boolean}
     */
    this.update = this.isUpdate();

    /**
     * Whther or not this is a prime access news item
     * @type {boolean}
     */
    this.primeAccess = this.isPrimeAccess();

    /**
     * Whether or not this is a stream
     * @type {boolean}
     */
    this.stream = this.isStream();

    /**
     * Translation of the news item
     * @type {Object.<string.<string>>
     */
    this.translations = {};
    data.Messages.forEach((message) => {
      this.translations[message.LanguageCode] = message.Message;
    });

    /**
     * The string representation of this object at creation
     * @type {string}
     */
    this.asString = this.toString();
  }

  /**
   * Get a string indicating how long it will take for the event to start or
   * how long it's been since the news went up
   * @returns {string}
   */
  getETAString() {
    if (this.endDate) {
      const timeDelta = this.timeDate.fromNow(this.endDate);
      return `in ${this.timeDate.timeDeltaToString(timeDelta)}`;
    }
    const timeDelta = this.timeDate.toNow(this.date);
    return `${this.timeDate.timeDeltaToString(timeDelta)} ago`;
  }

  /**
   * Whether or not this is about a game update
   * @returns {boolean}
   */
  isUpdate() {
    return updateReg.test(this.link);
  }

  /**
   * Whether or not this is about a new Prime Access
   * @returns {boolean}
   */
  isPrimeAccess() {
    return primeAccessReg.test(this.link);
  }

  /**
   * Whether or not this is about a new Prime Access
   * @returns {boolean}
   */
  isStream() {
    return streamReg.test(this.link);
  }

  /**
   * String representation
   * @returns {string}
   */
  toString() {
    return `[${this.getETAString()}] ${this.mdConfig.linkBegin}${this.message}` +
      `${this.mdConfig.linkMid}${this.link}${this.mdConfig.linkEnd}`;
  }
}

module.exports = News;
<commit_msg>Update News.js (#68)<commit_after>'use strict';

const WorldstateObject = require('./WorldstateObject.js');

const updateReg = /(update|hotfix)/i;
const primeAccessReg = /(access)/i;
const streamReg = /(devstream|prime-time|warframeinternational)/i;

/**
 * Represents a game news item
 * @extends {WorldstateObject}
 */
class News extends WorldstateObject {
  /**
   * @param   {Object}             data            The news data
   * @param   {Object}             deps            The dependencies object
   * @param   {MarkdownSettings}   deps.mdConfig   The markdown settings
   * @param   {TimeDateFunctions}  deps.timeDate   The time and date functions
   */
  constructor(data, { mdConfig, timeDate }) {
    super(data);

    /**
     * The markdown settings
     * @type {MarkdownSettings}
     * @private
     */
    this.mdConfig = mdConfig;
    Object.defineProperty(this, 'mdConfig', { enumerable: false, configurable: false });

    /**
     * The time and date functions
     * @type {TimeDateFunctions}
     * @private
     */
    this.timeDate = timeDate;
    Object.defineProperty(this, 'timeDate', { enumerable: false, configurable: false });

    /**
     * The news message
     * @type {string}
     */
    this.message = data.Messages[0].Message;

    /**
     * The link to the forum post
     * @type {string}
     */
    this.link = data.Prop;

    /**
     * The news's image link
     * @type {string}
     */
    this.imageLink = data.ImageUrl || 'https://i.imgur.com/CNrsc7V.png';

    /**
     * Whether this has priority over other news or not
     * @type {boolean}
     */
    this.priority = data.Priority;

    /**
     * The date at which the post was published
     * @type {Date}
     */
    this.date = timeDate.parseDate(data.Date);

    /**
     * The date at which the event starts
     * @type {?Date}
     */
    this.startDate = data.EventStartDate
      ? timeDate.parseDate(data.EventStartDate)
      : undefined;

    /**
     * The date at which the event ends
     * @type {?Date}
     */
    this.endDate = data.EventEndDate
      ? timeDate.parseDate(data.EventEndDate)
      : undefined;

    /**
     * ETA string (at time of object creation)
     * @type {String}
     */
    this.eta = this.getETAString();

    /**
     * Whther or not this is an update news item
     * @type {boolean}
     */
    this.update = this.isUpdate();

    /**
     * Whther or not this is a prime access news item
     * @type {boolean}
     */
    this.primeAccess = this.isPrimeAccess();

    /**
     * Whether or not this is a stream
     * @type {boolean}
     */
    this.stream = this.isStream();

    /**
     * Translation of the news item
     * @type {Object.<string.<string>>
     */
    this.translations = {};
    data.Messages.forEach((message) => {
      this.translations[message.LanguageCode] = message.Message;
    });

    /**
     * The string representation of this object at creation
     * @type {string}
     */
    this.asString = this.toString();
  }

  /**
   * Get a string indicating how long it will take for the event to start or
   * how long it's been since the news went up
   * @returns {string}
   */
  getETAString() {
    if (this.endDate) {
      const timeDelta = this.timeDate.fromNow(this.endDate);
      return `in ${this.timeDate.timeDeltaToString(timeDelta)}`;
    }
    const timeDelta = this.timeDate.toNow(this.date);
    return `${this.timeDate.timeDeltaToString(timeDelta)} ago`;
  }

  /**
   * Whether or not this is about a game update
   * @returns {boolean}
   */
  isUpdate() {
    return updateReg.test(this.link);
  }

  /**
   * Whether or not this is about a new Prime Access
   * @returns {boolean}
   */
  isPrimeAccess() {
    return primeAccessReg.test(this.link);
  }

  /**
   * Whether or not this is about a new Prime Access
   * @returns {boolean}
   */
  isStream() {
    return streamReg.test(this.link);
  }

  /**
   * String representation
   * @returns {string}
   */
  toString() {
    return `[${this.getETAString()}] ${this.mdConfig.linkBegin}${this.message}` +
      `${this.mdConfig.linkMid}${this.link}${this.mdConfig.linkEnd}`;
  }

  /**
  * The title of the new in the specified language
  * @param {string} langCode Ex. 'es', 'de', 'fr'
  * @returns {string}
  */
  getTitle(langCode) {
    return (langCode in this.translations) ? this.translations[langCode] : this.message;
  }
}

module.exports = News;
<|endoftext|>