<commit_before>const fs = require('fs');
const {ipcRenderer} = require('electron');
const Vue = require('vue');
const compiler = require('vue-template-compiler');

class ElectronVue extends Vue {
    constructor(...args) {
        if(args.length)
            ElectronVue.processArguments(args[0]);
        super(...args);
    }

    /**
     * This method processes any incoming arguments and supplements them
     * for ElectronVue's needs before any Vue initialization happens.
     * @param {object} args The object defining a Vue as passed into this object's constructor
     */
    static processArguments(args) {
        // This makes sure we have a data object and if
        // it's a function then it's converted to an object.
        // Converting the function to an object might limit the
        // ability of callers to implement more dynamic data setup
        // procedures.  This should probably be addressed in a future
        // release.
        if(!args.data)
            args.data = {};
        else if(typeof args.data != 'object')
            args.data = args.data();

        // mix ev object with defaults
        args.data.electronVue = Object.assign({
            errorText: 'EV Template Error',
            errorStyles: {
                color: '#fff',
                background: '#f50000',
                textAlign: 'center',
                padding: '10px',
                borderRadius: '4px'
            }
        }, args.data.electronVue);

        // if there's not already a render method then generate one from
        // the template attribute
        if(!args.render)
            Object.assign(args, ElectronVue.createRenderer(args.template));

        // register local components which just means to convert component
        // template attributes to render functions
        if(args.components)
            ElectronVue.processComponents(args.components);

        // register a callback to use for ipc registration once the vue has
        // been instantiated
        args.mixins = [{
            created() {
                if(args.ipc)
                    ElectronVue.ipcRegistration(this, args.ipc);
            }
        }];
    }

    /**
     * This function recusively loops through components and creates
     * render functions for template attributes.
     * @see {@link https://vuejs.org/v2/guide/components.html#Local-Registration}
     * @param {object} components Local registration component object
     */
    static processComponents(components) {
        for(let name in components) {
            let component = components[name];

            // register callbacks for each component so that their ipc callbacks
            // can be registered once each component has been instantiated
            component.mixins = [{
                created() {
                    if(component.ipc)
                        ElectronVue.ipcRegistration(this, component.ipc);
                }
            }];

            // if there's not a render method then generate one from the
            // template attribute
            if(!component.render)
                Object.assign(component, ElectronVue.createRenderer(component.template));

            // if this component has child components then recursively
            // register them too
            if(component.components)
                ElectronVue.processComponents(component.components);
        }
    }

    /**
     * This function adds the ability to reference html files
     * as templates in addition to the standard vue implementation.
     * @param {string} template Template value
     * @return {function} Vue render method
     */
    static createRenderer(template) {
        if(template && template.endsWith('.html')) {
            try {
                template = fs.readFileSync(template, 'utf-8');
            } catch(err) {
                console.error(err);
                template = '

';
            }
        }

        return compiler.compileToFunctions(template);
    }

    /**
     * This registers all functions as callbacks for the main process.
     * @param {object} thisArg A value to bind with callbacks so that they have an appropriate this.
     * @param {string} ipcCallbacks An object of callback methods to be registered.
     */
    static ipcRegistration(thisArg, ipc) {
        for(let name in ipc) {
            let callback = ipc[name];
            if(typeof callback == 'object')
                ipcRenderer.on(ElectronVue.toSpinalCase(callback.channel), callback.method.bind(thisArg));
            else
                ipcRenderer.on(ElectronVue.toSpinalCase(name), callback.bind(thisArg));
        }
    }

    /**
     * This function converts camelcase strings into spinalcase
     * by attempting to break the string into words based on
     * capitalization.
     * @param {string} value The camelcase value to convert.
     * @return {string} A spinalcase version of the camelcase value.
     */
    static toSpinalCase(value) {
        let words = [];
        let lower = false;
        let wasLower = lower;

        for(const c of value) {
            if(!words.length) {
                words.push([c]);
                if(c == c.toLowerCase()) {
                    lower = true;
                    wasLower = true;
                }
            } else {
                lower = false;
                if(c == c.toLowerCase())
                    lower = true;

                const lastWordIndex = words.length - 1;
                if(lower != wasLower) {
                    const lastWordLastIndex = words[lastWordIndex].length - 1;
                    const lastChar = words[lastWordIndex][lastWordLastIndex];

                    // Okay, this gets a little dicey.  If the last character of the
                    // last word is uppercase then some things need to be shuffled
                    // around a bit.  Otherwise, just start a new word with the
                    // current character as the first letter in the word.
                    if(lastChar == lastChar.toUpperCase()) {
                        // The last character of the previous word was uppercase.
                        // Therefore, remove it from the previous word and make it
                        // the first character in the new word.
                        words[lastWordIndex].pop();

                        // If the previous word is empty after removing the last
                        // character, then remove it from the list of words so that
                        // we don't end up with a blank word.
                        if(!words[lastWordIndex].length)
                            words.splice(lastWordIndex, 1);

                        // Lastly, push the last character of the previous word and
                        // the current character into a new word as the first two
                        // characters.
                        words.push([lastChar, c]);
                    } else
                        words.push([c]);
                } else
                    words[lastWordIndex].push(c);

                wasLower = lower;
            }
        }

        // This just takes the list of words and smashes them together to
        // produce a lowercase string with hyphens between each word.
        return words.map((word) => {
            return word.join('');
        }).join('-').toLowerCase();
    }
}

module.exports = ElectronVue;
<commit_msg>fixes #6 ipc callbacks are not managed during vue lifecycle events<commit_after>const fs = require('fs');
const {ipcRenderer} = require('electron');
const Vue = require('vue');
const compiler = require('vue-template-compiler');

class ElectronVue extends Vue {
    constructor(...args) {
        if(args.length)
            ElectronVue.processArguments(args[0]);
        super(...args);
    }

    /**
     * This method processes any incoming arguments and supplements them
     * for ElectronVue's needs before any Vue initialization happens.
     * @param {object} args The object defining a Vue as passed into this object's constructor
     */
    static processArguments(args) {
        // This makes sure we have a data object and if
        // it's a function then it's converted to an object.
        // Converting the function to an object might limit the
        // ability of callers to implement more dynamic data setup
        // procedures.  This should probably be addressed in a future
        // release.
        if(!args.data)
            args.data = {};
        else if(typeof args.data != 'object')
            args.data = args.data();

        // mix ev object with defaults
        args.data.electronVue = Object.assign({
            errorText: 'EV Template Error',
            errorStyles: {
                color: '#fff',
                background: '#f50000',
                textAlign: 'center',
                padding: '10px',
                borderRadius: '4px'
            }
        }, args.data.electronVue);

        // if there's not already a render method then generate one from
        // the template attribute
        if(!args.render)
            Object.assign(args, ElectronVue.createRenderer(args.template));

        // register local components which just means to convert component
        // template attributes to render functions
        if(args.components)
            ElectronVue.processComponents(args.components);

        // register a callback to use for ipc registration once the vue has
        // been instantiated
        args.mixins = [{
            created() {
                if(args.ipc)
                    ElectronVue.ipcRegistration(this, args.ipc);
            },
            destroyed() {
                if(args.ipc)
                    ElectronVue.ipcRemoveListeners(this, args.ipc);
            }
        }];
    }

    /**
     * This function recusively loops through components and creates
     * render functions for template attributes.
     * @see {@link https://vuejs.org/v2/guide/components.html#Local-Registration}
     * @param {object} components Local registration component object
     */
    static processComponents(components) {
        for(let name in components) {
            let component = components[name];

            // register callbacks for each component so that their ipc callbacks
            // can be registered once each component has been instantiated
            component.mixins = [{
                created() {
                    if(component.ipc)
                        ElectronVue.ipcRegistration(this, component.ipc);
                },
                destroyed() {
                    if(component.ipc)
                        ElectronVue.ipcRemoveListeners(this, component.ipc);
                }
            }];

            // if there's not a render method then generate one from the
            // template attribute
            if(!component.render)
                Object.assign(component, ElectronVue.createRenderer(component.template));

            // if this component has child components then recursively
            // register them too
            if(component.components)
                ElectronVue.processComponents(component.components);
        }
    }

    /**
     * This function adds the ability to reference html files
     * as templates in addition to the standard vue implementation.
     * @param {string} template Template value
     * @return {function} Vue render method
     */
    static createRenderer(template) {
        if(template && template.endsWith('.html')) {
            try {
                template = fs.readFileSync(template, 'utf-8');
            } catch(err) {
                console.error(err);
                template = '

';
            }
        }

        return compiler.compileToFunctions(template);
    }

    /**
     * This registers all functions as callbacks for the main process.
     * @param {object} thisArg A value to bind with callbacks so that they have an appropriate this.
     * @param {string} ipcCallbacks An object of callback methods to be registered.
     */
    static ipcRegistration(thisArg, ipc) {
        thisArg.$electronVue = {
            ipcCallbacks: []
        };

        for(const name in ipc) {
            const callback = ipc[name];
            let channel = ElectronVue.toSpinalCase(name);
            let boundCallback = callback.bind(thisArg);
            if(typeof callback == 'object') {
                channel = ElectronVue.toSpinalCase(callback.channel);
                boundCallback = callback.method.bind(thisArg);
            }

            thisArg.$electronVue.ipcCallbacks.push({channel: channel, method: boundCallback});
            ipcRenderer.on(channel, boundCallback);
        }
    }

    /**
     * This unregisters all ipc callback methods currently registered for this instance.  In other words,
     * this removes all channels previously registered with the ipcRenderer.
     * @param {object} thisArg The vue instance containing registered ipc callbacks.
     */
    static ipcRemoveListeners(thisArg) {
        if(thisArg.$electronVue && this.$electronVue.ipcCallbacks) {
            for(const callback of thisArg.$electronVue.ipcCallback) {
                ipcRenderer.removeListener(callback.channel, callback.method);
            }
        }
    }

    /**
     * This function converts camelcase strings into spinalcase
     * by attempting to break the string into words based on
     * capitalization.
     * @param {string} value The camelcase value to convert.
     * @return {string} A spinalcase version of the camelcase value.
     */
    static toSpinalCase(value) {
        let words = [];
        let lower = false;
        let wasLower = lower;

        for(const c of value) {
            if(!words.length) {
                words.push([c]);
                if(c == c.toLowerCase()) {
                    lower = true;
                    wasLower = true;
                }
            } else {
                lower = false;
                if(c == c.toLowerCase())
                    lower = true;

                const lastWordIndex = words.length - 1;
                if(lower != wasLower) {
                    const lastWordLastIndex = words[lastWordIndex].length - 1;
                    const lastChar = words[lastWordIndex][lastWordLastIndex];

                    // Okay, this gets a little dicey.  If the last character of the
                    // last word is uppercase then some things need to be shuffled
                    // around a bit.  Otherwise, just start a new word with the
                    // current character as the first letter in the word.
                    if(lastChar == lastChar.toUpperCase()) {
                        // The last character of the previous word was uppercase.
                        // Therefore, remove it from the previous word and make it
                        // the first character in the new word.
                        words[lastWordIndex].pop();

                        // If the previous word is empty after removing the last
                        // character, then remove it from the list of words so that
                        // we don't end up with a blank word.
                        if(!words[lastWordIndex].length)
                            words.splice(lastWordIndex, 1);

                        // Lastly, push the last character of the previous word and
                        // the current character into a new word as the first two
                        // characters.
                        words.push([lastChar, c]);
                    } else
                        words.push([c]);
                } else
                    words[lastWordIndex].push(c);

                wasLower = lower;
            }
        }

        // This just takes the list of words and smashes them together to
        // produce a lowercase string with hyphens between each word.
        return words.map((word) => {
            return word.join('');
        }).join('-').toLowerCase();
    }
}

module.exports = ElectronVue;
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var Funnel = require('broccoli-funnel');
var mergeTrees = require('broccoli-merge-trees');
var path = require('path');
var esTranspiler = require('broccoli-babel-transpiler');
const concat = require('broccoli-concat');
var packageDependencies = require("./package.json")['dependencies'];
var Filter = require('broccoli-filter');

function UMDToAMDRewriteFilter(inputNode, packageName, options) {
  options = options || {};
  Filter.call(this, inputNode, {
    annotation: options.annotation
  });
  this.packageName = packageName;
}

UMDToAMDRewriteFilter.prototype = Object.create(Filter.prototype);
UMDToAMDRewriteFilter.prototype.constructor = UMDToAMDRewriteFilter;

function createAMDHeader() {
  return "  // ember-cli-d3-primitive: Insert a fake AMD definition so that Ember's loader.js loads this UMD build.\n" +
         "  define.amd = true;";
}

UMDToAMDRewriteFilter.prototype.processString = function(content) {
  var lines = content.split(/\n/);
  var header = createAMDHeader();
  lines.splice(1, 0, header);
  lines.splice(5, 0, "  delete define.amd;");
  return lines.join("\n");
};

module.exports = {
  isDevelopingAddon: function(){
    return true;
  },

  name: 'd3',

  d3Modules: [
    // Imported from package.json
    // 'd3-transition', // Disabled until this is ported from d3 properly
  ],

  included: function(app) {
    this._super.included.apply(this, arguments);
    this.app = app;

    this.d3Modules = [];

    for (var packageName in packageDependencies) {
      if (packageDependencies.hasOwnProperty(packageName)) {
        if (/^d3\-/.test(packageName)) {
          this.d3Modules.push(packageName);
        }
      }
    }

    this.d3Modules.forEach(function(packageName) {
      app.import(path.join('vendor', packageName, packageName + '.js'));
    });
  },

  compileSourceTree: function(src, packageName) {
    var srcTree = new Funnel(src, {
      include: ['src/**/*.js', 'index.js'],
      destDir: '/' + packageName,
      annotation: 'Funnel: D3 Source ['+ packageName + ']'
    });

    return esTranspiler(srcTree, {
      persist: false,

      stage: 0,
      moduleIds: true,
      modules: 'amd',

      comments: true,
      compact: false,
      loose: false,

      moduleRoot: packageName,

      getModuleId: function (name) {
        name = name
          .replace(/\/index$/, '')
          .replace(/\/src/, '');
        return name;
      },

      resolveModuleSource: function (source, filename) {
        if (/\.\//.test(source)) {
          // This is a relative import from within the package
          var newPath = path.resolve("/", filename, "..", source)
            .replace(/\/src/, '')
            .replace(/^\//, '');

          return newPath;
        }else{
          // This is *probably* an import for another package.
          return source;
        }
      }
    }, {
      annotation: 'Transpile D3 source to AMD ['+ packageName+ ']',
    });
  },

  treeForVendor: function(tree) {
    var trees = [];

    if (tree) { trees.push(tree); }

    this.d3Modules.forEach(function(packageName) {
      let importFileBaseName = path.parse(require.resolve(packageName)).name;
      var d3PathToSrc, srcTree;

      if (importFileBaseName === 'index') {
        d3PathToSrc = require.resolve(packageName).replace(/index\.js$/, '');
        srcTree = this.compileSourceTree(path.join(d3PathToSrc), packageName);
      }else{
        var packageBuildPath = path.join('build', packageName + '.js');
        d3PathToSrc = require.resolve(packageName).replace(packageBuildPath, '');
        var tree = new Funnel(d3PathToSrc, {
          include: [packageBuildPath],
          destDir: '/' + packageName,
          annotation: 'Funnel: D3 Source ['+ packageName + ']'
        });

        srcTree = new UMDToAMDRewriteFilter(tree, packageName);
      }

      trees.push(concat(srcTree, {
        inputFiles: [
          '**/**/*.js',
        ],
        outputFile: '/' + packageName + '/' + packageName + '.js'
      }));
    });

    return mergeTrees(trees);
  }
};
<commit_msg>Try trailing slash<commit_after>/* jshint node: true */
'use strict';

var Funnel = require('broccoli-funnel');
var mergeTrees = require('broccoli-merge-trees');
var path = require('path');
var esTranspiler = require('broccoli-babel-transpiler');
const concat = require('broccoli-concat');
var packageDependencies = require("./package.json")['dependencies'];
var Filter = require('broccoli-filter');

function UMDToAMDRewriteFilter(inputNode, packageName, options) {
  options = options || {};
  Filter.call(this, inputNode, {
    annotation: options.annotation
  });
  this.packageName = packageName;
}

UMDToAMDRewriteFilter.prototype = Object.create(Filter.prototype);
UMDToAMDRewriteFilter.prototype.constructor = UMDToAMDRewriteFilter;

function createAMDHeader() {
  return "  // ember-cli-d3-primitive: Insert a fake AMD definition so that Ember's loader.js loads this UMD build.\n" +
         "  define.amd = true;";
}

UMDToAMDRewriteFilter.prototype.processString = function(content) {
  var lines = content.split(/\n/);
  var header = createAMDHeader();
  lines.splice(1, 0, header);
  lines.splice(5, 0, "  delete define.amd;");
  return lines.join("\n");
};

module.exports = {
  isDevelopingAddon: function(){
    return true;
  },

  name: 'd3',

  d3Modules: [
    // Imported from package.json
    // 'd3-transition', // Disabled until this is ported from d3 properly
  ],

  included: function(app) {
    this._super.included.apply(this, arguments);
    this.app = app;

    this.d3Modules = [];

    for (var packageName in packageDependencies) {
      if (packageDependencies.hasOwnProperty(packageName)) {
        if (/^d3\-/.test(packageName)) {
          this.d3Modules.push(packageName);
        }
      }
    }

    this.d3Modules.forEach(function(packageName) {
      app.import(path.join('vendor', packageName, packageName + '.js'));
    });
  },

  compileSourceTree: function(src, packageName) {
    var srcTree = new Funnel(src, {
      include: ['src/**/*.js', 'index.js'],
      destDir: '/' + packageName,
      annotation: 'Funnel: D3 Source ['+ packageName + ']'
    });

    return esTranspiler(srcTree, {
      persist: false,

      stage: 0,
      moduleIds: true,
      modules: 'amd',

      comments: true,
      compact: false,
      loose: false,

      moduleRoot: packageName,

      getModuleId: function (name) {
        name = name
          .replace(/\/index$/, '')
          .replace(/\/src/, '');
        return name;
      },

      resolveModuleSource: function (source, filename) {
        if (/\.\//.test(source)) {
          // This is a relative import from within the package
          var newPath = path.resolve("/", filename, "..", source)
            .replace(/\/src/, '')
            .replace(/^\//, '');

          return newPath;
        }else{
          // This is *probably* an import for another package.
          return source;
        }
      }
    }, {
      annotation: 'Transpile D3 source to AMD ['+ packageName+ ']',
    });
  },

  treeForVendor: function(tree) {
    var trees = [];

    if (tree) { trees.push(tree); }

    this.d3Modules.forEach(function(packageName) {
      let importFileBaseName = path.parse(require.resolve(packageName)).name;
      var d3PathToSrc, srcTree;

      if (importFileBaseName === 'index') {
        d3PathToSrc = require.resolve(packageName).replace(/index\.js$/, '');
        srcTree = this.compileSourceTree(path.join(d3PathToSrc), packageName);
      }else{
        var packageBuildPath = path.join('build', packageName + '.js');
        d3PathToSrc = require.resolve(packageName).replace(packageBuildPath, '');
        var tree = new Funnel(d3PathToSrc, {
          include: [packageBuildPath],
          destDir: '/' + packageName + "/",
          annotation: 'Funnel: D3 Source ['+ packageName + ']'
        });

        srcTree = new UMDToAMDRewriteFilter(tree, packageName);
      }

      trees.push(concat(srcTree, {
        inputFiles: [
          '**/**/*.js',
        ],
        outputFile: '/' + packageName + '/' + packageName + '.js'
      }));
    });

    return mergeTrees(trees);
  }
};
<|endoftext|>


<commit_before>const findVersions        = require('find-versions')
const githubBasic         = require('github-basic')
const githubFromPackage   = require('github-from-package')
const githubUrlToObject   = require('github-url-to-object')
const got                 = require('got')
const {lt, maxSatisfying} = require('semver')
const striptags           = require('striptags')

const messagePrefix = 'Update to '

function getVersionDirectoryIndex(data)
{
  // Search all the semver strings on the text and get the highest
  // non-prerelease one
  return maxSatisfying(findVersions(striptags(data.toString())), '')
}

function getVersionGithub(data)
{
  // Search all the semver strings on the text and get the highest
  // non-prerelease one
  return maxSatisfying(findVersions(striptags(data.toString())), '')
}

/**
 * Get latest version of Node.js
 */
function getVersionNode(data)
{
  return JSON.parse(data)[0].version.slice(1)
}

function Buho(PKG, auth)
{
  if(!(this instanceof Buho)) return new Buho(PKG, auth)

  const userRepo = githubUrlToObject(githubFromPackage(PKG))
  const user = userRepo.user
  const repo = userRepo.repo

  const options =
  {
    version: 3,
    auth: auth
  }

  const client = githubBasic(options)

  /**
   * Check latest version
   */
  this.check = function(type, url)
  {
    switch(type)
    {
      case 'DirectoryIndex':
        var getLatestVersion = getVersionDirectoryIndex
      break

      case 'Github':
        var getLatestVersion = getVersionGithub
      break

      case 'nodejs':
        var getLatestVersion = getVersionNode
      break

      default:
        throw 'Unnkown type "'+type+'"'
    }

    return got(url).then(function(res)
    {
      const latest = getLatestVersion(res.body)

      if(lt(PKG.version, latest)) return latest
    })
  }

  /**
   * Update version of `package.json` and create a pull-request
   */
  this.update = function(version)
  {
    PKG.version = version

    const message = messagePrefix+version
    const branch  = message.split(' ').join('_')

    return client.branch(user, repo, 'master', branch)
    .then(function()
    {
      const commit =
      {
        branch: branch,
        message: message,
        updates:
        [
          {
            path: 'package.json',
            content: JSON.stringify(PKG, null, 2)
          }
        ]
      }

      return client.commit(user, repo, commit)
    })
    .then(function()
    {
      return client.pull({user, repo, branch}, {user, repo}, {title: message})
    })
  }

  /**
   * Merge the pull-request with the `master` branch and delete it
   */
  this.merge = function(branch)
  {
    return client.merge(user, repo, branch)
    .then(function()
    {
      return client.deleteBranch(user, repo, branch)
    })
  }
}

Buho.messagePrefix = messagePrefix

module.exports = Buho
<commit_msg>Fetch and update sha256 from `sha256sums.asc` file<commit_after>const findVersions        = require('find-versions')
const githubBasic         = require('github-basic')
const githubFromPackage   = require('github-from-package')
const githubUrlToObject   = require('github-url-to-object')
const got                 = require('got')
const {lt, maxSatisfying} = require('semver')
const striptags           = require('striptags')

const messagePrefix = 'Update to '

function getVersionDirectoryIndex(data)
{
  // Search all the semver strings on the text and get the highest
  // non-prerelease one
  return maxSatisfying(findVersions(striptags(data.toString())), '')
}

function getVersionGithub(data)
{
  // Search all the semver strings on the text and get the highest
  // non-prerelease one
  return maxSatisfying(findVersions(striptags(data.toString())), '')
}

/**
 * Get latest version of Node.js
 */
function getVersionNode(data)
{
  return JSON.parse(data)[0].version.slice(1)
}

function Buho(PKG, auth)
{
  if(!(this instanceof Buho)) return new Buho(PKG, auth)

  async function updateSha256(version)
  {
    return await got(`${PKG.buho.url}/sha256sums.asc`)
    .then(function({body})
    {
      return body.toString().split('\n')
      .map(function(element)
      {
        return element.split(/\s+/)
      })
      .find(function([, filename])
      {
        return filename === `linux-${version}.tar.gz`
      })
    })
    .then(function([sha256])
    {
      return sha256
    })
  }

  const userRepo = githubUrlToObject(githubFromPackage(PKG))
  const user = userRepo.user
  const repo = userRepo.repo

  const options =
  {
    version: 3,
    auth: auth
  }

  const client = githubBasic(options)

  /**
   * Check latest version
   */
  this.check = function(type, url)
  {
    switch(type)
    {
      case 'DirectoryIndex':
        var getLatestVersion = getVersionDirectoryIndex
      break

      case 'Github':
        var getLatestVersion = getVersionGithub
      break

      case 'nodejs':
        var getLatestVersion = getVersionNode
      break

      default:
        throw 'Unnkown type "'+type+'"'
    }

    return got(url).then(function(res)
    {
      const latest = getLatestVersion(res.body)

      if(lt(PKG.version, latest)) return latest
    })
  }

  /**
   * Update version of `package.json` and create a pull-request
   */
  this.update = function(version)
  {
    PKG.version = version

    const {buho: {sha256} = {}} = PKG
    if(sha256) PKG.buho.sha256 = updateSha256(version)

    const message = messagePrefix+version
    const branch  = message.split(' ').join('_')

    return client.branch(user, repo, 'master', branch)
    .then(function()
    {
      const commit =
      {
        branch: branch,
        message: message,
        updates:
        [
          {
            path: 'package.json',
            content: JSON.stringify(PKG, null, 2)
          }
        ]
      }

      return client.commit(user, repo, commit)
    })
    .then(function()
    {
      return client.pull({user, repo, branch}, {user, repo}, {title: message})
    })
  }

  /**
   * Merge the pull-request with the `master` branch and delete it
   */
  this.merge = function(branch)
  {
    return client.merge(user, repo, branch)
    .then(function()
    {
      return client.deleteBranch(user, repo, branch)
    })
  }
}

Buho.messagePrefix = messagePrefix

module.exports = Buho
<|endoftext|>


<commit_before>var fs = require('fs');

var Parser = function(){

}

Parser.init = function(filePath){
  var file;
  try {
    file = fs.readFileSync(filePath);
  } catch (e) {
    console.log('bad');
    throw new Error('BAAAAAD');
  }

  return {
  };
}

module.exports = Parser;
<commit_msg>methods<commit_after>var fs = require('fs');

var Parser = function(){

}

/**
 * returns the header objects
 *
 * @returns {Object} Key value pairs containing the header info
 */
Parser.prototype.getHeader = function(){
  var header = {
    type: '',
    size: 0,
    data:{
      start: null,
      end: null,
      size: 0,
      endianess: null
    },
    analysis: {
      start: null,
      end: null
    }
  };
  return header;
};

/**
 * return parameters object
 *
 * @returns {Object} key value pairs param name param value
 */
Parser.prototype.getParams(){
  var params = {}

  return params;
};

Parser.init = function(filePath){
  var file;
  try {
    file = fs.readFileSync(filePath);
  } catch (e) {
    console.log('bad');
    throw new Error('BAAAAAD');
  }

  return new Parser(file);
}

module.exports = Parser;
<|endoftext|>


<commit_before>var useragent = require('express-useragent'),
  transientAnalytics = require('./lib/transientAnalytics'),
  persistentAnalytics = require('./lib/persistentAnalytics');

exports.model = {
  Total: require('./models/total').modelFactory,
  TotalMinute: require('./models/totalMinute').modelFactory
};

exports.core = {
  transientAnalytics: transientAnalytics,
  persistentAnalytics: persistentAnalytics
};

exports.middleware = [
  function(mwc) {
    persistentAnalytics.initializeModels(mwc.model.Total, mwc.model.TotalMinute);
    persistentAnalytics.startTimer(2000);
    return useragent.express();
  },
  function(mwc) {
    transientAnalytics.useRedis(mwc.redisClient);
    return transientAnalytics.store;
  }
];

exports.routes = function(mwc) {
  mwc.app.get('/analytics/:site/hotpixel.png', function(request, response) {
    response.set('Cache-Control', 'no-cache, no-store, must-revalidate');
    response.set('Pragma', 'no-cache');
    response.set('Expires', 0);
    response.sendfile(__dirname + '/public/img/hotpixel.png');
  });
};
<commit_msg>[fix] - more usefull hotpixel and some insights how to make it more usefull<commit_after>var useragent = require('express-useragent'),
  transientAnalytics = require('./lib/transientAnalytics'),
  persistentAnalytics = require('./lib/persistentAnalytics');

exports.model = {
  Total: require('./models/total').modelFactory,
  TotalMinute: require('./models/totalMinute').modelFactory
};

exports.core = {
  transientAnalytics: transientAnalytics,
  persistentAnalytics: persistentAnalytics
};

exports.middleware = [
  function(mwc) {
    persistentAnalytics.initializeModels(mwc.model.Total, mwc.model.TotalMinute);
    persistentAnalytics.startTimer(2000);
    return useragent.express();
  },
  function(mwc) {
    transientAnalytics.useRedis(mwc.redisClient);
    return transientAnalytics.store;
  }
];

exports.routes = function(mwc) {
  mwc.app.get(/^\/analytics\/([\/0-9a-z\.]+)\/hotpixel.png$/, function(request, response) {
    //we react on site name like this
    /*
     /analytics/somesite.org/mega/hotpixel.png -> somesite.org/mega
     /analytics/somesite.org/hotpixel.png -> somesite.org
     /analytics/localhost/hotpixel.png -> localhost
    */

    var siteName = request.params[0]; // this is sitename parsed from url, we can process it
    var referrerUrl = request.header('Referer'); //http://expressjs.com/api.html#req.get

    //for hitpixels referer is USUALLY the URL of page, where it is placed,
    //if referrer !=siteName - means somebody places referrer on 3rd party site to fake the statistics

    var refregex=new RegExp('/'+siteName+'/','i');
    if(refregex.test(referrerUrl)){
      //this is correct hotpixel
    } else {
      //this is cheating!
    }

    response.set('Cache-Control', 'no-cache, no-store, must-revalidate');
    response.set('Pragma', 'no-cache');
    response.set('Expires', 0);
    response.sendfile(__dirname + '/public/img/hotpixel.png');
  });
};
<|endoftext|>


<commit_before>var express  = require('express');
var mongoose = require('mongoose');
var lingo    = require('lingo');

var BASE_URI = '/api/'; // TODO config

var model = function(schema) {
  return mongoose.models[schema.metadata('singular')];
};

var get = function(schema) {
  // retrieve the addressed document
  var r = function(request, response, next) {
    var id = request.params.id;
    model(schema).findById(id).run(function (err, doc) {
      if (err) return response.send(500); // TODO ?
      if (doc === null) return response.send(404);
      return response.json(doc);
    });
  };

  return r;
};

var post = function(schema) {
  // treat the addressed document as a collection, and push the addressed object to it (?)
  var r = function (request, response, next) {
    response.send(405); // method not allowed (as of yet unimplemented)	 ???
  };

  return r;
};

var put = function (schema) {
  // replace the addressed document, or create it if nonexistant
  var r = function(request, response, next) {
    var id  = request.params.id || null;

    model(schema).update({_id: id}, request.body, {upsert: true}, function (err, doc) {
      if (err) return next(err);
      response.send(200);
    });
  };

  return r;
};

var del = function (schema) {
  // delete the addressed object
  var r = function (request, response, next) {
    var id = request.params.id;
    model(schema).remove({ _id: id }).run( function (err, count) {
      if (err) return next(err);
      response.json(count);
    });
  };

  return r;
};

var pluralGet = function (schema) {
  // retrieve documents matching conditions
  var r = function (request, response, next) {
    var conditions = request.body || {};
    var query = model(schema).find(conditions);
    query.exec(function(err, docs) {
      if (err) return next(err);
      response.json(docs);
    });
  };

  return r;
};

var pluralPost = function (schema) {
  // create a new document and return its ID
  var r = function(request, response, next) {
    var given = request.body || [];

    if (!Array.isArray(given)) given = [given];

    var docs = given.map( function(e) {
      return new (model(schema))(e);
    });

    var ids = [];

    docs.forEach( function (doc) {
      doc.save(function (err, doc) {
	if (err) return next(err);
	ids.push(doc._id);
	if (ids.length === docs.length) response.json(ids);
      });
    });
  };

  return r;
};

var pluralPut = function (schema) {
  // repalce all docs with given docs ...
  var r = function (request, response, next) {
    response.send(405); // method not allowed (as of yet unimplemented)	 ???
  };

  return r;
};

var pluralDel = function (schema) {
  // delete all documents matching conditions
  var r = function(request, response, next) {
    var conditions = request.body || {};
    var query = model(schema).remove(conditions);
    query.exec(function (err, count) {
      if (err) return next(err);
      response.json(count);
    });
  };

  return r;
};

express.HTTPServer.prototype.rest =
express.HTTPSServer.prototype.rest = function (schemata) {
  if (!Array.isArray(schemata)) {
    // if array leave alone, otherwise
    if (schemata.paths) {
      // single schema -> array
      schemata = [schemata];
    }
    else {
      // hash -> array
      schemata = Object.keys(schemata).map( function (key) {
	return schemata[key];
      });
    }
  }

  var app = this;

  schemata.forEach( function (schema) {
    var singular    = schema.metadata('singular');
    var plural      = schema.metadata('plural') || lingo.pluralize(singular);
    var singularUrl = BASE_URI + singular + '/:id';
    var pluralUrl   = BASE_URI + plural + '/';
    var middleware  = schema.metadata('middleware') || [];

    // add if not already present
    if (!model(schema)) {
      mongoose.model(singular, schema, plural);
    }

    app.get(singularUrl,  middleware, get(schema));
    app.post(singularUrl, middleware, post(schema));
    app.put(singularUrl,  middleware, put(schema));
    app.del(singularUrl,  middleware, del(schema));

    app.get(pluralUrl,  middleware, pluralGet(schema));
    app.post(pluralUrl, middleware, pluralPost(schema));
    app.put(pluralUrl,  middleware, pluralPut(schema));
    app.del(pluralUrl,  middleware, pluralDel(schema));
  });
};

mongoose.Schema.prototype.metadata = function (data) {
  if(!data)                             return this._metadata;
  if(data && typeof(data) === 'string') return this._metadata[data];

  if(data && typeof(data) === 'object') {
    if (this._metadata) throw new Error('Metadata was already set');
    return this._metadata = data;
  }

  throw new Error('Unrecognized use of metadata method');
};
<commit_msg>Update for Express 3 (probably breaks tests)<commit_after>var express  = require('express');
var mongoose = require('mongoose');
var lingo    = require('lingo');

var BASE_URI = '/api/'; // TODO config

var model = function(schema) {
  return mongoose.model(schema.metadata('singular'));
};

var get = function(schema) {
  // retrieve the addressed document
  var r = function(request, response, next) {
    var id = request.params.id;
    model(schema).findById(id).run(function (err, doc) {
      if (err) return response.send(500); // TODO ?
      if (doc === null) return response.send(404);
      return response.json(doc);
    });
  };

  return r;
};

var post = function(schema) {
  // treat the addressed document as a collection, and push the addressed object to it (?)
  var r = function (request, response, next) {
    response.send(405); // method not allowed (as of yet unimplemented)	 ??? //TODO or 501?
  };

  return r;
};

var put = function (schema) {
  // replace the addressed document, or create it if nonexistant
  var r = function(request, response, next) {
    var id  = request.params.id || null;

    model(schema).update({_id: id}, request.body, {upsert: true}, function (err, doc) {
      if (err) return next(err);
      response.send(200); // TODO send 201 when creating or 200/204 when updating
    });
  };

  return r;
};

var del = function (schema) {
  // delete the addressed object
  var r = function (request, response, next) {
    var id = request.params.id;
    model(schema).remove({ _id: id }).run( function (err, count) {
      if (err) return next(err);
      response.json(count);
    });
  };

  return r;
};

var pluralGet = function (schema) {
  // retrieve documents matching conditions
  var r = function (request, response, next) {
    var conditions = request.body || {};
    var query = model(schema).find(conditions);
    query.exec(function(err, docs) {
      if (err) return next(err);
      response.json(docs);
    });
  };

  return r;
};

var pluralPost = function (schema) {
  // create a new document and return its ID
  var r = function(request, response, next) {
    if (!request.body || request.body.length === 0) {
      return next(new Error('Must supply a document or array to POST'));
    }

    var ids   = [];
    var given = request.body;
    if (!Array.isArray(given)) given = [given];

    var docs = given.map( function(e) {
      return new (model(schema))(e);
    });

    response.statusCode = 201;

    docs.forEach( function (doc) {
      doc.save(function (err, doc) {
	if (err) return next(err);
	ids.push(doc._id);
	if (ids.length === docs.length) response.json(ids);
      });
    });
  };

  return r;
};

var pluralPut = function (schema) {
  // repalce all docs with given docs ...
  var r = function (request, response, next) {
    response.send(405); // method not allowed (as of yet unimplemented)	 ??? // TODO 501?
  };

  return r;
};

var pluralDel = function (schema) {
  // delete all documents matching conditions
  var r = function(request, response, next) {
    var conditions = request.body || {};
    var query = model(schema).remove(conditions);
    query.exec(function (err, count) {
      if (err) return next(err);
      response.json(count);
    });
  };

  return r;
};

module.exports = {};

// TODO maybe check if express.HTTPServer exists and hook that up for backward compat.

module.exports.rest = function (app, schemata) {
  if (!Array.isArray(schemata)) {
    // if array leave alone, otherwise
    if (schemata.paths) {
      // single schema -> array
      schemata = [schemata];
    }
    else {
      // hash -> array
      schemata = Object.keys(schemata).map( function (key) {
	return schemata[key];
      });
    }
  }

  schemata.forEach( function (schema) {
    var singular    = schema.metadata('singular');
    var plural      = schema.metadata('plural') || lingo.pluralize(singular);
    var singularUrl = BASE_URI + singular + '/:id';
    var pluralUrl   = BASE_URI + plural + '/';
    var middleware  = schema.metadata('middleware') || [];

    // add if not already present
    if (!model(schema)) {
      mongoose.model(singular, schema, plural);
    }

//    app.head(singularUrl, middleware, head(schema)); // TODO
    app.get(singularUrl,  middleware, get(schema));
    app.post(singularUrl, middleware, post(schema));
    app.put(singularUrl,  middleware, put(schema));
    app.del(singularUrl,  middleware, del(schema));

//    app.head(pluralUrl, middleware, pluralHead(schema)); // TODO
    app.get(pluralUrl,  middleware, pluralGet(schema));
    app.post(pluralUrl, middleware, pluralPost(schema));
    app.put(pluralUrl,  middleware, pluralPut(schema));
    app.del(pluralUrl,  middleware, pluralDel(schema));
  });
};

mongoose.Schema.prototype.metadata = function (data) {
  if(!data)                             return this._metadata;
  if(data && typeof(data) === 'string') return this._metadata[data];

  if(data && typeof(data) === 'object') {
    if (this._metadata) throw new Error('Metadata was already set');
    return this._metadata = data;
  }

  throw new Error('Unrecognized use of metadata method');
};
<|endoftext|>


<commit_before>var transformTools = require('browserify-transform-tools');

module.exports = transformTools.makeRequireTransform('literalify', {}, function(args, opts, cb) {
  if (opts.config && args[0] in opts.config) {
    return cb(null, opts.config[args[0]]);
  } else {
    return cb();
  }
});
<commit_msg>Fixed JSON handling.<commit_after>var transformTools = require('browserify-transform-tools');

module.exports = transformTools.makeRequireTransform('literalify', {excludeExtensions: ['json']}, function(args, opts, cb) {
  if (opts.config && args[0] in opts.config) {
    return cb(null, opts.config[args[0]]);
  } else {
    return cb();
  }
});
<|endoftext|>


<commit_before>goog.provide('ngeo.ScaleselectorController');
goog.provide('ngeo.ScaleselectorOptions');
goog.provide('ngeo.scaleselectorDirective');

goog.require('ngeo');
goog.require('ol.array');
goog.require('ol.Map');
goog.require('ol.Object');
goog.require('ol.events');

ngeo.module.value('ngeoScaleselectorTemplateUrl',
    /**
     * @param {angular.JQLite} element Element.
     * @param {angular.Attributes} attrs Attributes.
     * @return {string} Template URL.
     */
    function(element, attrs) {
      var templateUrl = attrs['ngeoScaleselectorTemplateurl'];
      return templateUrl !== undefined ? templateUrl :
          ngeo.baseTemplateUrl + '/scaleselector.html';
    });

/**
 * @typedef {{dropup: (boolean|undefined)}}
 */
ngeo.ScaleselectorOptions;

/**
 * Provides the "ngeoScaleselector" directive, a widget for
 * selecting map scales.
 *
 * Example:
 *
 *

 *

 *
 * The expression passed to the ngeo-scaleselector attribute should return an
 * object of this form:
 *
 *     {
 *       '0': $sce.trustAsHtml('1 : 200\'000\'000'),
 *       '1': $sce.trustAsHtml('1 : 100\'000\'000'),
 *       '2': $sce.trustAsHtml('1 : 50\'000\'000'),
 *       '3': $sce.trustAsHtml('1 : 25\'000\'000'),
 *       '4': $sce.trustAsHtml('1 : 12\'000\'000')
 *     }
 *
 * This object's keys are strings representing zoom levels, the values are
 * strings representing scales. The directive's partial uses ng-bind-html so
 * the scale strings should be trusted.
 *
 * That directive's partial uses Bootstrap's `dropdown` and `dropdown-menu`
 * classes, and `data-toggle="dropdown"`, so it is meant to be used with
 * Bootstrap's "dropdown" jQuery plugin.
 *
 * By default the directive uses "scaleselector.html" as its templateUrl. This
 * an be changed by redefining the "ngeoScaleselectorTemplateUrl" value.
 *
 * The directive has its own scope, but it is not isolate scope. That scope
 * includes a reference to the directive's controller: the "scaleselectorCtrl"
 * scope property.
 *
 * The directive doesn't create any watcher. In particular the object including
 * the scales information is now watched.
 *
 * @htmlAttribute {Object.<string, string>} ngeo-scaleselector-scales The available scales (key: scale, value: display text).
 * @htmlAttribute {ol.Map} ngeo-scaleselector-map The map.
 * @param {string|function(!angular.JQLite=, !angular.Attributes=)}
 *     ngeoScaleselectorTemplateUrl Template URL for the directive.
 * @return {angular.Directive} Directive Definition Object.
 * @ngInject
 * @ngdoc directive
 * @ngname ngeoScaleselector
 */
ngeo.scaleselectorDirective = function(ngeoScaleselectorTemplateUrl) {
  return {
    restrict: 'A',
    scope: true,
    controller: 'NgeoScaleselectorController',
    templateUrl: ngeoScaleselectorTemplateUrl
  };
};

ngeo.module.directive('ngeoScaleselector', ngeo.scaleselectorDirective);

/**
 * @constructor
 * @param {angular.Scope} $scope Directive scope.
 * @param {angular.JQLite} $element Element.
 * @param {angular.Attributes} $attrs Attributes.
 * @export
 * @ngInject
 * @ngdoc controller
 * @ngname NgeoScaleselectorController
 */
ngeo.ScaleselectorController = function($scope, $element, $attrs) {

  var scalesExpr = $attrs['ngeoScaleselector'];

  /**
   * The zoom level/scale map object.
   * @type {!Object.<string, string>}
   * @export
   */
  this.scales = /** @type {!Object.<string, string>} */
      ($scope.$eval(scalesExpr));
  goog.asserts.assert(this.scales !== undefined);

  /**
   * @type {Array.<number>}
   * @export
   */
  this.zoomLevels;

  $scope.$watchCollection(goog.bind(function() {
    return this.scales;
  }, this), goog.bind(function(newNames) {
    this.zoomLevels = Object.keys(this.scales).map(Number);
    this.zoomLevels.sort(ol.array.numberSafeCompareFunction);
  }, this));

  var mapExpr = $attrs['ngeoScaleselectorMap'];

  /**
   * @type {ol.Map}
   * @private
   */
  this.map_ = /** @type {ol.Map} */ ($scope.$eval(mapExpr));
  goog.asserts.assertInstanceof(this.map_, ol.Map);

  var optionsExpr = $attrs['ngeoScaleselectorOptions'];
  var options = $scope.$eval(optionsExpr);

  /**
   * @type {!ngeo.ScaleselectorOptions}
   * @export
   */
  this.options = ngeo.ScaleselectorController.getOptions_(options);

  /**
   * @type {angular.Scope}
   * @private
   */
  this.$scope_ = $scope;

  /**
   * @type {?ol.events.Key}
   * @private
   */
  this.resolutionChangeKey_ = null;

  /**
   * @type {string|undefined}
   * @export
   */
  this.currentScale = undefined;

  var view = this.map_.getView();
  if (view !== null) {
    var currentZoom = this.map_.getView().getZoom();
    if (currentZoom !== undefined) {
      this.currentScale = this.getScale(currentZoom);
    }
  }

  ol.events.listen(this.map_, ol.Object.getChangeEventType('view'),
      this.handleViewChange_, this);

  this.registerResolutionChangeListener_();

  $scope['scaleselectorCtrl'] = this;

};

/**
 * @param {?} options Options after expression evaluation.
 * @return {!ngeo.ScaleselectorOptions} Options object.
 * @private
 */
ngeo.ScaleselectorController.getOptions_ = function(options) {
  var ret;
  if (options === undefined) {
    ret = {'dropup': false};
  } else {
    if (options['dropup'] === undefined) {
      options['dropup'] = false;
    }
    ret = /** @type {ngeo.ScaleselectorOptions} */ (options);
  }
  return ret;
};

/**
 * @param {number} zoom Zoom level.
 * @return {string} Scale.
 * @export
 */
ngeo.ScaleselectorController.prototype.getScale = function(zoom) {
  return this.scales[zoom.toString()];
};

/**
 * @param {number} zoom Zoom level.
 * @export
 */
ngeo.ScaleselectorController.prototype.changeZoom = function(zoom) {
  this.map_.getView().setZoom(zoom);
};

/**
 * @param {ol.ObjectEvent} e OpenLayers ObjectEvent.
 * @private
 */
ngeo.ScaleselectorController.prototype.handleResolutionChange_ = function(e) {
  var view = this.map_.getView();
  var currentScale = this.scales[view.getZoom().toString()];

  // handleResolutionChange_ is a change:resolution listener. The listener
  // may be executed outside the Angular context, for example when the user
  // double-clicks to zoom on the map.
  //
  // But it may also be executed inside the Angular context, when a function
  // in Angular context calls setZoom or setResolution on the view, which
  // is for example what happens when this controller's changeZoom function
  // is called.
  //
  // For that reason we use $applyAsync instead of $apply here.

  this.$scope_.$applyAsync(function() {
    this.currentScale = currentScale;
  }.bind(this));
};

/**
 * @param {ol.ObjectEvent} e OpenLayers ObjectEvent.
 * @private
 */
ngeo.ScaleselectorController.prototype.handleViewChange_ = function(e) {
  this.registerResolutionChangeListener_();
  this.handleResolutionChange_(null);
};

/**
 * @private
 */
ngeo.ScaleselectorController.prototype.registerResolutionChangeListener_ = function() {
  if (this.resolutionChangeKey_ !== null) {
    ol.events.unlistenByKey(this.resolutionChangeKey_);
  }
  var view = this.map_.getView();
  this.resolutionChangeKey_ = ol.events.listen(view,
      ol.Object.getChangeEventType('resolution'), this.handleResolutionChange_,
      this);
};

ngeo.module.controller('NgeoScaleselectorController',
    ngeo.ScaleselectorController);
<commit_msg>Listen on a modification of the amount of keys instead of a modification of each property<commit_after>goog.provide('ngeo.ScaleselectorController');
goog.provide('ngeo.ScaleselectorOptions');
goog.provide('ngeo.scaleselectorDirective');

goog.require('ngeo');
goog.require('ol.array');
goog.require('ol.Map');
goog.require('ol.Object');
goog.require('ol.events');

ngeo.module.value('ngeoScaleselectorTemplateUrl',
    /**
     * @param {angular.JQLite} element Element.
     * @param {angular.Attributes} attrs Attributes.
     * @return {string} Template URL.
     */
    function(element, attrs) {
      var templateUrl = attrs['ngeoScaleselectorTemplateurl'];
      return templateUrl !== undefined ? templateUrl :
          ngeo.baseTemplateUrl + '/scaleselector.html';
    });

/**
 * @typedef {{dropup: (boolean|undefined)}}
 */
ngeo.ScaleselectorOptions;

/**
 * Provides the "ngeoScaleselector" directive, a widget for
 * selecting map scales.
 *
 * Example:
 *
 *

 *

 *
 * The expression passed to the ngeo-scaleselector attribute should return an
 * object of this form:
 *
 *     {
 *       '0': $sce.trustAsHtml('1 : 200\'000\'000'),
 *       '1': $sce.trustAsHtml('1 : 100\'000\'000'),
 *       '2': $sce.trustAsHtml('1 : 50\'000\'000'),
 *       '3': $sce.trustAsHtml('1 : 25\'000\'000'),
 *       '4': $sce.trustAsHtml('1 : 12\'000\'000')
 *     }
 *
 * This object's keys are strings representing zoom levels, the values are
 * strings representing scales. The directive's partial uses ng-bind-html so
 * the scale strings should be trusted.
 *
 * That directive's partial uses Bootstrap's `dropdown` and `dropdown-menu`
 * classes, and `data-toggle="dropdown"`, so it is meant to be used with
 * Bootstrap's "dropdown" jQuery plugin.
 *
 * By default the directive uses "scaleselector.html" as its templateUrl. This
 * an be changed by redefining the "ngeoScaleselectorTemplateUrl" value.
 *
 * The directive has its own scope, but it is not isolate scope. That scope
 * includes a reference to the directive's controller: the "scaleselectorCtrl"
 * scope property.
 *
 * The directive doesn't create any watcher. In particular the object including
 * the scales information is now watched.
 *
 * @htmlAttribute {Object.<string, string>} ngeo-scaleselector-scales The available scales (key: scale, value: display text).
 * @htmlAttribute {ol.Map} ngeo-scaleselector-map The map.
 * @param {string|function(!angular.JQLite=, !angular.Attributes=)}
 *     ngeoScaleselectorTemplateUrl Template URL for the directive.
 * @return {angular.Directive} Directive Definition Object.
 * @ngInject
 * @ngdoc directive
 * @ngname ngeoScaleselector
 */
ngeo.scaleselectorDirective = function(ngeoScaleselectorTemplateUrl) {
  return {
    restrict: 'A',
    scope: true,
    controller: 'NgeoScaleselectorController',
    templateUrl: ngeoScaleselectorTemplateUrl
  };
};

ngeo.module.directive('ngeoScaleselector', ngeo.scaleselectorDirective);

/**
 * @constructor
 * @param {angular.Scope} $scope Directive scope.
 * @param {angular.JQLite} $element Element.
 * @param {angular.Attributes} $attrs Attributes.
 * @export
 * @ngInject
 * @ngdoc controller
 * @ngname NgeoScaleselectorController
 */
ngeo.ScaleselectorController = function($scope, $element, $attrs) {

  var scalesExpr = $attrs['ngeoScaleselector'];

  /**
   * The zoom level/scale map object.
   * @type {!Object.<string, string>}
   * @export
   */
  this.scales = /** @type {!Object.<string, string>} */
      ($scope.$eval(scalesExpr));
  goog.asserts.assert(this.scales !== undefined);

  /**
   * @type {Array.<number>}
   * @export
   */
  this.zoomLevels;

  $scope.$watch(function() {
    return Object.keys(this.scales).length;
  }.bind(this), function(newLength) {
    this.zoomLevels = Object.keys(this.scales).map(Number);
    this.zoomLevels.sort(ol.array.numberSafeCompareFunction);
  }.bind(this));

  var mapExpr = $attrs['ngeoScaleselectorMap'];

  /**
   * @type {ol.Map}
   * @private
   */
  this.map_ = /** @type {ol.Map} */ ($scope.$eval(mapExpr));
  goog.asserts.assertInstanceof(this.map_, ol.Map);

  var optionsExpr = $attrs['ngeoScaleselectorOptions'];
  var options = $scope.$eval(optionsExpr);

  /**
   * @type {!ngeo.ScaleselectorOptions}
   * @export
   */
  this.options = ngeo.ScaleselectorController.getOptions_(options);

  /**
   * @type {angular.Scope}
   * @private
   */
  this.$scope_ = $scope;

  /**
   * @type {?ol.events.Key}
   * @private
   */
  this.resolutionChangeKey_ = null;

  /**
   * @type {string|undefined}
   * @export
   */
  this.currentScale = undefined;

  var view = this.map_.getView();
  if (view !== null) {
    var currentZoom = this.map_.getView().getZoom();
    if (currentZoom !== undefined) {
      this.currentScale = this.getScale(currentZoom);
    }
  }

  ol.events.listen(this.map_, ol.Object.getChangeEventType('view'),
      this.handleViewChange_, this);

  this.registerResolutionChangeListener_();

  $scope['scaleselectorCtrl'] = this;

};

/**
 * @param {?} options Options after expression evaluation.
 * @return {!ngeo.ScaleselectorOptions} Options object.
 * @private
 */
ngeo.ScaleselectorController.getOptions_ = function(options) {
  var ret;
  if (options === undefined) {
    ret = {'dropup': false};
  } else {
    if (options['dropup'] === undefined) {
      options['dropup'] = false;
    }
    ret = /** @type {ngeo.ScaleselectorOptions} */ (options);
  }
  return ret;
};

/**
 * @param {number} zoom Zoom level.
 * @return {string} Scale.
 * @export
 */
ngeo.ScaleselectorController.prototype.getScale = function(zoom) {
  return this.scales[zoom.toString()];
};

/**
 * @param {number} zoom Zoom level.
 * @export
 */
ngeo.ScaleselectorController.prototype.changeZoom = function(zoom) {
  this.map_.getView().setZoom(zoom);
};

/**
 * @param {ol.ObjectEvent} e OpenLayers ObjectEvent.
 * @private
 */
ngeo.ScaleselectorController.prototype.handleResolutionChange_ = function(e) {
  var view = this.map_.getView();
  var currentScale = this.scales[view.getZoom().toString()];

  // handleResolutionChange_ is a change:resolution listener. The listener
  // may be executed outside the Angular context, for example when the user
  // double-clicks to zoom on the map.
  //
  // But it may also be executed inside the Angular context, when a function
  // in Angular context calls setZoom or setResolution on the view, which
  // is for example what happens when this controller's changeZoom function
  // is called.
  //
  // For that reason we use $applyAsync instead of $apply here.

  this.$scope_.$applyAsync(function() {
    this.currentScale = currentScale;
  }.bind(this));
};

/**
 * @param {ol.ObjectEvent} e OpenLayers ObjectEvent.
 * @private
 */
ngeo.ScaleselectorController.prototype.handleViewChange_ = function(e) {
  this.registerResolutionChangeListener_();
  this.handleResolutionChange_(null);
};

/**
 * @private
 */
ngeo.ScaleselectorController.prototype.registerResolutionChangeListener_ = function() {
  if (this.resolutionChangeKey_ !== null) {
    ol.events.unlistenByKey(this.resolutionChangeKey_);
  }
  var view = this.map_.getView();
  this.resolutionChangeKey_ = ol.events.listen(view,
      ol.Object.getChangeEventType('resolution'), this.handleResolutionChange_,
      this);
};

ngeo.module.controller('NgeoScaleselectorController',
    ngeo.ScaleselectorController);
<|endoftext|>


<commit_before>////
//// Add extra data/links to searches dealing with single terms.
////

//
function MedialInit(){

    // Logger.
    var logger = new bbop.logger();
    logger.DEBUG = true;
    function ll(str){ logger.kvetch('M: ' + str); }

    ll('');
    ll('Medial.js');
    ll('MedialInit start...');

    // Only trigger when we've been passed the candidate.
    if( ! global_acc ){
	ll('No candidate--skipping');
    }else{

	// Ready the configuration that we'll use.
	var gconf = new bbop.golr.conf(amigo.data.golr);
	var sd = new amigo.data.server();
	var solr_server = sd.golr_base();
	var al = new amigo.linker();

	///
	/// Create a bookmark for searching annotations and
	/// bioentities with this term. Generate links and activate
	/// hidden stubs in the doc.
	///

	// Get bookmark for annotations.
	(function(){
	     var man = new bbop.golr.manager.jquery(solr_server, gconf);
	     man.set_personality('annotation');
	     man.add_query_filter('document_category', 'annotation', ['*']);
	     man.add_query_filter('regulates_closure', global_acc);
	     //ll('qurl: ' + man.get_query_url());
	     //var lstate = encodeURIComponent(man.get_state_url());
	     var lstate = man.get_filter_query_string();
	     var lurl = al.url(lstate, 'search', 'annotation');

	     // Add it to the DOM.
	     jQuery('#prob_ann_href').attr('href', lurl);
	     jQuery('#prob_ann').removeClass('hidden');
	 })();
    }

	// Get bookmark for annotations.
	(function(){
	     var man = new bbop.golr.manager.jquery(solr_server, gconf);
	     man.set_personality('annotation');
	     man.add_query_filter('document_category', 'annotation', ['*']);
	     man.add_query_filter('regulates_closure', global_acc);
	     //ll('qurl: ' + man.get_query_url());
	     //var lstate = encodeURIComponent(man.get_state_url());
	     var lstate = man.get_filter_query_string();
	     var lurl = al.url(lstate, 'search', 'annotation');

	     // Add it to the DOM.
	     jQuery('#prob_ann_href').attr('href', lurl);
	     jQuery('#prob_ann').removeClass('hidden');
	 })();

    // Get bookmark for annotations.
    (function(){
	 var man = new bbop.golr.manager.jquery(solr_server, gconf);
	 man.set_personality('annotation');
	 man.add_query_filter('document_category', 'bioentity', ['*']);
	 man.add_query_filter('regulates_closure', global_acc);
	 //ll('qurl: ' + man.get_query_url());
	 //var lstate = encodeURIComponent(man.get_state_url());
	 var lstate = man.get_filter_query_string();
	 var lurl = al.url(lstate, 'search', 'bioentity');

	 // Add it to the DOM.
	 jQuery('#prob_bio_href').attr('href', lurl);
	 jQuery('#prob_bio').removeClass('hidden');
     })();

    //
    ll('MedialInit done.');
}
<commit_msg>too much<commit_after>////
//// Add extra data/links to searches dealing with single terms.
////

//
function MedialInit(){

    // Logger.
    var logger = new bbop.logger();
    logger.DEBUG = true;
    function ll(str){ logger.kvetch('M: ' + str); }

    ll('');
    ll('Medial.js');
    ll('MedialInit start...');

    // Only trigger when we've been passed the candidate.
    if( ! global_acc ){
	ll('No candidate--skipping');
    }else{

	// Ready the configuration that we'll use.
	var gconf = new bbop.golr.conf(amigo.data.golr);
	var sd = new amigo.data.server();
	var solr_server = sd.golr_base();
	var al = new amigo.linker();

	///
	/// Create a bookmark for searching annotations and
	/// bioentities with this term. Generate links and activate
	/// hidden stubs in the doc.
	///

	// Get bookmark for annotations.
	(function(){
	     var man = new bbop.golr.manager.jquery(solr_server, gconf);
	     man.set_personality('annotation');
	     man.add_query_filter('document_category', 'annotation', ['*']);
	     man.add_query_filter('regulates_closure', global_acc);
	     //ll('qurl: ' + man.get_query_url());
	     //var lstate = encodeURIComponent(man.get_state_url());
	     var lstate = man.get_filter_query_string();
	     var lurl = al.url(lstate, 'search', 'annotation');

	     // Add it to the DOM.
	     jQuery('#prob_ann_href').attr('href', lurl);
	     jQuery('#prob_ann').removeClass('hidden');
	 })();
    }

    // Get bookmark for bioentities.
    (function(){
	 var man = new bbop.golr.manager.jquery(solr_server, gconf);
	 man.set_personality('annotation');
	 man.add_query_filter('document_category', 'bioentity', ['*']);
	 man.add_query_filter('regulates_closure', global_acc);
	 //ll('qurl: ' + man.get_query_url());
	 //var lstate = encodeURIComponent(man.get_state_url());
	 var lstate = man.get_filter_query_string();
	 var lurl = al.url(lstate, 'search', 'bioentity');

	 // Add it to the DOM.
	 jQuery('#prob_bio_href').attr('href', lurl);
	 jQuery('#prob_bio').removeClass('hidden');
     })();

    //
    ll('MedialInit done.');
}
<|endoftext|>


<commit_before>(function ($, window, document, undefined) {
  'use strict';

  // Accordion
  $('.accordion > dd').hide();
  $('.accordion > dt > span > a').click(function() {
    var definition = $(this).parent().parent().next();
    var display = definition.css("display");
    if (display == "none") {
      definition.show();
      $(this).text("[-]");
    } else {
      definition.hide();
      $(this).text("[+]");
    }

    return false;
  });

  // Banner image rotation

  /**
   * Returns a random integer between min and max
   * Using Math.round() will give you a non-uniform distribution!
   */
  function getRandomInt (min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  var bannerImages = [
    "baby_cacti.jpg",
    "bird_statue.jpg",
    "books.jpg",
    "cactus_closeup.jpg",
    "canoe_paddle.jpg",
    "cd07_blue.jpg",
    "closeup_grass.jpg",
    "duquesne_ghosthouse2.jpg",
    "duquesne_ghosthouse_wall.jpg",
    "duquesne_oldadobe.jpg",
    "fh_reflection.jpg",
    "flowerpot.jpg",
    "getting_ceiling.jpg",
    "harshaw_ghosthouse1.jpg",
    "harshaw_ghosthouse2.jpg",
    "harshaw_ghosthouse_wall.jpg",
    "hawk_takeoff.jpg",
    "icicles.jpg",
    "lochiel_slag2.jpg",
    "lochiel_slag.jpg",
    "lone_bird.jpg",
    "loon.jpg",
    "mtlemmon_ice.jpg",
    "mtnscows_srv.jpg",
    "newspaper.jpg",
    "pads.jpg",
    "patagonia_above.jpg",
    "pike_jump2.jpg",
    "pike_jump3.jpg",
    "pronghorns_srv.jpg",
    "rainwindow.jpg",
    "sanr_wind.jpg",
    "shoreline.jpg",
    "smokestack.jpg",
    "snake_path.jpg",
    "snow.jpg",
    "snowy_cactus.jpg",
    "sundial_slh.jpg",
    "tracks_srv.jpg",
    "treetops_tbc.jpg",
    "vantana_out4.jpg",
    "wake.jpg",
    "water_surface.jpg",
    "wheat2.jpg",
    "window_vc.jpg"
  ];

  var arrayIndex = getRandomInt(0, bannerImages.length - 1);
  var imagePath = "images/banner_340_280/" + bannerImages[arrayIndex];
  $('.banner-square').css("background-image", "url(" + imagePath + ")");

  var bannerAnchors = $('.banner-square-image-url');
  bannerAnchors.attr("href", imagePath);
}(jQuery, this, this.document));
<commit_msg>Update customize.js<commit_after>(function ($, window, document, undefined) {
  'use strict';

  // Accordion
  $('.accordion > dd').hide();
  $('.accordion > dt > span > a').click(function() {
    var definition = $(this).parent().parent().next();
    var display = definition.css("display");
    if (display == "none") {
      definition.show();
      $(this).text("[-]");
    } else {
      definition.hide();
      $(this).text("[+]");
    }

    return false;
  });

  // Banner image rotation

  /**
   * Returns a random integer between min and max
   * Using Math.round() will give you a non-uniform distribution!
   */
  function getRandomInt (min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  var bannerImages = [
    "baby_cacti.jpg",
    "bird_statue.jpg",
    "books.jpg",
    "cactus_closeup.jpg",
    "canoe_paddle.jpg",
    "cd07_blue.jpg",
    "closeup_grass.jpg",
    "duquesne_ghosthouse2.jpg",
    "duquesne_ghosthouse_wall.jpg",
    "duquesne_oldadobe.jpg",
    "fh_reflection.jpg",
    "flowerpot.jpg",
    "getting_ceiling.jpg",
    "harshaw_ghosthouse2.jpg",
    "hawk_takeoff.jpg",
    "icicles.jpg",
    "lochiel_slag2.jpg",
    "lochiel_slag.jpg",
    "lone_bird.jpg",
    "loon.jpg",
    "mtlemmon_ice.jpg",
    "mtnscows_srv.jpg",
    "newspaper.jpg",
    "pads.jpg",
    "patagonia_above.jpg",
    "pike_jump2.jpg",
    "pike_jump3.jpg",
    "pronghorns_srv.jpg",
    "rainwindow.jpg",
    "sanr_wind.jpg",
    "shoreline.jpg",
    "smokestack.jpg",
    "snake_path.jpg",
    "snow.jpg",
    "snowy_cactus.jpg",
    "sundial_slh.jpg",
    "tracks_srv.jpg",
    "treetops_tbc.jpg",
    "vantana_out4.jpg",
    "wake.jpg",
    "water_surface.jpg",
    "wheat2.jpg",
    "window_vc.jpg"
  ];

  var arrayIndex = getRandomInt(0, bannerImages.length - 1);
  var imagePath = "images/banner_340_280/" + bannerImages[arrayIndex];
  $('.banner-square').css("background-image", "url(" + imagePath + ")");

  var bannerAnchors = $('.banner-square-image-url');
  bannerAnchors.attr("href", imagePath);
}(jQuery, this, this.document));
<|endoftext|>


<commit_before>var CHEMICAL_ELEMENTS = {
  0: {'background-color': '#F1EEFA',
      'border-color': '#AAA',
      'color': '#F1EEFA',
      'name': 'n/a',
      'symbol': ''},

  1: {'background-color': '#dde',
      'border-color': '#888',
      'color': 'black',
      'name': 'hydrogen',
      'symbol': 'H'},

  2: {'background-color': '#edd',
      'border-color': '#888',
      'color': 'black',
      'name': 'helium',
      'symbol': 'He'},
};

var BLOCK_FONT = "12px Verdana";
var DROP_DELAY = 300;

var GRID_HEIGHT = 20;
var GRID_WIDTH = 10;

var BLOCK_WIDTH, BLOCK_HEIGHT;
var BLOCK_SPACING_WIDTH, BLOCK_SPACING_HEIGHT;

var TETRINIMO_TEMPLATES = {
  jBlock: ['xx',
           'x ',
           'x '],
  lBlock: ['xx',
           ' x',
           ' x'],
  square: ['xx',
           'xx'],
  sBlock: ['x ',
           'xx',
           ' x'],
  zBlock: [' x',
           'xx',
           'x '],
  line:   ['x',
           'x',
           'x',
           'x'],
  tBlock: ['xxx',
           ' x ']
};
var processTetrinimos = function() {
  var tetraShape = new Object;
  for(var shape in TETRINIMO_TEMPLATES) {
    if( TETRINIMO_TEMPLATES.hasOwnProperty(shape)) {
      tetraShape[shape] = new Array;
      var currentShape = TETRINIMO_TEMPLATES[shape];
      for(var row in currentShape) {
        for(var col in currentShape[row]) {
          if(currentShape[row][col] == 'x') {
            tetraShape[shape].push({x: parseInt(col, 10),
                                    y: parseInt(row, 10)});
          }
        }
      }
    }
  }
  return tetraShape
}
var tetrinimoShapes = processTetrinimos();

var TetrisBoard = function() {
  this.board = new Array;

  for(var row = 0; row < 20; row++) {
    this.board[row] = new Array;
    for(var col = 0; col < 10; col++) {
      this.board[row][col] = 0;
    }
  };
}
TetrisBoard.prototype.blit = function(args) {
  var tetrinimo = args.tetrinimo;
  var element = tetrinimo.element;

  if(args.clear) {
    element = 0;
  }

  for(var block in tetrinimo.blocks) {
    var currentBlock = tetrinimo.blocks[block];
    this.board[currentBlock.y][currentBlock.x] = element;
  }
};
TetrisBoard.prototype.detectCollision = function(tetrinimo) {
  for(var block in tetrinimo.blocks) {
    currentBlock = tetrinimo.blocks[block];
    if(currentBlock.y >= GRID_HEIGHT) {
      return 'floor';
    }
    else if(currentBlock.x < 0 || currentBlock.x >= GRID_WIDTH) {
      return 'wall';
    }
    else if(this.board[currentBlock.y][currentBlock.x] !== 0) {
      return 'block';
    }
  }
  return 'clear';
};
TetrisBoard.prototype.dropBlock = function(tetrinimo) {
  this.blit({tetrinimo: tetrinimo, clear: true});
  tetrinimo.drop();
  var collision = this.detectCollision(tetrinimo);
  if(collision == 'floor' || collision == 'block') {
    tetrinimo.raise();
    clearInterval(this.intervalID);
  }
  this.blit({tetrinimo: tetrinimo});
};

var Tetrinimo = function(args) {
  this.element = args.element;
  this.blocks = args.blocks;
  this.row = 0;
  this.col = 5;

  for(var block in this.blocks) {
    this.blocks[block].y += this.row;
    this.blocks[block].x += this.col;
  }
}
Tetrinimo.prototype.raise = function() {
  this.row--;
  for(var block in this.blocks) {
    this.blocks[block].y--;
  }
};
Tetrinimo.prototype.drop = function() {
  this.row++;
  for(var block in this.blocks) {
    this.blocks[block].y++;
  }
};
var directToInt = {
  'left': -1,
  'right': 1
};
Tetrinimo.prototype.slide = function(direction) {
  this.blocks.forEach(function(block) {
    block.x += directToInt[direction];
  });
};

var charCodes = {
  'left': 37,
  'right': 38,
  'up': 39,
  'down': 40,
  'backspace': 8
}

var View = function(args) {
  this.context = document.querySelector('canvas').getContext('2d');
  this.debug = "debug string";

  addEventListener('keydown', function(event) {
    event.preventDefault();
    console.log("event happened!", event);
  });
}
View.prototype.drawBoard = function(board) {
  var context = this.context
  context.lineWidth = 4;
  context.font = BLOCK_FONT;

  board.forEach(function(row, rIndex) {
    row.forEach(function(col, cIndex) {
      context.fillStyle = CHEMICAL_ELEMENTS[col]['background-color'];
      context.strokeStyle = CHEMICAL_ELEMENTS[col]['border-color'];

      context.fillRect((cIndex * BLOCK_SPACING_WIDTH) + 5, (rIndex * BLOCK_SPACING_HEIGHT) + 5, BLOCK_WIDTH, BLOCK_HEIGHT);
      context.strokeRect((cIndex * BLOCK_SPACING_WIDTH) + 5, (rIndex * BLOCK_SPACING_HEIGHT) + 5, BLOCK_WIDTH, BLOCK_HEIGHT);
      context.fillStyle = CHEMICAL_ELEMENTS[col]['color'];
      context.fillText(CHEMICAL_ELEMENTS[col].symbol, (cIndex * BLOCK_SPACING_WIDTH) + (BLOCK_SPACING_WIDTH / 2) - 4, (rIndex * BLOCK_SPACING_HEIGHT) + (BLOCK_SPACING_HEIGHT / 2) + 4);
    });
  });
};
View.prototype.animate = function(board) {
  var lastTime = null;
  var progress = true;
  var self = this;

  var animate = function(time) {
    if(lastTime) {
      var timeStep = Math.min(time - lastTime, 100) / 1000;
      progress = timeStep < 2000;
    }
    lastTime = time;
    self.drawBoard(board);
    if(progress) {
      requestAnimationFrame(animate);
    }
  }
  requestAnimationFrame(animate);
};

var ready = function(fn) {
  if(document.readyState != 'loading') {
    fn();
  }
  else {
    document.addEventListener('DOMContentLoaded', fn);
  }
}
ready(function() {
  var canvas = document.querySelector('canvas');
  BLOCK_SPACING_HEIGHT = canvas.getAttribute('height') / 20;
  BLOCK_SPACING_WIDTH = canvas.getAttribute('width') / 10;
  BLOCK_HEIGHT = BLOCK_SPACING_HEIGHT - 10;
  BLOCK_WIDTH = BLOCK_SPACING_WIDTH - 10;

  window.gameView = new View();
  window.gameBoard = new TetrisBoard();
  window.lineBlock = new Tetrinimo({element: 1, blocks: tetrinimoShapes.line});

  gameBoard.blit({tetrinimo: lineBlock});
  gameView.animate(gameBoard.board);

  gameBoard.intervalID = setInterval(function() {
    gameBoard.dropBlock(lineBlock);
  }, DROP_DELAY);
});
<commit_msg>Swap props and values in charCodes to facilitate conversion<commit_after>var CHEMICAL_ELEMENTS = {
  0: {'background-color': '#F1EEFA',
      'border-color': '#AAA',
      'color': '#F1EEFA',
      'name': 'n/a',
      'symbol': ''},

  1: {'background-color': '#dde',
      'border-color': '#888',
      'color': 'black',
      'name': 'hydrogen',
      'symbol': 'H'},

  2: {'background-color': '#edd',
      'border-color': '#888',
      'color': 'black',
      'name': 'helium',
      'symbol': 'He'},
};

var BLOCK_FONT = "12px Verdana";
var DROP_DELAY = 300;

var GRID_HEIGHT = 20;
var GRID_WIDTH = 10;

var BLOCK_WIDTH, BLOCK_HEIGHT;
var BLOCK_SPACING_WIDTH, BLOCK_SPACING_HEIGHT;

var TETRINIMO_TEMPLATES = {
  jBlock: ['xx',
           'x ',
           'x '],
  lBlock: ['xx',
           ' x',
           ' x'],
  square: ['xx',
           'xx'],
  sBlock: ['x ',
           'xx',
           ' x'],
  zBlock: [' x',
           'xx',
           'x '],
  line:   ['x',
           'x',
           'x',
           'x'],
  tBlock: ['xxx',
           ' x ']
};
var processTetrinimos = function() {
  var tetraShape = new Object;
  for(var shape in TETRINIMO_TEMPLATES) {
    if( TETRINIMO_TEMPLATES.hasOwnProperty(shape)) {
      tetraShape[shape] = new Array;
      var currentShape = TETRINIMO_TEMPLATES[shape];
      for(var row in currentShape) {
        for(var col in currentShape[row]) {
          if(currentShape[row][col] == 'x') {
            tetraShape[shape].push({x: parseInt(col, 10),
                                    y: parseInt(row, 10)});
          }
        }
      }
    }
  }
  return tetraShape
}
var tetrinimoShapes = processTetrinimos();

var TetrisBoard = function() {
  this.board = new Array;

  for(var row = 0; row < 20; row++) {
    this.board[row] = new Array;
    for(var col = 0; col < 10; col++) {
      this.board[row][col] = 0;
    }
  };
}
TetrisBoard.prototype.blit = function(args) {
  var tetrinimo = args.tetrinimo;
  var element = tetrinimo.element;

  if(args.clear) {
    element = 0;
  }

  for(var block in tetrinimo.blocks) {
    var currentBlock = tetrinimo.blocks[block];
    this.board[currentBlock.y][currentBlock.x] = element;
  }
};
TetrisBoard.prototype.detectCollision = function(tetrinimo) {
  for(var block in tetrinimo.blocks) {
    currentBlock = tetrinimo.blocks[block];
    if(currentBlock.y >= GRID_HEIGHT) {
      return 'floor';
    }
    else if(currentBlock.x < 0 || currentBlock.x >= GRID_WIDTH) {
      return 'wall';
    }
    else if(this.board[currentBlock.y][currentBlock.x] !== 0) {
      return 'block';
    }
  }
  return 'clear';
};
TetrisBoard.prototype.dropBlock = function(tetrinimo) {
  this.blit({tetrinimo: tetrinimo, clear: true});
  tetrinimo.drop();
  var collision = this.detectCollision(tetrinimo);
  if(collision == 'floor' || collision == 'block') {
    tetrinimo.raise();
    clearInterval(this.intervalID);
  }
  this.blit({tetrinimo: tetrinimo});
};

var Tetrinimo = function(args) {
  this.element = args.element;
  this.blocks = args.blocks;
  this.row = 0;
  this.col = 5;

  for(var block in this.blocks) {
    this.blocks[block].y += this.row;
    this.blocks[block].x += this.col;
  }
}
Tetrinimo.prototype.raise = function() {
  this.row--;
  for(var block in this.blocks) {
    this.blocks[block].y--;
  }
};
Tetrinimo.prototype.drop = function() {
  this.row++;
  for(var block in this.blocks) {
    this.blocks[block].y++;
  }
};
var directToInt = {
  'left': -1,
  'right': 1
};
Tetrinimo.prototype.slide = function(direction) {
  this.blocks.forEach(function(block) {
    block.x += directToInt[direction];
  });
};

var charCodes = {
  37: 'left',
  38: 'right',
  39: 'up',
  40: 'down',
  8: 'backspace'
}

var View = function(args) {
  this.context = document.querySelector('canvas').getContext('2d');
  this.debug = "debug string";

  addEventListener('keydown', function(event) {
    event.preventDefault();
    console.log("event happened!", event);
  });
}
View.prototype.drawBoard = function(board) {
  var context = this.context
  context.lineWidth = 4;
  context.font = BLOCK_FONT;

  board.forEach(function(row, rIndex) {
    row.forEach(function(col, cIndex) {
      context.fillStyle = CHEMICAL_ELEMENTS[col]['background-color'];
      context.strokeStyle = CHEMICAL_ELEMENTS[col]['border-color'];

      context.fillRect((cIndex * BLOCK_SPACING_WIDTH) + 5, (rIndex * BLOCK_SPACING_HEIGHT) + 5, BLOCK_WIDTH, BLOCK_HEIGHT);
      context.strokeRect((cIndex * BLOCK_SPACING_WIDTH) + 5, (rIndex * BLOCK_SPACING_HEIGHT) + 5, BLOCK_WIDTH, BLOCK_HEIGHT);
      context.fillStyle = CHEMICAL_ELEMENTS[col]['color'];
      context.fillText(CHEMICAL_ELEMENTS[col].symbol, (cIndex * BLOCK_SPACING_WIDTH) + (BLOCK_SPACING_WIDTH / 2) - 4, (rIndex * BLOCK_SPACING_HEIGHT) + (BLOCK_SPACING_HEIGHT / 2) + 4);
    });
  });
};
View.prototype.animate = function(board) {
  var lastTime = null;
  var progress = true;
  var self = this;

  var animate = function(time) {
    if(lastTime) {
      var timeStep = Math.min(time - lastTime, 100) / 1000;
      progress = timeStep < 2000;
    }
    lastTime = time;
    self.drawBoard(board);
    if(progress) {
      requestAnimationFrame(animate);
    }
  }
  requestAnimationFrame(animate);
};

var ready = function(fn) {
  if(document.readyState != 'loading') {
    fn();
  }
  else {
    document.addEventListener('DOMContentLoaded', fn);
  }
}
ready(function() {
  var canvas = document.querySelector('canvas');
  BLOCK_SPACING_HEIGHT = canvas.getAttribute('height') / 20;
  BLOCK_SPACING_WIDTH = canvas.getAttribute('width') / 10;
  BLOCK_HEIGHT = BLOCK_SPACING_HEIGHT - 10;
  BLOCK_WIDTH = BLOCK_SPACING_WIDTH - 10;

  window.gameView = new View();
  window.gameBoard = new TetrisBoard();
  window.lineBlock = new Tetrinimo({element: 1, blocks: tetrinimoShapes.line});

  gameBoard.blit({tetrinimo: lineBlock});
  gameView.animate(gameBoard.board);

  gameBoard.intervalID = setInterval(function() {
    gameBoard.dropBlock(lineBlock);
  }, DROP_DELAY);
});
<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc directive
 * @name ngPluralize
 * @restrict EA
 *
 * @description
 * `ngPluralize` is a directive that displays messages according to en-US localization rules.
 * These rules are bundled with angular.js, but can be overridden
 * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive
 * by specifying the mappings between
 * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
 * and the strings to be displayed.
 *
 * # Plural categories and explicit number rules
 * There are two
 * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
 * in Angular's default en-US locale: "one" and "other".
 *
 * While a plural category may match many numbers (for example, in en-US locale, "other" can match
 * any number that is not 1), an explicit number rule can only match one number. For example, the
 * explicit number rule for "3" matches the number 3. There are examples of plural categories
 * and explicit number rules throughout the rest of this documentation.
 *
 * # Configuring ngPluralize
 * You configure ngPluralize by providing 2 attributes: `count` and `when`.
 * You can also provide an optional attribute, `offset`.
 *
 * The value of the `count` attribute can be either a string or an {@link guide/expression
 * Angular expression}; these are evaluated on the current scope for its bound value.
 *
 * The `when` attribute specifies the mappings between plural categories and the actual
 * string to be displayed. The value of the attribute should be a JSON object.
 *
 * The following example shows how to configure ngPluralize:
 *
 * ```html
 * <ng-pluralize count="personCount"
                 when="{'0': 'Nobody is viewing.',
 *                      'one': '1 person is viewing.',
 *                      'other': '{} people are viewing.'}">
 * </ng-pluralize>
 *```
 *
 * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not
 * specify this rule, 0 would be matched to the "other" category and "0 people are viewing"
 * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for
 * other numbers, for example 12, so that instead of showing "12 people are viewing", you can
 * show "a dozen people are viewing".
 *
 * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted
 * into pluralized strings. In the previous example, Angular will replace `{}` with
 * `{{personCount}}`. The closed braces `{}` is a placeholder
 * for {{numberExpression}}.
 *
 * # Configuring ngPluralize with offset
 * The `offset` attribute allows further customization of pluralized text, which can result in
 * a better user experience. For example, instead of the message "4 people are viewing this document",
 * you might display "John, Kate and 2 others are viewing this document".
 * The offset attribute allows you to offset a number by any desired value.
 * Let's take a look at an example:
 *
 * ```html
 * <ng-pluralize count="personCount" offset=2
 *               when="{'0': 'Nobody is viewing.',
 *                      '1': '{{person1}} is viewing.',
 *                      '2': '{{person1}} and {{person2}} are viewing.',
 *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',
 *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
 * </ng-pluralize>
 * ```
 *
 * Notice that we are still using two plural categories(one, other), but we added
 * three explicit number rules 0, 1 and 2.
 * When one person, perhaps John, views the document, "John is viewing" will be shown.
 * When three people view the document, no explicit number rule is found, so
 * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
 * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
 * is shown.
 *
 * Note that when you specify offsets, you must provide explicit number rules for
 * numbers from 0 up to and including the offset. If you use an offset of 3, for example,
 * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for
 * plural categories "one" and "other".
 *
 * @param {string|expression} count The variable to be bound to.
 * @param {string} when The mapping between plural category to its corresponding strings.
 * @param {number=} offset Offset to deduct from the total number.
 *
 * @example
    <example>
      <file name="index.html">

          Person 1:<input type="text" ng-model="person1" value="Igor" />

          Person 2:<input type="text" ng-model="person2" value="Misko" />

          Number of People:<input type="text" ng-model="personCount" value="1" />

          Without Offset:
          <ng-pluralize count="personCount"
                        when="{'0': 'Nobody is viewing.',
                               'one': '1 person is viewing.',
                               'other': '{} people are viewing.'}">
          </ng-pluralize>

          With Offset(2):
          <ng-pluralize count="personCount" offset=2
                        when="{'0': 'Nobody is viewing.',
                               '1': '{{person1}} is viewing.',
                               '2': '{{person1}} and {{person2}} are viewing.',
                               'one': '{{person1}}, {{person2}} and one other person are viewing.',
                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
          </ng-pluralize>

      </file>
      <file name="protractor.js" type="protractor">
        it('should show correct pluralized string', function() {
          var withoutOffset = element.all(by.css('ng-pluralize')).get(0);
          var withOffset = element.all(by.css('ng-pluralize')).get(1);
          var countInput = element(by.model('personCount'));

          expect(withoutOffset.getText()).toEqual('1 person is viewing.');
          expect(withOffset.getText()).toEqual('Igor is viewing.');

          countInput.clear();
          countInput.sendKeys('0');

          expect(withoutOffset.getText()).toEqual('Nobody is viewing.');
          expect(withOffset.getText()).toEqual('Nobody is viewing.');

          countInput.clear();
          countInput.sendKeys('2');

          expect(withoutOffset.getText()).toEqual('2 people are viewing.');
          expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');

          countInput.clear();
          countInput.sendKeys('3');

          expect(withoutOffset.getText()).toEqual('3 people are viewing.');
          expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');

          countInput.clear();
          countInput.sendKeys('4');

          expect(withoutOffset.getText()).toEqual('4 people are viewing.');
          expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');
        });
        it('should show data-bound names', function() {
          var withOffset = element.all(by.css('ng-pluralize')).get(1);
          var personCount = element(by.model('personCount'));
          var person1 = element(by.model('person1'));
          var person2 = element(by.model('person2'));
          personCount.clear();
          personCount.sendKeys('4');
          person1.clear();
          person1.sendKeys('Di');
          person2.clear();
          person2.sendKeys('Vojta');
          expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');
        });
      </file>
    </example>
 */
var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {
  var BRACE = /{}/g;
  return {
    restrict: 'EA',
    link: function(scope, element, attr) {
      var numberExp = attr.count,
          whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
          offset = attr.offset || 0,
          whens = scope.$eval(whenExp) || {},
          whensExpFns = {},
          startSymbol = $interpolate.startSymbol(),
          endSymbol = $interpolate.endSymbol(),
          isWhen = /^when(Minus)?(.+)$/;

      forEach(attr, function(expression, attributeName) {
        if (isWhen.test(attributeName)) {
          whens[lowercase(attributeName.replace('when', '').replace('Minus', '-'))] =
            element.attr(attr.$attr[attributeName]);
        }
      });
      forEach(whens, function(expression, key) {
        whensExpFns[key] =
          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +
            offset + endSymbol));
      });

      scope.$watch(function ngPluralizeWatch() {
        var value = parseFloat(scope.$eval(numberExp));

        if (!isNaN(value)) {
          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
          //check it against pluralization rules in $locale service
          if (!(value in whens)) value = $locale.pluralCat(value - offset);
           return whensExpFns[value](scope, element, true);
        } else {
          return '';
        }
      }, function ngPluralizeWatchAction(newVal) {
        element.text(newVal);
      });
    }
  };
}];
<commit_msg>docs(ngPluralize): update example to use a module<commit_after>'use strict';

/**
 * @ngdoc directive
 * @name ngPluralize
 * @restrict EA
 *
 * @description
 * `ngPluralize` is a directive that displays messages according to en-US localization rules.
 * These rules are bundled with angular.js, but can be overridden
 * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive
 * by specifying the mappings between
 * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
 * and the strings to be displayed.
 *
 * # Plural categories and explicit number rules
 * There are two
 * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
 * in Angular's default en-US locale: "one" and "other".
 *
 * While a plural category may match many numbers (for example, in en-US locale, "other" can match
 * any number that is not 1), an explicit number rule can only match one number. For example, the
 * explicit number rule for "3" matches the number 3. There are examples of plural categories
 * and explicit number rules throughout the rest of this documentation.
 *
 * # Configuring ngPluralize
 * You configure ngPluralize by providing 2 attributes: `count` and `when`.
 * You can also provide an optional attribute, `offset`.
 *
 * The value of the `count` attribute can be either a string or an {@link guide/expression
 * Angular expression}; these are evaluated on the current scope for its bound value.
 *
 * The `when` attribute specifies the mappings between plural categories and the actual
 * string to be displayed. The value of the attribute should be a JSON object.
 *
 * The following example shows how to configure ngPluralize:
 *
 * ```html
 * <ng-pluralize count="personCount"
                 when="{'0': 'Nobody is viewing.',
 *                      'one': '1 person is viewing.',
 *                      'other': '{} people are viewing.'}">
 * </ng-pluralize>
 *```
 *
 * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not
 * specify this rule, 0 would be matched to the "other" category and "0 people are viewing"
 * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for
 * other numbers, for example 12, so that instead of showing "12 people are viewing", you can
 * show "a dozen people are viewing".
 *
 * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted
 * into pluralized strings. In the previous example, Angular will replace `{}` with
 * `{{personCount}}`. The closed braces `{}` is a placeholder
 * for {{numberExpression}}.
 *
 * # Configuring ngPluralize with offset
 * The `offset` attribute allows further customization of pluralized text, which can result in
 * a better user experience. For example, instead of the message "4 people are viewing this document",
 * you might display "John, Kate and 2 others are viewing this document".
 * The offset attribute allows you to offset a number by any desired value.
 * Let's take a look at an example:
 *
 * ```html
 * <ng-pluralize count="personCount" offset=2
 *               when="{'0': 'Nobody is viewing.',
 *                      '1': '{{person1}} is viewing.',
 *                      '2': '{{person1}} and {{person2}} are viewing.',
 *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',
 *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
 * </ng-pluralize>
 * ```
 *
 * Notice that we are still using two plural categories(one, other), but we added
 * three explicit number rules 0, 1 and 2.
 * When one person, perhaps John, views the document, "John is viewing" will be shown.
 * When three people view the document, no explicit number rule is found, so
 * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
 * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
 * is shown.
 *
 * Note that when you specify offsets, you must provide explicit number rules for
 * numbers from 0 up to and including the offset. If you use an offset of 3, for example,
 * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for
 * plural categories "one" and "other".
 *
 * @param {string|expression} count The variable to be bound to.
 * @param {string} when The mapping between plural category to its corresponding strings.
 * @param {number=} offset Offset to deduct from the total number.
 *
 * @example
    <example module="pluralizeExample">
      <file name="index.html">

          Person 1:<input type="text" ng-model="person1" value="Igor" />

          Person 2:<input type="text" ng-model="person2" value="Misko" />

          Number of People:<input type="text" ng-model="personCount" value="1" />

          Without Offset:
          <ng-pluralize count="personCount"
                        when="{'0': 'Nobody is viewing.',
                               'one': '1 person is viewing.',
                               'other': '{} people are viewing.'}">
          </ng-pluralize>

          With Offset(2):
          <ng-pluralize count="personCount" offset=2
                        when="{'0': 'Nobody is viewing.',
                               '1': '{{person1}} is viewing.',
                               '2': '{{person1}} and {{person2}} are viewing.',
                               'one': '{{person1}}, {{person2}} and one other person are viewing.',
                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
          </ng-pluralize>

      </file>
      <file name="protractor.js" type="protractor">
        it('should show correct pluralized string', function() {
          var withoutOffset = element.all(by.css('ng-pluralize')).get(0);
          var withOffset = element.all(by.css('ng-pluralize')).get(1);
          var countInput = element(by.model('personCount'));

          expect(withoutOffset.getText()).toEqual('1 person is viewing.');
          expect(withOffset.getText()).toEqual('Igor is viewing.');

          countInput.clear();
          countInput.sendKeys('0');

          expect(withoutOffset.getText()).toEqual('Nobody is viewing.');
          expect(withOffset.getText()).toEqual('Nobody is viewing.');

          countInput.clear();
          countInput.sendKeys('2');

          expect(withoutOffset.getText()).toEqual('2 people are viewing.');
          expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');

          countInput.clear();
          countInput.sendKeys('3');

          expect(withoutOffset.getText()).toEqual('3 people are viewing.');
          expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');

          countInput.clear();
          countInput.sendKeys('4');

          expect(withoutOffset.getText()).toEqual('4 people are viewing.');
          expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');
        });
        it('should show data-bound names', function() {
          var withOffset = element.all(by.css('ng-pluralize')).get(1);
          var personCount = element(by.model('personCount'));
          var person1 = element(by.model('person1'));
          var person2 = element(by.model('person2'));
          personCount.clear();
          personCount.sendKeys('4');
          person1.clear();
          person1.sendKeys('Di');
          person2.clear();
          person2.sendKeys('Vojta');
          expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');
        });
      </file>
    </example>
 */
var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {
  var BRACE = /{}/g;
  return {
    restrict: 'EA',
    link: function(scope, element, attr) {
      var numberExp = attr.count,
          whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
          offset = attr.offset || 0,
          whens = scope.$eval(whenExp) || {},
          whensExpFns = {},
          startSymbol = $interpolate.startSymbol(),
          endSymbol = $interpolate.endSymbol(),
          isWhen = /^when(Minus)?(.+)$/;

      forEach(attr, function(expression, attributeName) {
        if (isWhen.test(attributeName)) {
          whens[lowercase(attributeName.replace('when', '').replace('Minus', '-'))] =
            element.attr(attr.$attr[attributeName]);
        }
      });
      forEach(whens, function(expression, key) {
        whensExpFns[key] =
          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +
            offset + endSymbol));
      });

      scope.$watch(function ngPluralizeWatch() {
        var value = parseFloat(scope.$eval(numberExp));

        if (!isNaN(value)) {
          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
          //check it against pluralization rules in $locale service
          if (!(value in whens)) value = $locale.pluralCat(value - offset);
           return whensExpFns[value](scope, element, true);
        } else {
          return '';
        }
      }, function ngPluralizeWatchAction(newVal) {
        element.text(newVal);
      });
    }
  };
}];
<|endoftext|>