<commit_before>/**
 * React application controller.
 *
 * 2013 (c) Andrey Popp <8mayday@gmail.com>
 */
"use strict";

var qs                    = require('querystring');
var React                 = require('react-tools/build/modules/React');
var createRouter          = require('./router');

function Controller(routes, opts) {
  opts = opts || {};
  routes = routes || {};

  this.routes = routes;
  this.opts = opts;
  this.router = createRouter(routes);
  this.activeRequest = null;
  this.activeComponent = null;

  this.renderComponent = opts.renderComponent ||
    renderComponent;

  this.renderComponentToString = opts.renderComponentToString ||
    renderComponentToString;

  this.onPopState = skipFirst(this.onPopState.bind(this));
}

Controller.prototype = {
  /**
   * Start controller
   *
   * @param {Object} data Bootstrap data which will be passed to the first
   *                      matched component
   * @param {Callback} cb
   */
  start: function(data, cb) {
    window.addEventListener('popstate', this.onpopstate);
    this.process(null, cb);
  },

  /**
   * Stop controller
   */
  stop: function() {
    window.removeEventListener('popstate', this.onPopState);
    React.unmountAndReleaseReactRootNode
  },

  /**
   * Navigate to a new URL
   *
   * @param {String|Request} URL
   * @param {Callback} cb
   */
  navigate: function(request, cb) {
    if (isString(request))
      request = createRequestFromURL(request);
    var url = createURL(request);
    window.history.pushState(null, '', url);
    this.process(request, cb);
  },

  /**
   * Navigate to a new URL by updating querystring
   *
   * @param {Object} query Values for querystring
   * @param {Callback} cb
   */
  navigateQuery: function(query, cb) {
    var k, newQuery = {}
    for (k in this.activeRequest.query)
      newQuery[k] = this.activeRequest.query[k];
    for (k in query)
      newQuery[k] = query[k];
    var request = {path: this.activeRequest.path, query: newQuery};
    this.navigate(request);
  },

  /**
   * Generate markup for a component for a specified request.
   *
   * This method doesn't touch the DOM and could be used on server to
   * pre-generate markup for a specified request.
   *
   * @param {String|Request} request
   * @param {Callback} cb
   */
  generateMarkup: function(request, cb) {
    if (isString(request))
      request = createRequestFromURL(request);
    var component = this.createComponent(request);
    if (!component)
      return cb(new NotFoundError(request.path));
    this.renderComponentToString(component, cb);
  },

  /**
   * Process request
   *
   * @private
   */
  process: function(request, cb) {
    request = request || createRequestFromLocation(window.location);
    cb = cb || function(err) { throwAsync(err); };

    var component = this.createComponent(request);
    if (!component)
      return cb(new NotFoundError(request.path));

    var mountPoint = this.opts.mountPoint || document.body;

    this.renderComponent(component, mountPoint, function(err, component) {
      if (err)
        return cb(err);

      this.activeRequest = request;
      this.activeComponent = component;

      cb(null, this);
    }.bind(this));
  },

  /**
   * Create component for request
   *
   * @private
   */
  createComponent: function(request) {
    var match = this.router.match(request.path);

    if (!match)
      return null;

    return match.handler({
      controller: this,
      request: {
        path: request.path,
        query: request.query || {},
        params: match.params || {}
      },
      data: request.data,
      options: this.opts.options
    });
  },

  /**
   * Handle 'popstate' event
   *
   * @private
   */
  onPopState: function(e) {
    e.preventDefault();
    this.process(null);
  }
};

/**
 * If object is a string
 *
 * @param {Object} obj
 */
function isString(obj) {
  return Object.prototype.toString.call(obj) === '[object String]';
}

/**
 * Skip first invokation for a specified func
 *
 * @param {Function} func
 */
function skipFirst(func) {
  var n = 0;
  return function() {
    if (n > 0) return func.apply(this, arguments);
    n = n + 1;
  }
}

/**
 * Throw exception in an async way.
 */
function throwAsync(err) {
  setTimeout(function() { throw err; }, 0);
}

function renderComponentAsync(component, element, cb) {
  try {
    component = React.renderComponent(component, element);
  } catch (err) {
    return cb(err);
  }
  cb(null, component);
}

function renderComponent(component, element, cb) {
  var doc = element.ownerDocument;

  if (doc.readyState === 'interactive' || doc.readyState === 'complete') {
    renderComponentAsync(component, element, cb);
  } else {
    window.addEventListener('DOMContentLoaded', function() {
      renderComponentAsync(component, element, cb);
    });
  }
}

function renderComponentToString(component, cb) {
  React.renderComponentToString(component, cb.bind(null, null));
}

/**
 * Error which will be thrown in case of no match found for a processed request.
 *
 * @param {String} url
 */
function NotFoundError(url) {
  Error.call(this, 'not found: ' + url);
  this.name = 'NotFoundError';
  this.url = url;
  this.isNotFound = true;
}
NotFoundError.prototype = new Error();

function createURL(request) {
  var url = request.path;
  if (request.query)
    url = url + '?' + qs.stringify(request.query);
  return url;
}

/**
 * Create request from URL
 *
 * @param {String} url
 * @param {Object} data
 */
function createRequestFromURL(url, data) {
  if (url.indexOf('?') > -1) {
    var parts = url.split('?');
    return {
      path: parts[0],
      query: qs.parse(parts[1]),
      data: data
    };
  } else {
    return {
      path: url,
      query: undefined,
      data: data
    };
  }
}

/**
 * Create request from location (such as window.location)
 *
 * @param {Location} loc
 * @param {Object} data
 */
function createRequestFromLocation(loc, data) {
  return {
    path: loc.pathname,
    query: loc.search ? qs.parse(loc.search.slice(1)) : null,
    data: data
  };
}

/**
 * Create controller
 *
 * @param {Object} routes Mapping from URL patterns to React components
 */
function createController(routes, opts) {
  return new Controller(routes, opts);
}

module.exports = createController;
module.exports.createController = createController;
module.exports.createRequestFromURL = createRequestFromURL;
module.exports.createRequestFromLocation = createRequestFromLocation;
module.exports.createRouter = createRouter;
module.exports.createURL = createURL;
module.exports.renderComponent = renderComponent;
module.exports.renderComponentToString = renderComponentToString;
module.exports.NotFoundError = NotFoundError;
<commit_msg>Few fixes from battlefield<commit_after>/**
 * React application controller.
 *
 * 2013 (c) Andrey Popp <8mayday@gmail.com>
 */
"use strict";

var qs                    = require('querystring');
var React                 = require('react-tools/build/modules/React');
var createRouter          = require('./router');

function Controller(routes, opts) {
  opts = opts || {};
  routes = routes || {};

  this.routes = routes;
  this.opts = opts;
  this.router = createRouter(routes);
  this.activeRequest = null;
  this.activeComponent = null;

  this.renderComponent = opts.renderComponent ||
    renderComponent;

  this.renderComponentToString = opts.renderComponentToString ||
    renderComponentToString;

  this.onPopState = skipFirst(this.onPopState.bind(this));
}

Controller.prototype = {
  /**
   * Start controller
   *
   * @param {Object} data Bootstrap data which will be passed to the first
   *                      matched component
   * @param {Callback} cb
   */
  start: function(data, cb) {
    window.addEventListener('popstate', this.onPopState);
    this.process(null, function(err, controller) {
      if (err)
        cb ? cb(err) : throwAsync(err);
      if (this.opts.started) this.opts.started.call(this);
      if (cb) cb(err, controller);
    }.bind(this));
  },

  /**
   * Stop controller
   */
  stop: function() {
    window.removeEventListener('popstate', this.onPopState);
    var mountPoint = this.getMountPoint();
    React.unmountAndReleaseReactRootNode(mountPoint);
  },

  /**
   * Navigate to a new URL
   *
   * @param {String|Request} URL
   * @param {Callback} cb
   */
  navigate: function(request, cb) {
    if (isString(request))
      request = createRequestFromURL(request);
    var url = createURL(request);
    window.history.pushState(null, '', url);
    this.process(request, cb);
  },

  /**
   * Navigate to a new URL by updating querystring
   *
   * @param {Object} query Values for querystring
   * @param {Callback} cb
   */
  navigateQuery: function(query, cb) {
    var k, newQuery = {}
    for (k in this.activeRequest.query)
      newQuery[k] = this.activeRequest.query[k];
    for (k in query)
      newQuery[k] = query[k];
    var request = {path: this.activeRequest.path, query: newQuery};
    this.navigate(request);
  },

  /**
   * Generate markup for a component for a specified request.
   *
   * This method doesn't touch the DOM and could be used on server to
   * pre-generate markup for a specified request.
   *
   * @param {String|Request} request
   * @param {Callback} cb
   */
  generateMarkup: function(request, cb) {
    if (isString(request))
      request = createRequestFromURL(request);
    var component = this.createComponent(request);
    if (!component) {
      return cb(new NotFoundError(request.path));
    }
    this.renderComponentToString(component, cb);
  },

  /**
   * Get mount point
   *
   * @private
   */
  getMountPoint: function() {
    if (this.opts.mountPoint) {
      return typeof this.opts.mountPoint === 'function' ?
        this.opts.mountPoint.call(this) :
        this.opts.mountPoint;
    } else {
      return document.body;
    }
  },

  /**
   * Process request
   *
   * @private
   */
  process: function(request, cb) {
    request = request || createRequestFromLocation(window.location);
    cb = cb || function(err) { if (err) throwAsync(err); };

    var component = this.createComponent(request);
    if (!component)
      return cb(new NotFoundError(request.path));

    var mountPoint = this.getMountPoint();

    this.renderComponent(component, mountPoint, function(err, component) {
      if (err)
        return cb(err);

      this.activeRequest = request;
      this.activeComponent = component;

      cb(null, this);
    }.bind(this));
  },

  /**
   * Create component for request
   *
   * @private
   */
  createComponent: function(request) {
    var match = this.router.match(request.path);

    if (!match)
      return null;

    return match.handler({
      controller: this,
      request: {
        path: request.path,
        query: request.query || {},
        params: match.params || {}
      },
      data: request.data,
      options: this.opts.options
    });
  },

  /**
   * Handle 'popstate' event
   *
   * @private
   */
  onPopState: function(e) {
    e.preventDefault();
    this.process(null);
  }
};

/**
 * If object is a string
 *
 * @param {Object} obj
 */
function isString(obj) {
  return Object.prototype.toString.call(obj) === '[object String]';
}

/**
 * Skip first invokation for a specified func
 *
 * @param {Function} func
 */
function skipFirst(func) {
  var n = 0;
  return function() {
    if (n > 0) return func.apply(this, arguments);
    n = n + 1;
  }
}

/**
 * Throw exception in an async way.
 */
function throwAsync(err) {
  setTimeout(function() { throw err; }, 0);
}

function renderComponentAsync(component, element, cb) {
  try {
    component = React.renderComponent(component, element);
  } catch (err) {
    return cb(err);
  }
  cb(null, component);
}

function renderComponent(component, element, cb) {
  var doc = element.ownerDocument;

  if (doc.readyState === 'interactive' || doc.readyState === 'complete') {
    renderComponentAsync(component, element, cb);
  } else {
    window.addEventListener('DOMContentLoaded', function() {
      renderComponentAsync(component, element, cb);
    });
  }
}

function renderComponentToString(component, cb) {
  React.renderComponentToString(component, cb.bind(null, null));
}

/**
 * Error which will be thrown in case of no match found for a processed request.
 *
 * @param {String} url
 */
function NotFoundError(url) {
  Error.call(this, 'not found: ' + url);
  this.url = url;
}
NotFoundError.prototype = new Error();
NotFoundError.prototype.constructor = NotFoundError;
NotFoundError.prototype.name = 'NotFoundError';
NotFoundError.prototype.isNotFoundError = true;

function createURL(request) {
  var url = request.path;
  if (request.query)
    url = url + '?' + qs.stringify(request.query);
  return url;
}

/**
 * Create request from URL
 *
 * @param {String} url
 * @param {Object} data
 */
function createRequestFromURL(url, data) {
  if (url.indexOf('?') > -1) {
    var parts = url.split('?');
    return {
      path: parts[0],
      query: qs.parse(parts[1]),
      data: data
    };
  } else {
    return {
      path: url,
      query: undefined,
      data: data
    };
  }
}

/**
 * Create request from location (such as window.location)
 *
 * @param {Location} loc
 * @param {Object} data
 */
function createRequestFromLocation(loc, data) {
  return {
    path: loc.pathname,
    query: loc.search ? qs.parse(loc.search.slice(1)) : null,
    data: data
  };
}

/**
 * Create controller
 *
 * @param {Object} routes Mapping from URL patterns to React components
 */
function createController(routes, opts) {
  return new Controller(routes, opts);
}

module.exports = createController;
module.exports.createController = createController;
module.exports.createRequestFromURL = createRequestFromURL;
module.exports.createRequestFromLocation = createRequestFromLocation;
module.exports.createRouter = createRouter;
module.exports.createURL = createURL;
module.exports.renderComponent = renderComponent;
module.exports.renderComponentToString = renderComponentToString;
module.exports.NotFoundError = NotFoundError;
<|endoftext|>


<commit_before>import { sync as exec } from 'execa';

import { sync as glob } from 'glob';

import {
  readFileSync as readFile,
  existsSync as exists
} from 'fs';

import path from 'path';

import DmnModdle from '../..';

import SchemaValidator from 'xsd-schema-validator';

import { expect } from 'chai';

const DMN_XSD = 'resources/dmn/xsd/DMN13.xsd';

const tckDirectory = 'tmp/tck';

describe('dmn-moddle - TCK roundtrip', function() {

  const moddle = new DmnModdle();

  this.timeout(30000);

  if (exists(path.join(__dirname, tckDirectory, '.git'))) {
    console.log('tck repository already cloned, fetching and checking out origin/master...');

    const cwd = path.join(__dirname, tckDirectory);

    exec('git', [ 'fetch' ], { cwd });
    exec('git', [ 'checkout', 'origin/master' ], { cwd });
  } else {
    console.log(`cloning tck repository to ${ tckDirectory }...`);

    exec(
      'git',
      [ 'clone', '--depth=1', 'git@github.com:dmn-tck/tck.git', tckDirectory ],
      { cwd: __dirname }
    );
  }

  const fileNames = glob(tckDirectory + '/TestCases/**/*.dmn', { cwd: __dirname });

  for (const fileName of fileNames) {

    it(`should serialize valid DMN xml after read (${ fileName })`, function(done) {
      this.timeout(5000);

      // given
      let fileContents = readFile(`${ __dirname }/${ fileName }`, 'utf8');

      // replace DMN 1.2 namespaces with DMN 1.3 namespaces
      fileContents = replaceNamespaces(fileContents, {
        'http://www.omg.org/spec/DMN/20180521/MODEL/': 'https://www.omg.org/spec/DMN/20191111/MODEL/',
        'http://www.omg.org/spec/DMN/20180521/DMNDI/': 'https://www.omg.org/spec/DMN/20191111/DMNDI/',
      });

      // when
      moddle.fromXML(fileContents, 'dmn:Definitions', function(err, result, context) {

        if (err) {
          return done(err);
        }

        try {
          expect(context.warnings).to.be.empty;
        } catch (err) {
          return done(err);
        }

        return toXML(result, { format: true }, function(err, xml) {

          // then
          validate(err, xml, done);
        });
      });
    });

  }

});

/**
 * Replace namespaces in XML.
 *
 * @param {string} xml
 * @param {Object} namespaces
 *
 * @returns {string}
 */
function replaceNamespaces(xml, namespaces) {
  for (const namespace in namespaces) {
    const namespaceRegExp = new RegExp(namespace, 'g');

    xml = xml.replace(namespaceRegExp, namespaces[ namespace ]);
  }

  return xml;
}

function toXML(element, opts, done) {
  element.$model.toXML(element, opts, done);
}

function validate(err, xml, done) {

  if (err) {
    return done(err);
  }

  if (!xml) {
    return done(new Error('XML is not defined'));
  }

  SchemaValidator.validateXML(xml, DMN_XSD, function(err, result) {

    if (err) {
      return done(err);
    }

    expect(result.valid).to.be.true;
    done();
  });
}<commit_msg>test(tck): improve spec output<commit_after>import { sync as exec } from 'execa';

import { sync as glob } from 'glob';

import {
  readFileSync as readFile,
  existsSync as exists
} from 'fs';

import path from 'path';

import DmnModdle from '../..';

import SchemaValidator from 'xsd-schema-validator';

import { expect } from 'chai';

const DMN_XSD = 'resources/dmn/xsd/DMN13.xsd';

const tckDirectory = 'tmp/tck';

describe('dmn-moddle - TCK roundtrip', function() {

  const moddle = new DmnModdle();

  this.timeout(30000);

  if (exists(path.join(__dirname, tckDirectory, '.git'))) {
    console.log('tck repository already cloned, fetching and checking out origin/master...');

    const cwd = path.join(__dirname, tckDirectory);

    exec('git', [ 'fetch' ], { cwd });
    exec('git', [ 'checkout', 'origin/master' ], { cwd });
  } else {
    console.log(`cloning tck repository to ${ tckDirectory }...`);

    exec(
      'git',
      [ 'clone', '--depth=1', 'git@github.com:dmn-tck/tck.git', tckDirectory ],
      { cwd: __dirname }
    );
  }

  const fileNames = glob(tckDirectory + '/TestCases/**/*.dmn', { cwd: __dirname });

  describe('should roundtrip', function() {

    for (const fileName of fileNames) {

      it(fileName, function(done) {
        this.timeout(5000);

        // given
        let fileContents = readFile(`${ __dirname }/${ fileName }`, 'utf8');

        // replace DMN 1.2 namespaces with DMN 1.3 namespaces
        fileContents = replaceNamespaces(fileContents, {
          'http://www.omg.org/spec/DMN/20180521/MODEL/': 'https://www.omg.org/spec/DMN/20191111/MODEL/',
          'http://www.omg.org/spec/DMN/20180521/DMNDI/': 'https://www.omg.org/spec/DMN/20191111/DMNDI/',
        });

        // when
        moddle.fromXML(fileContents, 'dmn:Definitions', function(err, result, context) {

          if (err) {
            return done(err);
          }

          try {
            expect(context.warnings).to.be.empty;
          } catch (err) {
            return done(err);
          }

          return toXML(result, { format: true }, function(err, xml) {

            // then
            validate(err, xml, done);
          });
        });
      });

    }

  });

});

/**
 * Replace namespaces in XML.
 *
 * @param {string} xml
 * @param {Object} namespaces
 *
 * @returns {string}
 */
function replaceNamespaces(xml, namespaces) {
  for (const namespace in namespaces) {
    const namespaceRegExp = new RegExp(namespace, 'g');

    xml = xml.replace(namespaceRegExp, namespaces[ namespace ]);
  }

  return xml;
}

function toXML(element, opts, done) {
  element.$model.toXML(element, opts, done);
}

function validate(err, xml, done) {

  if (err) {
    return done(err);
  }

  if (!xml) {
    return done(new Error('XML is not defined'));
  }

  SchemaValidator.validateXML(xml, DMN_XSD, function(err, result) {

    if (err) {
      return done(err);
    }

    expect(result.valid).to.be.true;
    done();
  });
}<|endoftext|>


<commit_before><commit_msg>Change talks descriptions event<commit_after><|endoftext|>


<commit_before>var util = require('util'),
    path = require('path'),
    fs = require('fs'),
    yeoman = require('../../../'),
    grunt = require('grunt'),
    rimraf = require('rimraf'),
    exec = require('child_process').exec;

module.exports = Generator;

function Generator() {
  yeoman.generators.Base.apply(this, arguments);

  this.sourceRoot(path.join(__dirname, 'templates'));
}

util.inherits(Generator, yeoman.generators.NamedBase);

// get the latest stable version of Wordpress
Generator.prototype.getVersion = function getVersion() {
  var cb = this.async(),
      self = this,
      latestVersion = '3.4.2'; // we still store the latest version to avoid throwing error

  grunt.log.writeln('');
  grunt.log.writeln('Trying to get the latest stable version of Wordpress');

  // try to get the latest version using the git tags
  try {
    var version = exec('git ls-remote --tags git://github.com/WordPress/WordPress.git | tail -n 1', function(err, stdout, stderr) {
                    if (err) {
                      self.latestVersion = latestVersion;
                    }
                    else {
                      var pattern = /\d\.\d\.\d/ig;
                      var match = pattern.exec(stdout);

                      if (match !== null) {
                        self.latestVersion = match[0];
                        grunt.log.writeln('Latest version: '+self.latestVersion);
                      }
                      else {
                        self.latestVersion = latestVersion;
                      }
                    }

                    cb();
                  });
  }
  catch(e) {
    self.latestVersion = latestVersion;
    cb();
  }
}

// try to find the config file and read the infos to set the prompts default values
Generator.prototype.getConfig = function getConfig() {
  var cb = this.async(),
      self = this;

  self.defaultAuthorName = '';
  self.defaultAuthorURI = '';
  self.configExists = false;

  try {
    var home = process.env.HOME || process.env.USERPROFILE;
    var configFile = path.join(home, '.yeoman/yeoman-wordpress/config.json');
    fs.readFile(configFile, 'utf8', function(err, data) {
      if (!err) {
        var config = JSON.parse(data);
        self.defaultAuthorName = config.authorName;
        self.defaultAuthorURI = config.authorURI;
        self.configExists = true;
      }

      cb();
    });
  }
  catch(e) {
    cb();
  }
}

Generator.prototype.askFor = function askFor(arguments) {
  var cb = this.async(),
      self = this;

  var prompts = [{
          name: 'themeName',
          message: 'Name of the theme you want to use: ',
          default: 'mytheme'
      },
      {
          name: 'themeBoilerplate',
          message: 'Starter theme (please provide a github link): ',
          default: 'https://github.com/automattic/_s'
      },
      {
          name: 'wordpressVersion',
          message: 'Which version of Wordpress do you want?',
          default: self.latestVersion
      },
      {
          name: 'includeRequireJS',
          message: 'Would you like to include RequireJS (for AMD support)?',
          default: 'Y/n',
          warning: 'Yes: RequireJS will be placed into the JavaScript vendor directory.'
      },
      {
          name: 'authorName',
          message: 'Author name: ',
          default: self.defaultAuthorName
      },
      {
          name: 'authorURI',
          message: 'Author URI: ',
          default: self.defaultAuthorURI
      }];

  this.prompt(prompts, function(e, props) {
    if(e) { return self.emit('error', e); }

    // set the property to parse the gruntfile
    self.themeNameOriginal = props.themeName;
    self.themeName = props.themeName.replace(/\ /g, '').toLowerCase();
    self.themeBoilerplate = props.themeBoilerplate;
    self.wordpressVersion = props.wordpressVersion;
    self.includeRequireJS = (/y/i).test(props.includeRequireJS);
    self.authorName = props.authorName;
    self.authorURI = props.authorURI;

    // check if the user only gave the repo url or the entire url with /tarball/{branch}
    var tarballLink = (/[.]*tarball\/[.]*/).test(self.themeBoilerplate);
    if (!tarballLink) {
      // if the user gave the repo url we add the end of the url. we assume he wants the master branch
      var lastChar = self.themeBoilerplate.substring(self.themeBoilerplate.length - 1);
      if (lastChar === '/') {
        self.themeBoilerplate = self.themeBoilerplate+'tarball/master';
      }
      else {
        self.themeBoilerplate = self.themeBoilerplate+'/tarball/master';
      }
    }

    // create the config file it does not exists
    if (!self.configExists) {
      var configData = '{ "authorName": "'+self.authorName+'", "authorURI": "'+self.authorURI+'"}';
      var home = process.env.HOME || process.env.USERPROFILE;
      var configDirectory = path.join(home, '.yeoman/yeoman-wordpress');

      fs.mkdir(configDirectory, '0777', function() {
        var configFile = path.join(configDirectory, 'config.json');
        fs.writeFile(configFile, configData, 'utf8', cb);
      });
    }
    else {
      cb();
    }
  });
}

// download the framework and unzip it in the project app/
Generator.prototype.createApp = function createApp(cb) {
  var cb = this.async(),
      self = this;

  grunt.log.writeln('Let\'s download the framework, shall we?');
  grunt.log.writeln('Downloading Wordpress version '+self.wordpressVersion);
  this.tarball('https://github.com/WordPress/WordPress/tarball/'+self.wordpressVersion, 'app', cb);
}

// remove the basic theme and create a new one
Generator.prototype.createTheme = function createTheme() {
  var cb = this.async(),
      self = this;

  grunt.log.writeln('First let\'s remove the built-in themes we will not use');
  // remove the existing themes
  fs.readdir('app/wp-content/themes', function(err, files) {
    if (typeof files != 'undefined' && files.length != 0) {
      files.forEach(function(file) {
        var pathFile = fs.realpathSync('app/wp-content/themes/'+file);
        var isDirectory = fs.statSync(pathFile).isDirectory();

        if (isDirectory) {
          rimraf.sync(pathFile);
          grunt.log.writeln('Removing ' + pathFile);
        }
      });
    }

    grunt.log.writeln('');
    grunt.log.writeln('Now we download the theme');

    // create the theme
    self.tarball(self.themeBoilerplate, 'app/wp-content/themes/'+self.themeName, cb);
  });
}

// add Require.js if needed
Generator.prototype.requireJS = function requireJS() {
  var cb = this.async(),
      self = this;

  if (self.includeRequireJS) {
    this.remote('jrburke', 'requirejs', '2.0.5', function(err, remote) {
      if (err) { return cb(err); }

      fs.mkdir('app/wp-content/themes/'+self.themeName+'/js', function() {
        remote.copy('require.js', 'app/wp-content/themes/'+self.themeName+'/js/vendors/require.js');

        cb();
      });
    });
  }
  else {
    cb();
  }
}

// rename all the css files to scss
Generator.prototype.convertFiles = function convertFiles() {
  var cb = this.async(),
      self = this;

  // parse recursively a directory and rename the css files to .scss
  function parseDirectory(path) {
    fs.readdir(path, function(err, files) {
      files.forEach(function(file) {
        var pathFile = fs.realpathSync(path+'/'+file);
        var isDirectory = fs.statSync(pathFile).isDirectory();

        if (isDirectory) {
          parseDirectory(pathFile);
        }
        else {
          var cssName = /[.]*\.css/i;
          if (cssName.test(file)) {
            var newName = pathFile.substring(0, pathFile.length - 3) + 'scss';
            // to avoid deleting style.css which is needed to activate the them,
            // we do not rename but only create another file then copy the content
            fs.open(newName, 'w', '0666', function() {
              fs.readFile(pathFile, 'utf8', function (err, data) {
                if (err) throw err;
                // Insert the given theme name into SCSS and CSS files
                data = data.replace(/^.*Theme Name:.*$/mg, 'Theme Name: ' + self.themeNameOriginal);
                data = data.replace(/^.*Author: .*$/mg, 'Author: ' + self.authorName);
                data = data.replace(/^.*Author URI: .*$/mg, 'Author URI: ' + self.authorURI);

                fs.writeFile(newName, data);
                fs.writeFile(pathFile, data);
              });
            });
          }
        }
      });
    });
  }

  grunt.log.writeln('Renaming the css files to scss');
  parseDirectory('app/wp-content/themes/'+self.themeName);

  cb();
}

// generate the files to use Yeoman and the git related files
Generator.prototype.createYeomanFiles = function createYeomanFiles() {
  this.template('Gruntfile.js');
  this.copy('package.json', 'package.json');
  this.copy('gitignore', '.gitignore');
  this.copy('gitattributes', '.gitattributes');
}

Generator.prototype.endGenerator = function endGenerator() {
  grunt.log.writeln('');
  grunt.log.writeln('Looks like we\'re done!');
  grunt.log.writeln('Now you just need to install Wordpress the usual way');
  grunt.log.writeln('Don\'t forget to activate the new theme in the admin panel, and then you can start coding!');
  grunt.log.writeln('');
}<commit_msg>The config file now also store the starter theme URL<commit_after>var util = require('util'),
    path = require('path'),
    fs = require('fs'),
    yeoman = require('../../../'),
    grunt = require('grunt'),
    rimraf = require('rimraf'),
    exec = require('child_process').exec;

module.exports = Generator;

function Generator() {
  yeoman.generators.Base.apply(this, arguments);

  this.sourceRoot(path.join(__dirname, 'templates'));
}

util.inherits(Generator, yeoman.generators.NamedBase);

// get the latest stable version of Wordpress
Generator.prototype.getVersion = function getVersion() {
  var cb = this.async(),
      self = this,
      latestVersion = '3.4.2'; // we still store the latest version to avoid throwing error

  grunt.log.writeln('');
  grunt.log.writeln('Trying to get the latest stable version of Wordpress');

  // try to get the latest version using the git tags
  try {
    var version = exec('git ls-remote --tags git://github.com/WordPress/WordPress.git | tail -n 1', function(err, stdout, stderr) {
                    if (err) {
                      self.latestVersion = latestVersion;
                    }
                    else {
                      var pattern = /\d\.\d\.\d/ig;
                      var match = pattern.exec(stdout);

                      if (match !== null) {
                        self.latestVersion = match[0];
                        grunt.log.writeln('Latest version: '+self.latestVersion);
                      }
                      else {
                        self.latestVersion = latestVersion;
                      }
                    }

                    cb();
                  });
  }
  catch(e) {
    self.latestVersion = latestVersion;
    cb();
  }
}

// try to find the config file and read the infos to set the prompts default values
Generator.prototype.getConfig = function getConfig() {
  var cb = this.async(),
      self = this;

  self.defaultAuthorName = '';
  self.defaultAuthorURI = '';
  self.defaultTheme = 'https://github.com/automattic/_s';
  self.configExists = false;

  try {
    var home = process.env.HOME || process.env.USERPROFILE;
    var configFile = path.join(home, '.yeoman/yeoman-wordpress/config.json');
    fs.readFile(configFile, 'utf8', function(err, data) {
      if (!err) {
        var config = JSON.parse(data);
        self.defaultAuthorName = config.authorName || '';
        self.defaultAuthorURI = config.authorURI || '';
        self.defaultTheme = config.theme || self.defaultTheme;

        // if a default value is missing in the config file we re-create it
        if (config.defaultAuthorName && config.defaultAuthorURI && config.defaultTheme) {
          self.configExists = true;
        }
      }

      cb();
    });
  }
  catch(e) {
    cb();
  }
}

Generator.prototype.askFor = function askFor(arguments) {
  var cb = this.async(),
      self = this;

  var prompts = [{
          name: 'themeName',
          message: 'Name of the theme you want to use: ',
          default: 'mytheme'
      },
      {
          name: 'themeBoilerplate',
          message: 'Starter theme (please provide a github link): ',
          default: self.defaultTheme
      },
      {
          name: 'wordpressVersion',
          message: 'Which version of Wordpress do you want?',
          default: self.latestVersion
      },
      {
          name: 'includeRequireJS',
          message: 'Would you like to include RequireJS (for AMD support)?',
          default: 'Y/n',
          warning: 'Yes: RequireJS will be placed into the JavaScript vendor directory.'
      },
      {
          name: 'authorName',
          message: 'Author name: ',
          default: self.defaultAuthorName
      },
      {
          name: 'authorURI',
          message: 'Author URI: ',
          default: self.defaultAuthorURI
      }];

  this.prompt(prompts, function(e, props) {
    if(e) { return self.emit('error', e); }

    // set the property to parse the gruntfile
    self.themeNameOriginal = props.themeName;
    self.themeName = props.themeName.replace(/\ /g, '').toLowerCase();
    self.themeOriginalURL = props.themeBoilerplate;
    self.themeBoilerplate = props.themeBoilerplate;
    self.wordpressVersion = props.wordpressVersion;
    self.includeRequireJS = (/y/i).test(props.includeRequireJS);
    self.authorName = props.authorName;
    self.authorURI = props.authorURI;

    // check if the user only gave the repo url or the entire url with /tarball/{branch}
    var tarballLink = (/[.]*tarball\/[.]*/).test(self.themeBoilerplate);
    if (!tarballLink) {
      // if the user gave the repo url we add the end of the url. we assume he wants the master branch
      var lastChar = self.themeBoilerplate.substring(self.themeBoilerplate.length - 1);
      if (lastChar === '/') {
        self.themeBoilerplate = self.themeBoilerplate+'tarball/master';
      }
      else {
        self.themeBoilerplate = self.themeBoilerplate+'/tarball/master';
      }
    }

    // create the config file it does not exists
    if (!self.configExists) {
      var configData = '{\n\t// these values are used for the yeoman-wordpress generator\n\t// for more informations see https://github.com/romainberger/yeoman-wordpress\n\t';
          configData += '"authorName": "'+self.authorName+'",\n\t"authorURI": "'+self.authorURI+'",\n\t';
          configData += '// please use a github link for the default theme\n\t"theme": "'+self.themeOriginalURL+'"\n}';
      var home = process.env.HOME || process.env.USERPROFILE;
      var configDirectory = path.join(home, '.yeoman/yeoman-wordpress');

      fs.mkdir(configDirectory, '0777', function() {
        var configFile = path.join(configDirectory, 'config.json');
        fs.writeFile(configFile, configData, 'utf8', cb);
      });
    }
    else {
      cb();
    }
  });
}

// download the framework and unzip it in the project app/
Generator.prototype.createApp = function createApp(cb) {
  var cb = this.async(),
      self = this;

  grunt.log.writeln('Let\'s download the framework, shall we?');
  grunt.log.writeln('Downloading Wordpress version '+self.wordpressVersion);
  this.tarball('https://github.com/WordPress/WordPress/tarball/'+self.wordpressVersion, 'app', cb);
}

// remove the basic theme and create a new one
Generator.prototype.createTheme = function createTheme() {
  var cb = this.async(),
      self = this;

  grunt.log.writeln('First let\'s remove the built-in themes we will not use');
  // remove the existing themes
  fs.readdir('app/wp-content/themes', function(err, files) {
    if (typeof files != 'undefined' && files.length != 0) {
      files.forEach(function(file) {
        var pathFile = fs.realpathSync('app/wp-content/themes/'+file);
        var isDirectory = fs.statSync(pathFile).isDirectory();

        if (isDirectory) {
          rimraf.sync(pathFile);
          grunt.log.writeln('Removing ' + pathFile);
        }
      });
    }

    grunt.log.writeln('');
    grunt.log.writeln('Now we download the theme');

    // create the theme
    self.tarball(self.themeBoilerplate, 'app/wp-content/themes/'+self.themeName, cb);
  });
}

// add Require.js if needed
Generator.prototype.requireJS = function requireJS() {
  var cb = this.async(),
      self = this;

  if (self.includeRequireJS) {
    this.remote('jrburke', 'requirejs', '2.0.5', function(err, remote) {
      if (err) { return cb(err); }

      fs.mkdir('app/wp-content/themes/'+self.themeName+'/js', function() {
        remote.copy('require.js', 'app/wp-content/themes/'+self.themeName+'/js/vendors/require.js');

        cb();
      });
    });
  }
  else {
    cb();
  }
}

// rename all the css files to scss
Generator.prototype.convertFiles = function convertFiles() {
  var cb = this.async(),
      self = this;

  // parse recursively a directory and rename the css files to .scss
  function parseDirectory(path) {
    fs.readdir(path, function(err, files) {
      files.forEach(function(file) {
        var pathFile = fs.realpathSync(path+'/'+file);
        var isDirectory = fs.statSync(pathFile).isDirectory();

        if (isDirectory) {
          parseDirectory(pathFile);
        }
        else {
          var cssName = /[.]*\.css/i;
          if (cssName.test(file)) {
            var newName = pathFile.substring(0, pathFile.length - 3) + 'scss';
            // to avoid deleting style.css which is needed to activate the them,
            // we do not rename but only create another file then copy the content
            fs.open(newName, 'w', '0666', function() {
              fs.readFile(pathFile, 'utf8', function (err, data) {
                if (err) throw err;
                // Insert the given theme name into SCSS and CSS files
                data = data.replace(/^.*Theme Name:.*$/mg, 'Theme Name: ' + self.themeNameOriginal);
                data = data.replace(/^.*Author: .*$/mg, 'Author: ' + self.authorName);
                data = data.replace(/^.*Author URI: .*$/mg, 'Author URI: ' + self.authorURI);

                fs.writeFile(newName, data);
                fs.writeFile(pathFile, data);
              });
            });
          }
        }
      });
    });
  }

  grunt.log.writeln('Renaming the css files to scss');
  parseDirectory('app/wp-content/themes/'+self.themeName);

  cb();
}

// generate the files to use Yeoman and the git related files
Generator.prototype.createYeomanFiles = function createYeomanFiles() {
  this.template('Gruntfile.js');
  this.copy('package.json', 'package.json');
  this.copy('gitignore', '.gitignore');
  this.copy('gitattributes', '.gitattributes');
}

Generator.prototype.endGenerator = function endGenerator() {
  grunt.log.writeln('');
  grunt.log.writeln('Looks like we\'re done!');
  grunt.log.writeln('Now you just need to install Wordpress the usual way');
  grunt.log.writeln('Don\'t forget to activate the new theme in the admin panel, and then you can start coding!');
  grunt.log.writeln('');
}<|endoftext|>


<commit_before>var sharedConfig = require('./karma-shared.conf');

module.exports = function (config) {
    var conf = sharedConfig();

    conf.files = conf.files.concat([

        {
            pattern: 'app/resources/**',
            included: false,
            served: true
        },

        //extra testing code
        'app/bower_components/angular-mocks/angular-mocks.js',

        //mocha stuff
        'test/mocha.conf.js',

        //test files
        'test/unit/**/*.js'
    ]);

    conf.proxies = {
        '/resources/': 'http://localhost:9876/base/app/resources/'
    };

    config.set(conf);
};
<commit_msg>- Set phantomJS for unit tests to avoid launching browser window<commit_after>var sharedConfig = require('./karma-shared.conf');

module.exports = function (config) {
    var conf = sharedConfig();

    conf.browsers = ['PhantomJS'];

    conf.files = conf.files.concat([

        {
            pattern: 'app/resources/**',
            included: false,
            served: true
        },

        //extra testing code
        'app/bower_components/angular-mocks/angular-mocks.js',

        //mocha stuff
        'test/mocha.conf.js',

        //test files
        'test/unit/**/*.js'
    ]);

    conf.proxies = {
        '/resources/': 'http://localhost:9876/base/app/resources/'
    };

    config.set(conf);
};
<|endoftext|>


<commit_before>$(document).ready( function()
{
	//Put in the header
	$("body").prepend(''
		+ ''
		    + ' indigoBox'

		  + '
'
		        + '
Home
'
		        + '
About
'
		        + '
Projects' // projects.html
		            + '
'
		                + '
Christmas In Clouds
'
		                + '
Snowshoes
'
		            + '
'
		        + '
'
//		        + '
Sneak Peek
'
		        + '
Contact
'
		    + '
'
		+ ''
	+ '');

	if(window.location.href.indexOf("indigobox.us") > -1) //if production
	{
		$(".menu a").each(function()
		{
			var href = $(this).attr("href");
			$(this).attr("href", href.replace(".html",""));
		});
	}

	if(window.location.href.indexOf("about") > -1)
	{
		$(".menu li").removeClass("selected");
		$(".menu #about").addClass("selected");
	}
	else if(window.location.href.indexOf("projects") > -1)
	{
		$(".menu li").removeClass("selected");
		$(".menu #projects").addClass("selected");
	}
	else if(window.location.href.indexOf("contact") > -1)
	{
		$(".menu li").removeClass("selected");
		$(".menu #contact").addClass("selected");
	}
	else if(window.location.href.indexOf("sneak-peek") > -1)
	{
		$(".menu li").removeClass("selected");
		$(".menu #sneak-peek").addClass("selected");
	}
});
<commit_msg>Updated Menu<commit_after>$(document).ready( function()
{
	//Put in the header
	$("body").prepend(''
		+ ''
		    + ' indigoBox'

		  + '
'
		        + '
Home
'
		        + '
About
'
		        + '
Projects' // projects.html
		            + '
'
		                + '
Snowshoes
'
						+ '
Carpe
'
						+ '
Scroll Stop
'
		            + '
'
		        + '
'
//		        + '
Sneak Peek
'
		        + '
Contact
'
		    + '
'
		+ ''
	+ '');

	if(window.location.href.indexOf("indigobox.us") > -1) //if production
	{
		$(".menu a").each(function()
		{
			var href = $(this).attr("href");
			$(this).attr("href", href.replace(".html",""));
		});
	}

	if(window.location.href.indexOf("about") > -1)
	{
		$(".menu li").removeClass("selected");
		$(".menu #about").addClass("selected");
	}
	else if(window.location.href.indexOf("projects") > -1)
	{
		$(".menu li").removeClass("selected");
		$(".menu #projects").addClass("selected");
	}
	else if(window.location.href.indexOf("contact") > -1)
	{
		$(".menu li").removeClass("selected");
		$(".menu #contact").addClass("selected");
	}
	else if(window.location.href.indexOf("sneak-peek") > -1)
	{
		$(".menu li").removeClass("selected");
		$(".menu #sneak-peek").addClass("selected");
	}
});
<|endoftext|>


<commit_before><commit_msg>Fix parameter key: json => _params<commit_after><|endoftext|>


<commit_before>module.exports = booleanJSONToCommonForm

function booleanJSONToCommonForm(argument) {
  if (Array.isArray(argument)) {
    return { content: argument } }
  else if ('and' in argument) {
    return {
      content: [ 'all of the following are true:' ]
        .concat(
          argument.and.map(function(conjunct) {
            return {
              form: booleanJSONToCommonForm(conjunct) } })) } }
  else if ('or' in argument) {
    return {
      content: [ 'any of the following is true:' ]
        .concat(
          argument.or.map(function(disjunct) {
            return {
              form: booleanJSONToCommonForm(disjunct) } })) } }
  else if ('not' in argument) {
    return {
      content: [ 'it is not the case that ' ]
        .concat(booleanJSONToCommonForm(argument.not).content) } }
  else {
    throw new Error('Invalid input') } }
<commit_msg>Avoid "following"<commit_after>module.exports = booleanJSONToCommonForm

function booleanJSONToCommonForm(argument) {
  if (Array.isArray(argument)) {
    return { content: argument } }
  else if ('and' in argument) {
    return {
      content: [ 'all of these are the case:' ]
        .concat(
          argument.and.map(function(conjunct) {
            return {
              form: booleanJSONToCommonForm(conjunct) } })) } }
  else if ('or' in argument) {
    return {
      content: [ 'any of these is the case:' ]
        .concat(
          argument.or.map(function(disjunct) {
            return {
              form: booleanJSONToCommonForm(disjunct) } })) } }
  else if ('not' in argument) {
    return {
      content: [ 'it is not the case that ' ]
        .concat(booleanJSONToCommonForm(argument.not).content) } }
  else {
    throw new Error('Invalid input') } }
<|endoftext|>


<commit_before><commit_msg>Smarter keypress redirection<commit_after><|endoftext|>


<commit_before>'use strict';
<commit_msg>Putting it all together<commit_after>'use strict';
const config = require('./config');
const generate = require('./lib/schema/generate');
const manifest = require('./lib/manifest');
const tables = require('./lib/tables');
const cleanup = require('./lib/cleanup');

function checkSetup () {
  cleanup();
  // Generate and execute DDL against the PostgreSQL database if `db.setup` flag is false
  if (typeof config.get('db.setup') === 'boolean' && config.get('db.setup') === false) {
    console.log('Database schema has not been setup! Beginning schema generation and execution.\n');
    // Generate DDL based on the Canvas Data API '/schema/latest' endpoint
    generate()
      .then(results => {
        console.log(`DDL generation complete.`);
        console.log(`${results.join(' | ')} \n`);
        // Execute DDL against the PostgreSQL database.
        const execute = require('./lib/schema/execute');
        execute();
        checkSeed();
      }, error => {
        console.error(error);
      });
  } else {
    console.log('Database schema has been setup - skipping.');
    checkSeed();
  }
}

function checkSeed () {
  // Seed PostgreSQL database if `db.seeded `flag is false
  if (typeof config.get('db.seeded') === 'boolean' && config.get('db.seeded') === false) {
    console.log(`Database has not been seeded! Beginning seed process.\n`);

    // Fetch the list of resources from the Canvas Data API endpoint /account/self/file/sync
    manifest.fetch()
      .then(results => {
        tables.init();
        const diff = require('./lib/tables/diff');
        const process = require('./lib/tables/process');
        const manifestItems = results['files'];
        const actions = diff(manifestItems);

        const series = function (table) {
          if (table) {
            process(table, function () {
              return series(actions.shift());
            });
          } else {
            config.set('db.seeded', true);
            console.log(`\nDatabase seeding completed.`);
            cleanup();
          }
        };
        series(actions.shift());
      }, error => {
        console.error(error);
      });
  } else {
    console.log('Database has been seeded - skipping.');
  }
}

checkSetup();
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('uber', function() {
  var localStrings = new LocalStrings();

  /**
   * Options for how web history should be handled.
   **/
  var HISTORY_STATE_OPTION = {
    PUSH: 1,    // Push a new history state.
    REPLACE: 2  // Replace the current history state.
  };

  /**
  * We cache a reference to the #navigation frame here to so we don't need to
  * grab it from the DOM on each scroll.
  * @type {Node}
  * @private
  * @static
  */
  var navFrame;

  /**
   * Handles page initialization.
   */
  function onLoad(e) {
    navFrame = $('navigation');
    navFrame.dataset.width = navFrame.offsetWidth;

    // Select a page based on the page-URL.
    var params = resolvePageInfo();
    showPage(params.id, HISTORY_STATE_OPTION.REPLACE, params.path);

    window.addEventListener('message', handleWindowMessage);
    window.setTimeout(function() {
      document.documentElement.classList.remove('loading');
    }, 0);

    // HACK(dbeam): This makes the assumption that any second part to a path
    // will result in needing background navigation. We shortcut it to avoid
    // flicker on load.
    if (params.path && window.location.pathname.indexOf('settings') == 0)
      backgroundNavigation();
  }

  /**
   * Find page information from window.location. If the location doesn't
   * point to one of our pages, return default parameters.
   * @return {Object} An object containing the following parameters:
   *     id - The 'id' of the page.
   *     path - A path into the page, including search and hash. Optional.
   */
  function resolvePageInfo() {
    var params = {};
    var path = window.location.pathname;
    if (path.length > 1) {
      // Split the path into id and the remaining path.
      path = path.slice(1);
      var index = path.indexOf('/');
      if (index != -1) {
        params.id = path.slice(0, index);
        params.path = path.slice(index + 1);
      } else {
        params.id = path;
      }

      var container = $(params.id);
      if (container) {
        // The id is valid. Add the hash and search parts of the URL to path.
        params.path = (params.path || '') + window.location.search +
            window.location.hash;
      } else {
        // The target sub-page does not exist, discard the params we generated.
        params.id = undefined;
        params.path = undefined;
      }
    }
    // If we don't have a valid page, get a default.
    if (!params.id)
      params.id = getDefaultIframe().id;

    return params;
  }

  /**
   * Handler for window.onpopstate.
   * @param {Event} e The history event.
   */
  function onPopHistoryState(e) {
    if (e.state && e.state.pageId)
      showPage(e.state.pageId, HISTORY_STATE_OPTION.PUSH);
  }

  /**
   * @return {Object} The default iframe container.
   */
  function getDefaultIframe() {
    return $(localStrings.getString('helpHost'));
  }

  /**
   * @return {Object} The currently selected iframe container.
   */
  function getSelectedIframe() {
    return document.querySelector('.iframe-container.selected');
  }

  /**
   * Handles postMessage calls from the iframes of the contained pages.
   *
   * The pages request functionality from this object by passing an object of
   * the following form:
   *
   *  { method : "methodToInvoke",
   *    params : {...}
   *  }
   *
   * |method| is required, while |params| is optional. Extra parameters required
   * by a method must be specified by that method's documentation.
   *
   * @param {Event} e The posted object.
   */
  function handleWindowMessage(e) {
    if (e.data.method === 'beginInterceptingEvents')
      backgroundNavigation();
    else if (e.data.method === 'stopInterceptingEvents')
      foregroundNavigation();
    else if (e.data.method === 'setTitle')
      setTitle_(e.origin, e.data.params.title);
    else if (e.data.method === 'showPage')
      showPage(e.data.params.pageId, HISTORY_STATE_OPTION.PUSH);
    else if (e.data.method === 'navigationControlsLoaded')
      onNavigationControlsLoaded();
    else if (e.data.method === 'adjustToScroll')
      adjustToScroll(e.data.params);
    else if (e.data.method === 'mouseWheel')
      forwardMouseWheel(e.data.params);
    else
      console.error('Received unexpected message',  e.data);
  }

  /**
   * Sends the navigation iframe to the background.
   */
  function backgroundNavigation() {
    navFrame.classList.add('background');
  }

  /**
   * Retrieves the navigation iframe from the background.
   */
  function foregroundNavigation() {
    navFrame.classList.remove('background');
  }

  /**
   * Enables or disables animated transitions when changing content while
   * horizontally scrolled.
   * @param {boolean} enabled True if enabled, else false to disable.
   */
  function setContentChanging(enabled) {
    navFrame.classList[enabled ? 'add' : 'remove']('changing-content');

    if (isRTL()) {
      uber.invokeMethodOnWindow(navFrame.firstChild.contentWindow,
                                'setContentChanging',
                                enabled);
    }
  }

  /**
   * Sets the title of the page.
   * @param {Object} origin The origin of the source iframe.
   * @param {string} title The title of the page.
   */
  function setTitle_(origin, title) {
    // |iframe.src| always contains a trailing backslash while |origin| does not
    // so add the trailing source for normalization.
    var query = '.iframe-container > iframe[src="' + origin + '/"]';

    // Cache the title for the client iframe, i.e., the iframe setting the
    // title. querySelector returns the actual iframe element, so use parentNode
    // to get back to the container.
    var container = document.querySelector(query).parentNode;
    container.dataset.title = title;

    // Only update the currently displayed title if this is the visible frame.
    if (container == getSelectedIframe())
      document.title = title;
  }

  /**
   * Selects a subpage. This is called from uber-frame.
   * @param {String} pageId Should matche an id of one of the iframe containers.
   * @param {integer} historyOption Indicates whether we should push or replace
   *     browser history.
   * @param {String=} path An optional sub-page path.
   */
  function showPage(pageId, historyOption, path) {
    var container = $(pageId);
    var lastSelected = document.querySelector('.iframe-container.selected');
    if (lastSelected === container)
      return;

    // Lazy load of iframe contents.
    var frame = container.querySelector('iframe');
    var sourceUrl = container.dataset.url;
    if (!frame) {
      frame = container.ownerDocument.createElement('iframe');
      container.appendChild(frame);
      frame.src = sourceUrl;
    }
    // If there is a non-empty path, alter the location of the frame.
    if (path && path.length)
      frame.contentWindow.location.replace(sourceUrl + path);

    if (lastSelected)
      lastSelected.classList.remove('selected');
    container.classList.add('selected');
    if (container.dataset.title)
      document.title = container.dataset.title;
    $('favicon').href = container.dataset.favicon;

    setContentChanging(true);
    adjustToScroll(0);

    var selectedFrame = getSelectedIframe().querySelector('iframe');
    uber.invokeMethodOnWindow(selectedFrame.contentWindow, 'frameSelected');

    if (historyOption == HISTORY_STATE_OPTION.PUSH)
      window.history.pushState({pageId: pageId}, '', '/' + pageId);
    else if (historyOption == HISTORY_STATE_OPTION.REPLACE)
      window.history.replaceState({pageId: pageId}, '', '/' + pageId);

    updateNavigationControls();
  }

  function onNavigationControlsLoaded() {
    updateNavigationControls();
  }

  /**
   * Sends a message to uber-frame to update the appearance of the nav controls.
   * It should be called whenever the selected iframe changes.
   */
  function updateNavigationControls() {
    var iframe = getSelectedIframe();
    uber.invokeMethodOnWindow(navFrame.firstChild.contentWindow,
                              'changeSelection', {pageId: iframe.id});
  }

  /**
   * Forwarded scroll offset from a content frame's scroll handler.
   * @param {number} scrollOffset The scroll offset from the content frame.
   */
  function adjustToScroll(scrollOffset) {
    // NOTE: The scroll is reset to 0 and easing turned on every time a user
    // switches frames. If we receive a non-zero value it has to have come from
    // a real user scroll, so we disable easing when this happens.
    if (scrollOffset != 0)
      setContentChanging(false);

    if (isRTL()) {
      uber.invokeMethodOnWindow(navFrame.firstChild.contentWindow,
                                'adjustToScroll',
                                scrollOffset);
      var navWidth = Math.max(0, +navFrame.dataset.width + scrollOffset);
      navFrame.style.width = navWidth + 'px';
    } else {
      navFrame.style.webkitTransform = 'translateX(' + -scrollOffset + 'px)';
    }
  }

  /**
   * Forward scroll wheel events to subpages.
   * @param {Object} params Relevant parameters of wheel event.
   */
  function forwardMouseWheel(params) {
    var iframe = getSelectedIframe().querySelector('iframe');
    uber.invokeMethodOnWindow(iframe.contentWindow, 'mouseWheel', params);
  }

  return {
    onLoad: onLoad,
    onPopHistoryState: onPopHistoryState
  };
});

window.addEventListener('popstate', uber.onPopHistoryState);
document.addEventListener('DOMContentLoaded', uber.onLoad);
<commit_msg>Fix JavaScript style nits in resources/uber<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('uber', function() {
  var localStrings = new LocalStrings();

  /**
   * Options for how web history should be handled.
   **/
  var HISTORY_STATE_OPTION = {
    PUSH: 1,    // Push a new history state.
    REPLACE: 2  // Replace the current history state.
  };

  /**
  * We cache a reference to the #navigation frame here to so we don't need to
  * grab it from the DOM on each scroll.
  * @type {Node}
  * @private
  */
  var navFrame;

  /**
   * Handles page initialization.
   */
  function onLoad(e) {
    navFrame = $('navigation');
    navFrame.dataset.width = navFrame.offsetWidth;

    // Select a page based on the page-URL.
    var params = resolvePageInfo();
    showPage(params.id, HISTORY_STATE_OPTION.REPLACE, params.path);

    window.addEventListener('message', handleWindowMessage);
    window.setTimeout(function() {
      document.documentElement.classList.remove('loading');
    }, 0);

    // HACK(dbeam): This makes the assumption that any second part to a path
    // will result in needing background navigation. We shortcut it to avoid
    // flicker on load.
    if (params.path && window.location.pathname.indexOf('settings') == 0)
      backgroundNavigation();
  }

  /**
   * Find page information from window.location. If the location doesn't
   * point to one of our pages, return default parameters.
   * @return {Object} An object containing the following parameters:
   *     id - The 'id' of the page.
   *     path - A path into the page, including search and hash. Optional.
   */
  function resolvePageInfo() {
    var params = {};
    var path = window.location.pathname;
    if (path.length > 1) {
      // Split the path into id and the remaining path.
      path = path.slice(1);
      var index = path.indexOf('/');
      if (index != -1) {
        params.id = path.slice(0, index);
        params.path = path.slice(index + 1);
      } else {
        params.id = path;
      }

      var container = $(params.id);
      if (container) {
        // The id is valid. Add the hash and search parts of the URL to path.
        params.path = (params.path || '') + window.location.search +
            window.location.hash;
      } else {
        // The target sub-page does not exist, discard the params we generated.
        params.id = undefined;
        params.path = undefined;
      }
    }
    // If we don't have a valid page, get a default.
    if (!params.id)
      params.id = getDefaultIframe().id;

    return params;
  }

  /**
   * Handler for window.onpopstate.
   * @param {Event} e The history event.
   */
  function onPopHistoryState(e) {
    if (e.state && e.state.pageId)
      showPage(e.state.pageId, HISTORY_STATE_OPTION.PUSH);
  }

  /**
   * @return {Object} The default iframe container.
   */
  function getDefaultIframe() {
    return $(localStrings.getString('helpHost'));
  }

  /**
   * @return {Object} The currently selected iframe container.
   */
  function getSelectedIframe() {
    return document.querySelector('.iframe-container.selected');
  }

  /**
   * Handles postMessage calls from the iframes of the contained pages.
   *
   * The pages request functionality from this object by passing an object of
   * the following form:
   *
   *  { method : "methodToInvoke",
   *    params : {...}
   *  }
   *
   * |method| is required, while |params| is optional. Extra parameters required
   * by a method must be specified by that method's documentation.
   *
   * @param {Event} e The posted object.
   */
  function handleWindowMessage(e) {
    if (e.data.method === 'beginInterceptingEvents')
      backgroundNavigation();
    else if (e.data.method === 'stopInterceptingEvents')
      foregroundNavigation();
    else if (e.data.method === 'setTitle')
      setTitle_(e.origin, e.data.params.title);
    else if (e.data.method === 'showPage')
      showPage(e.data.params.pageId, HISTORY_STATE_OPTION.PUSH);
    else if (e.data.method === 'navigationControlsLoaded')
      onNavigationControlsLoaded();
    else if (e.data.method === 'adjustToScroll')
      adjustToScroll(e.data.params);
    else if (e.data.method === 'mouseWheel')
      forwardMouseWheel(e.data.params);
    else
      console.error('Received unexpected message', e.data);
  }

  /**
   * Sends the navigation iframe to the background.
   */
  function backgroundNavigation() {
    navFrame.classList.add('background');
  }

  /**
   * Retrieves the navigation iframe from the background.
   */
  function foregroundNavigation() {
    navFrame.classList.remove('background');
  }

  /**
   * Enables or disables animated transitions when changing content while
   * horizontally scrolled.
   * @param {boolean} enabled True if enabled, else false to disable.
   */
  function setContentChanging(enabled) {
    navFrame.classList[enabled ? 'add' : 'remove']('changing-content');

    if (isRTL()) {
      uber.invokeMethodOnWindow(navFrame.firstChild.contentWindow,
                                'setContentChanging',
                                enabled);
    }
  }

  /**
   * Sets the title of the page.
   * @param {Object} origin The origin of the source iframe.
   * @param {string} title The title of the page.
   */
  function setTitle_(origin, title) {
    // |iframe.src| always contains a trailing backslash while |origin| does not
    // so add the trailing source for normalization.
    var query = '.iframe-container > iframe[src="' + origin + '/"]';

    // Cache the title for the client iframe, i.e., the iframe setting the
    // title. querySelector returns the actual iframe element, so use parentNode
    // to get back to the container.
    var container = document.querySelector(query).parentNode;
    container.dataset.title = title;

    // Only update the currently displayed title if this is the visible frame.
    if (container == getSelectedIframe())
      document.title = title;
  }

  /**
   * Selects a subpage. This is called from uber-frame.
   * @param {String} pageId Should matche an id of one of the iframe containers.
   * @param {integer} historyOption Indicates whether we should push or replace
   *     browser history.
   * @param {String=} path An optional sub-page path.
   */
  function showPage(pageId, historyOption, path) {
    var container = $(pageId);
    var lastSelected = document.querySelector('.iframe-container.selected');
    if (lastSelected === container)
      return;

    // Lazy load of iframe contents.
    var frame = container.querySelector('iframe');
    var sourceUrl = container.dataset.url;
    if (!frame) {
      frame = container.ownerDocument.createElement('iframe');
      container.appendChild(frame);
      frame.src = sourceUrl;
    }
    // If there is a non-empty path, alter the location of the frame.
    if (path && path.length)
      frame.contentWindow.location.replace(sourceUrl + path);

    if (lastSelected)
      lastSelected.classList.remove('selected');
    container.classList.add('selected');
    if (container.dataset.title)
      document.title = container.dataset.title;
    $('favicon').href = container.dataset.favicon;

    setContentChanging(true);
    adjustToScroll(0);

    var selectedFrame = getSelectedIframe().querySelector('iframe');
    uber.invokeMethodOnWindow(selectedFrame.contentWindow, 'frameSelected');

    if (historyOption == HISTORY_STATE_OPTION.PUSH)
      window.history.pushState({pageId: pageId}, '', '/' + pageId);
    else if (historyOption == HISTORY_STATE_OPTION.REPLACE)
      window.history.replaceState({pageId: pageId}, '', '/' + pageId);

    updateNavigationControls();
  }

  function onNavigationControlsLoaded() {
    updateNavigationControls();
  }

  /**
   * Sends a message to uber-frame to update the appearance of the nav controls.
   * It should be called whenever the selected iframe changes.
   */
  function updateNavigationControls() {
    var iframe = getSelectedIframe();
    uber.invokeMethodOnWindow(navFrame.firstChild.contentWindow,
                              'changeSelection', {pageId: iframe.id});
  }

  /**
   * Forwarded scroll offset from a content frame's scroll handler.
   * @param {number} scrollOffset The scroll offset from the content frame.
   */
  function adjustToScroll(scrollOffset) {
    // NOTE: The scroll is reset to 0 and easing turned on every time a user
    // switches frames. If we receive a non-zero value it has to have come from
    // a real user scroll, so we disable easing when this happens.
    if (scrollOffset != 0)
      setContentChanging(false);

    if (isRTL()) {
      uber.invokeMethodOnWindow(navFrame.firstChild.contentWindow,
                                'adjustToScroll',
                                scrollOffset);
      var navWidth = Math.max(0, +navFrame.dataset.width + scrollOffset);
      navFrame.style.width = navWidth + 'px';
    } else {
      navFrame.style.webkitTransform = 'translateX(' + -scrollOffset + 'px)';
    }
  }

  /**
   * Forward scroll wheel events to subpages.
   * @param {Object} params Relevant parameters of wheel event.
   */
  function forwardMouseWheel(params) {
    var iframe = getSelectedIframe().querySelector('iframe');
    uber.invokeMethodOnWindow(iframe.contentWindow, 'mouseWheel', params);
  }

  return {
    onLoad: onLoad,
    onPopHistoryState: onPopHistoryState
  };
});

window.addEventListener('popstate', uber.onPopHistoryState);
document.addEventListener('DOMContentLoaded', uber.onLoad);
<|endoftext|>


<commit_before><commit_msg>Makes errors show on frontend. No more disappointed AND clueless users. (#16)<commit_after><|endoftext|>


<commit_before>// Dependencies
var Request = require("request");

// Constants
const PROVIDER = "http://labs.bible.org/api/?type=json&passage=";

// Constructor
var BibleEnglish = module.exports = {};

/**
 * getVerse
 * Gets the reference using labs.bible.org provider.
 *
 * @name getVerse
 * @function
 * @param {String} reference Bible verse reference
 * @return
 */
BibleEnglish.getVerse = function (reference) {
    Request.get({
        json: true
      , url: PROVIDER + reference
    }, function (err, response, body) {

        if (err || response.statusCode !== 200) {
            return callback (err || response.message);
        }

        // TODO check response
        callback (null, body);
    });
};
<commit_msg>Added callback<commit_after>// Dependencies
var Request = require("request");

// Constants
const PROVIDER = "http://labs.bible.org/api/?type=json&passage=";

// Constructor
var BibleEnglish = module.exports = {};

/**
 * getVerse
 * Gets the reference using labs.bible.org provider.
 *
 * @name getVerse
 * @function
 * @param {String} reference Bible verse reference
 * @return
 */
BibleEnglish.getVerse = function (reference, callback) {
    Request.get({
        json: true
      , url: PROVIDER + reference
    }, function (err, response, body) {

        if (err || response.statusCode !== 200) {
            return callback (err || response.message);
        }

        // TODO check response
        callback (null, body);
    });
};
<|endoftext|>


<commit_before> express = require('express');
let bodyParser = require('body-parser');
let request = require('request');
let app = express();
let count = 0;

app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.listen((process.env.PORT || 3000));

// Server frontpage
app.get('/', function (req, res) {
    res.send('This is Tim\'s TestBot Server');
});

// Facebook Webhook
app.get('/webhook', function (req, res) {
    if (req.query['hub.verify_token'] === 'testbot_verify_token') {
        res.send(req.query['hub.challenge']);
    } else {
        res.send('Invalid verify token');
    }
});

// Trademark frontpage
app.get('/trademark', function (req, res) {
    res.send('Test trademark');
    res.sendfile('./trademark/index.html');
});

// handler receiving messages
app.post('/webhook', function (req, res) {
    let events = req.body.entry[0].messaging;
    for (i = 0; i < events.length; i++) {
        let event = events[i];
        if (event.message && event.message.text) {
            sendMessage(event.sender.id, {text: "Testbot Echo"+count/2+":\r\n " + event.message.text});
            count=count+1;
        }
    }
    res.sendStatus(200);
});

// generic function sending messages
function sendMessage(recipientId, message) {
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: recipientId},
            message: message,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
};<commit_msg>Enable static resurces<commit_after> express = require('express');
let bodyParser = require('body-parser');
let request = require('request');
let app = express();
let count = 0;
app.use(express.static('trademark'));

app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.listen((process.env.PORT || 3000));

// Server frontpage
app.get('/', function (req, res) {
    res.send('This is Tim\'s TestBot Server');
});

// Facebook Webhook
app.get('/webhook', function (req, res) {
    if (req.query['hub.verify_token'] === 'testbot_verify_token') {
        res.send(req.query['hub.challenge']);
    } else {
        res.send('Invalid verify token');
    }
});

// Trademark frontpage
app.get('/trademark', function (req, res) {
    res.sendfile('trademark/index.html');
});

// handler receiving messages
app.post('/webhook', function (req, res) {
    let events = req.body.entry[0].messaging;
    for (i = 0; i < events.length; i++) {
        let event = events[i];
        if (event.message && event.message.text) {
            sendMessage(event.sender.id, {text: "Testbot Echo"+count/2+":\r\n " + event.message.text});
            count=count+1;
        }
    }
    res.sendStatus(200);
});

// generic function sending messages
function sendMessage(recipientId, message) {
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: recipientId},
            message: message,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
};<|endoftext|>


<commit_before>// make sure that jQuery is loaded before this file is loaded

function showDialog(dialogContent, buttonNames) {
  dlog(dialogContent);
  dlog(buttons);
  $dialog = $('

');
  $dialog.html(dialogContent);
  $buttonRow = $('

');
  var commandNr = 0;
  for (var i=0; i<buttons.length; i++) {
    $buttonRow.append($('<input type=button value="'+buttonNames[i].name+'" onClick="dialogButtonClicked('+ i + ',' + buttons[i].command +')"></input>'));
  }
  $dialog.append($buttonRow);
  $dialogContainer = $('

');
  $dialogContainer.append($dialog);
  $dialogBackground = $('
');
  $('body').append( $dialogBackground);
  $('body').append( $dialogContainer );
  $dialogBackground.fadeIn(100);
  $dialogContainer.fadeIn(100);
  $(document).on("keydown.dialog",function(e) {
    if (e.keyCode == 27)
     dialogButtonClicked( -1, false );
     // only handle escape key, no default for return key yet.
  });
}

function dialogButtonClicked(nr,command) {
  $(document).off("keydown.dialog");
  var $dialogContainer = $('.dialogContainer');
  var $dialogBackground = $('.dialogBackground');
  $dialogBackground.fadeOut(100, function() { // delay should be small, because background prevents editing
    $dialogBackground.remove();
  });
  $dialogContainer.fadeOut(100, function() {
    $dialogContainer.remove();
  });

  if (command) {
    queueCommand("DialogButtonPressed "+nr);
  }
}

var spinners = new Array();

function addSpinner(id) {
  var opts = {
    lines: 12, // The number of lines to draw
    length: 7, // The length of each line
    width: 3, // The line thickness
    radius: 7, // The radius of the inner circle
    color: '#000', // #rgb or #rrggbb
    speed: 0.5, // Rounds per second
    trail: 60, // Afterglow percentage
    shadow: false // Whether to render a shadow
  };

  var targetElt = document.getElementById(id);
  var spinner = new Spinner(opts).spin(targetElt);

  $targetElt = $('#'+id);
  dlog(id, targetElt, $targetElt.height());
  var divWidth = $targetElt.width();
  var divHeight = $targetElt.height();
  var overlay = $('

');
  $targetElt.prepend(overlay);
  spinners.push({spinner: spinner, overlay: overlay});
}

function clearSpinners() {
	while (spinner = spinners.pop()) {
		dlog('Clearing spinner '+spinner);
		spinner.spinner.stop();
		spinner.overlay.remove();
	}

}

// Selects and deselect selectable views immediately, so we don't have to wait for the server response.
function selectSelectableView(viewId, viewIds) {
  for (var i = 0; i<viewIds.length; i++)
    if (viewIds[i]!=viewId)
      $('#'+viewIds[i]).removeClass('Selected').addClass('Deselected');

  $('#'+viewId).removeClass('Deselected').addClass('Selected');
}

(function($) { // from http://stackoverflow.com/questions/536814/insert-ellipsis-into-html-tag-if-content-too-wide
	$.fn.ellipsis = function() {
		return this.each(function() {
			var el = $(this);

			// after execution, the width and height are stored in ellipsisWidth/Height, so if these are equal
			// to the current width/height, we don't need to execute again.
			var isDirty = el.attr('ellipsisWidth') != el.width() || el.attr('ellipsisHeight') != el.height();

			if(el.css("overflow") == "hidden"  && isDirty) {
				dlog('Evaluating ellipsis on '+el.attr('id')+ ' for width: '+el.width()+' and height: '+el.height()
						 + ' ('+el.attr('ellipsisWidth')+','+el.attr('ellipsisHeight')+')');

				var text = el.html();
				var multiline = el.hasClass('multiline');
				var t = $(this.cloneNode(true))
								.hide()
								.css('position', 'absolute')
								.css('overflow', 'visible')
								.width(multiline ? el.width() : 'auto')
								.height(multiline ? 'auto' : el.height());

				el.after(t);

				function height() { return t.height() > el.height(); };
				function width() { return t.width() > el.width(); };

				var func = multiline ? height : width;

				var i = text.length / 2;
				var p = 0;

				while (i>0.5) {
					t.html(text.substr(0, p) + "...");
					if (func())
						p-=i;
					else
						p+=i;
					i = Math.floor(i / 2);
				}

				el.html( text.substr(0,p-1) + "..." ); // subtract one more, since binary search can end up one char too long (quick & dirty solution)
				el.attr('ellipsisWidth', el.width());
				el.attr('ellipsisHeight', el.height());
				t.remove();
			}
		});
	};
})(jQuery);
<commit_msg>Return key activates first button in dialog + Fixed accidental access to global variable.<commit_after>// make sure that jQuery is loaded before this file is loaded

function showDialog(dialogContent, buttons) {
  dlog(dialogContent);
  dlog(buttons);
  $dialog = $('

');
  $dialog.html(dialogContent);
  $buttonRow = $('

');
  var commandNr = 0;
  for (var i=0; i<buttons.length; i++) {
    $buttonRow.append($('<input type=button value="'+buttons[i].name+'" onClick="dialogButtonClicked('+ i + ',' + buttons[i].command +')"></input>'));
  }
  $dialog.append($buttonRow);
  $dialogContainer = $('

');
  $dialogContainer.append($dialog);
  $dialogBackground = $('
');
  $('body').append( $dialogBackground);
  $('body').append( $dialogContainer );
  $dialogBackground.fadeIn(100);
  $dialogContainer.fadeIn(100);
  $(document).on("keydown.dialog",function(e) {
    if (e.keyCode == 13)
      dialogButtonClicked(0, buttons[0].command == "true" ? true : false);
    else if (e.keyCode == 27)
      dialogButtonClicked(-1, false);
     // only handle escape key, no default for return key yet.
  });
}

function dialogButtonClicked(nr,command) { // command == false denotes a cancel button (for which nr is ignored)
  $(document).off("keydown.dialog");
  var $dialogContainer = $('.dialogContainer');
  var $dialogBackground = $('.dialogBackground');
  $dialogBackground.fadeOut(100, function() { // delay should be small, because background prevents editing
    $dialogBackground.remove();
  });
  $dialogContainer.fadeOut(100, function() {
    $dialogContainer.remove();
  });

  if (command) {
    queueCommand("DialogButtonPressed "+nr);
  }
}

var spinners = new Array();

function addSpinner(id) {
  var opts = {
    lines: 12, // The number of lines to draw
    length: 7, // The length of each line
    width: 3, // The line thickness
    radius: 7, // The radius of the inner circle
    color: '#000', // #rgb or #rrggbb
    speed: 0.5, // Rounds per second
    trail: 60, // Afterglow percentage
    shadow: false // Whether to render a shadow
  };

  var targetElt = document.getElementById(id);
  var spinner = new Spinner(opts).spin(targetElt);

  $targetElt = $('#'+id);
  dlog(id, targetElt, $targetElt.height());
  var divWidth = $targetElt.width();
  var divHeight = $targetElt.height();
  var overlay = $('

');
  $targetElt.prepend(overlay);
  spinners.push({spinner: spinner, overlay: overlay});
}

function clearSpinners() {
	while (spinner = spinners.pop()) {
		dlog('Clearing spinner '+spinner);
		spinner.spinner.stop();
		spinner.overlay.remove();
	}

}

// Selects and deselect selectable views immediately, so we don't have to wait for the server response.
function selectSelectableView(viewId, viewIds) {
  for (var i = 0; i<viewIds.length; i++)
    if (viewIds[i]!=viewId)
      $('#'+viewIds[i]).removeClass('Selected').addClass('Deselected');

  $('#'+viewId).removeClass('Deselected').addClass('Selected');
}

(function($) { // from http://stackoverflow.com/questions/536814/insert-ellipsis-into-html-tag-if-content-too-wide
	$.fn.ellipsis = function() {
		return this.each(function() {
			var el = $(this);

			// after execution, the width and height are stored in ellipsisWidth/Height, so if these are equal
			// to the current width/height, we don't need to execute again.
			var isDirty = el.attr('ellipsisWidth') != el.width() || el.attr('ellipsisHeight') != el.height();

			if(el.css("overflow") == "hidden"  && isDirty) {
				dlog('Evaluating ellipsis on '+el.attr('id')+ ' for width: '+el.width()+' and height: '+el.height()
						 + ' ('+el.attr('ellipsisWidth')+','+el.attr('ellipsisHeight')+')');

				var text = el.html();
				var multiline = el.hasClass('multiline');
				var t = $(this.cloneNode(true))
								.hide()
								.css('position', 'absolute')
								.css('overflow', 'visible')
								.width(multiline ? el.width() : 'auto')
								.height(multiline ? 'auto' : el.height());

				el.after(t);

				function height() { return t.height() > el.height(); };
				function width() { return t.width() > el.width(); };

				var func = multiline ? height : width;

				var i = text.length / 2;
				var p = 0;

				while (i>0.5) {
					t.html(text.substr(0, p) + "...");
					if (func())
						p-=i;
					else
						p+=i;
					i = Math.floor(i / 2);
				}

				el.html( text.substr(0,p-1) + "..." ); // subtract one more, since binary search can end up one char too long (quick & dirty solution)
				el.attr('ellipsisWidth', el.width());
				el.attr('ellipsisHeight', el.height());
				t.remove();
			}
		});
	};
})(jQuery);
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const resolve = require('resolve');
const version = require('./package.json').version;
const autoprefixer = require('broccoli-autoprefixer');
const mergeTrees = require('broccoli-merge-trees');
const writeFile = require('broccoli-file-creator');
const Funnel = require('broccoli-funnel');
const AngularScssFilter = require('./lib/angular-scss-filter');
const fastbootTransform = require('fastboot-transform');

module.exports = {
  name: 'ember-paper',

  included() {
    this._super.included.apply(this, arguments);
    let app;

    // If the addon has the _findHost() method (in ember-cli >= 2.7.0), we'll just
    // use that.
    if (typeof this._findHost === 'function') {
      app = this._findHost();
    } else {
      // Otherwise, we'll use this implementation borrowed from the _findHost()
      // method in ember-cli.
      let current = this;
      do {
        app = current.app || app;
      } while (current.parent.parent && (current = current.parent));
    }

    app.import('vendor/ember-paper/register-version.js');
    app.import('vendor/hammerjs/hammer.js');
    app.import('vendor/matchmedia-polyfill/matchMedia.js');
    app.import('vendor/propagating-hammerjs/propagating.js');
  },

  config() {
    return { 'ember-paper': { insertFontLinks: true } };
  },

  contentFor(type, config) {
    if (type === 'head') {
      if (config['ember-paper'].insertFontLinks) {
        return '<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">'
          + '<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">';
      }
    } else if (type === 'body-footer') {
      let response = null;
      let emberPowerSelect = this.addons.filter(function(addon) {
        return addon.name === 'ember-power-select';
      })[0];
      response = emberPowerSelect.contentFor(type, config);
      if (config.environment !== 'test' &&  !config._emberPaperContentForInvoked) {
        config._emberPaperContentForInvoked = true;
        response = `
          ${response || ''}

        `;
      }
      return response;
    }
  },

  treeForVendor(tree) {
    let trees = [];

    let versionTree = writeFile(
      'ember-paper/register-version.js',
      `Ember.libraries.register('Ember Paper', '${version}');`
    );

    let hammerJs = fastbootTransform(new Funnel(this.pathBase('hammerjs'), {
      files: ['hammer.js'],
      destDir: 'hammerjs'
    }));

    let matchMediaPolyfill = fastbootTransform(new Funnel(this.pathBase('matchmedia-polyfill'), {
      files: ['matchMedia.js'],
      destDir: 'matchmedia-polyfill'
    }));

    let propagatingHammerJs = fastbootTransform(new Funnel(this.pathBase('propagating-hammerjs'), {
      files: ['propagating.js'],
      destDir: 'propagating-hammerjs'
    }));

    trees = trees.concat([hammerJs, matchMediaPolyfill, propagatingHammerJs, versionTree]);

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

    return mergeTrees(trees);
  },

  treeForStyles(tree) {
    let scssFiles = [
      // core styles
      'core/style/typography.scss',
      'core/style/mixins.scss',
      'core/style/letiables.scss',
      'core/style/structure.scss',
      'core/style/layout.scss',
      'core/services/layout/layout.scss',

      // component styles
      'components/content/content.scss',
      'components/content/content-theme.scss',

      'components/card/card.scss',
      'components/card/card-theme.scss',

      'components/button/button.scss',
      'components/button/button-theme.scss',

      'components/checkbox/checkbox.scss',
      'components/checkbox/checkbox-theme.scss',

      'components/radioButton/radio-button.scss',
      'components/radioButton/radio-button-theme.scss',

      'components/switch/switch.scss',
      'components/switch/switch-theme.scss',

      'components/input/input.scss',
      'components/input/input-theme.scss',

      'components/list/list.scss',
      'components/list/list-theme.scss',

      'components/divider/divider.scss',
      'components/divider/divider-theme.scss',

      'components/whiteframe/whiteframe.scss',

      'components/toolbar/toolbar.scss',
      'components/toolbar/toolbar-theme.scss',

      'components/icon/icon.scss',
      'components/icon/icon-theme.scss',

      'components/slider/slider.scss',
      'components/slider/slider-theme.scss',

      'components/subheader/subheader.scss',
      'components/subheader/subheader-theme.scss',

      'components/autocomplete/autocomplete.scss',
      'components/autocomplete/autocomplete-theme.scss',

      'components/progressLinear/progress-linear.scss',
      'components/progressLinear/progress-linear-theme.scss',

      'components/progressCircular/progress-circular.scss',
      'components/progressCircular/progress-circular-theme.scss',

      'components/menu/menu.scss',
      'components/menu/menu-theme.scss',

      'components/select/select.scss',
      'components/select/select-theme.scss',

      'components/gridList/grid-list.scss',

      'components/sidenav/sidenav.scss',
      'components/sidenav/sidenav-theme.scss',

      'components/backdrop/backdrop.scss',
      'components/backdrop/backdrop-theme.scss',

      'components/dialog/dialog.scss',
      'components/dialog/dialog-theme.scss',

      'components/virtualRepeat/virtual-repeater.scss',

      'components/chips/chips.scss',
      'components/chips/chips-theme.scss',

      'components/panel/panel.scss',
      'components/panel/panel-theme.scss',

      'components/tooltip/tooltip.scss',
      'components/tooltip/tooltip-theme.scss',

      'components/toast/toast.scss',
      'components/toast/toast-theme.scss',

      'components/tabs/tabs.scss',
      'components/tabs/tabs-theme.scss',

      'components/fabSpeedDial/fabSpeedDial.scss'
    ];

    let angularScssFiles = new Funnel(this.pathBase('angular-material-source'), {
      files: scssFiles,
      srcDir: '/src',
      destDir: 'angular-material',
      annotation: 'AngularScssFunnel'
    });

    angularScssFiles = new AngularScssFilter(angularScssFiles, {
      annotation: 'AngularScssFilter'
    });

    return this._super.treeForStyles(mergeTrees([angularScssFiles, tree], { overwrite: true }));
  },

  /*
    Rely on the `resolve` package to mimic node's resolve algorithm.
    It finds the angular-material-source module in a manner that works for npm 2.x,
    3.x, and yarn in both the addon itself and projects that depend on this addon.

    This is an edge case b/c angular-material-source does not have a main
    module we can require.resolve through node itself and similarily ember-cli
    does not have such a hack for the same reason.

    tl;dr - We want the non built scss files, and b/c this dep is only provided via
    bower, we use this hack. Please change it if you read this and know a better way.
  */
  pathBase(packageName) {
    return path.dirname(resolve.sync(`${packageName}/package.json`, { basedir: __dirname }));
  },

  postprocessTree(type, tree) {
    if (type === 'all' || type === 'styles') {
      tree = autoprefixer(tree, this.app.options.autoprefixer || { browsers: ['last 2 versions'] });
    }
    return tree;
  }
};
<commit_msg>fix import<commit_after>'use strict';

const path = require('path');
const resolve = require('resolve');
const version = require('./package.json').version;
const autoprefixer = require('broccoli-autoprefixer');
const mergeTrees = require('broccoli-merge-trees');
const writeFile = require('broccoli-file-creator');
const Funnel = require('broccoli-funnel');
const AngularScssFilter = require('./lib/angular-scss-filter');
const fastbootTransform = require('fastboot-transform');

module.exports = {
  name: 'ember-paper',

  included() {
    this._super.included.apply(this, arguments);
    let app;

    // If the addon has the _findHost() method (in ember-cli >= 2.7.0), we'll just
    // use that.
    if (typeof this._findHost === 'function') {
      app = this._findHost();
    } else {
      // Otherwise, we'll use this implementation borrowed from the _findHost()
      // method in ember-cli.
      let current = this;
      do {
        app = current.app || app;
      } while (current.parent.parent && (current = current.parent));
    }

    app.import('vendor/ember-paper/register-version.js');
    app.import('vendor/hammerjs/hammer.js');
    app.import('vendor/matchmedia-polyfill/matchMedia.js');
    app.import('vendor/propagating-hammerjs/propagating.js');
  },

  config() {
    return { 'ember-paper': { insertFontLinks: true } };
  },

  contentFor(type, config) {
    if (type === 'head') {
      if (config['ember-paper'].insertFontLinks) {
        return '<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">'
          + '<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">';
      }
    } else if (type === 'body-footer') {
      let response = null;
      let emberPowerSelect = this.addons.filter(function(addon) {
        return addon.name === 'ember-power-select';
      })[0];
      response = emberPowerSelect.contentFor(type, config);
      if (config.environment !== 'test' &&  !config._emberPaperContentForInvoked) {
        config._emberPaperContentForInvoked = true;
        response = `
          ${response || ''}

        `;
      }
      return response;
    }
  },

  treeForVendor(tree) {
    let trees = [];

    let versionTree = writeFile(
      'ember-paper/register-version.js',
      `Ember.libraries.register('Ember Paper', '${version}');`
    );

    let hammerJs = fastbootTransform(new Funnel(this.pathBase('hammerjs'), {
      files: ['hammer.js'],
      destDir: 'hammerjs'
    }));

    let matchMediaPolyfill = fastbootTransform(new Funnel(this.pathBase('matchmedia-polyfill'), {
      files: ['matchMedia.js'],
      destDir: 'matchmedia-polyfill'
    }));

    let propagatingHammerJs = fastbootTransform(new Funnel(this.pathBase('propagating-hammerjs'), {
      files: ['propagating.js'],
      destDir: 'propagating-hammerjs'
    }));

    trees = trees.concat([hammerJs, matchMediaPolyfill, propagatingHammerJs, versionTree]);

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

    return mergeTrees(trees);
  },

  treeForStyles(tree) {
    let scssFiles = [
      // core styles
      'core/style/typography.scss',
      'core/style/mixins.scss',
      'core/style/variables.scss',
      'core/style/structure.scss',
      'core/style/layout.scss',
      'core/services/layout/layout.scss',

      // component styles
      'components/content/content.scss',
      'components/content/content-theme.scss',

      'components/card/card.scss',
      'components/card/card-theme.scss',

      'components/button/button.scss',
      'components/button/button-theme.scss',

      'components/checkbox/checkbox.scss',
      'components/checkbox/checkbox-theme.scss',

      'components/radioButton/radio-button.scss',
      'components/radioButton/radio-button-theme.scss',

      'components/switch/switch.scss',
      'components/switch/switch-theme.scss',

      'components/input/input.scss',
      'components/input/input-theme.scss',

      'components/list/list.scss',
      'components/list/list-theme.scss',

      'components/divider/divider.scss',
      'components/divider/divider-theme.scss',

      'components/whiteframe/whiteframe.scss',

      'components/toolbar/toolbar.scss',
      'components/toolbar/toolbar-theme.scss',

      'components/icon/icon.scss',
      'components/icon/icon-theme.scss',

      'components/slider/slider.scss',
      'components/slider/slider-theme.scss',

      'components/subheader/subheader.scss',
      'components/subheader/subheader-theme.scss',

      'components/autocomplete/autocomplete.scss',
      'components/autocomplete/autocomplete-theme.scss',

      'components/progressLinear/progress-linear.scss',
      'components/progressLinear/progress-linear-theme.scss',

      'components/progressCircular/progress-circular.scss',
      'components/progressCircular/progress-circular-theme.scss',

      'components/menu/menu.scss',
      'components/menu/menu-theme.scss',

      'components/select/select.scss',
      'components/select/select-theme.scss',

      'components/gridList/grid-list.scss',

      'components/sidenav/sidenav.scss',
      'components/sidenav/sidenav-theme.scss',

      'components/backdrop/backdrop.scss',
      'components/backdrop/backdrop-theme.scss',

      'components/dialog/dialog.scss',
      'components/dialog/dialog-theme.scss',

      'components/virtualRepeat/virtual-repeater.scss',

      'components/chips/chips.scss',
      'components/chips/chips-theme.scss',

      'components/panel/panel.scss',
      'components/panel/panel-theme.scss',

      'components/tooltip/tooltip.scss',
      'components/tooltip/tooltip-theme.scss',

      'components/toast/toast.scss',
      'components/toast/toast-theme.scss',

      'components/tabs/tabs.scss',
      'components/tabs/tabs-theme.scss',

      'components/fabSpeedDial/fabSpeedDial.scss'
    ];

    let angularScssFiles = new Funnel(this.pathBase('angular-material-source'), {
      files: scssFiles,
      srcDir: '/src',
      destDir: 'angular-material',
      annotation: 'AngularScssFunnel'
    });

    angularScssFiles = new AngularScssFilter(angularScssFiles, {
      annotation: 'AngularScssFilter'
    });

    return this._super.treeForStyles(mergeTrees([angularScssFiles, tree], { overwrite: true }));
  },

  /*
    Rely on the `resolve` package to mimic node's resolve algorithm.
    It finds the angular-material-source module in a manner that works for npm 2.x,
    3.x, and yarn in both the addon itself and projects that depend on this addon.

    This is an edge case b/c angular-material-source does not have a main
    module we can require.resolve through node itself and similarily ember-cli
    does not have such a hack for the same reason.

    tl;dr - We want the non built scss files, and b/c this dep is only provided via
    bower, we use this hack. Please change it if you read this and know a better way.
  */
  pathBase(packageName) {
    return path.dirname(resolve.sync(`${packageName}/package.json`, { basedir: __dirname }));
  },

  postprocessTree(type, tree) {
    if (type === 'all' || type === 'styles') {
      tree = autoprefixer(tree, this.app.options.autoprefixer || { browsers: ['last 2 versions'] });
    }
    return tree;
  }
};
<|endoftext|>


<commit_before>/*global it: false,
         describe: false,
         pub_keys: false,
         priv_keys: false,
         pub_pem: false,
         priv_pem: false */
/*jslint node: true, nomen: true */
"use strict";

var generate_verify = require('./generate_verify_spec'),
    child_process = require('child_process'),
    path = require('path'),
    util = require('util');

describe('python-jws-interop', function ()
{
    /*jslint unparam: true */

    this.timeout(60*1000);

    var spawn = function (cmd, json, cb)
    {
        var cp, env = process.env, stdout = '', stderr = '';

        env.PYTHONPATH = __dirname + path.delimiter +
                         path.join(__dirname, '..', 'python-jws');

        cp = child_process.spawn(
                'python',
                ['-c', 'from fixtures import *; ' + cmd],
                { env: env });

        cp.stdout.on('data', function (data)
        {
            stdout += data;
        });

        cp.stderr.on('data', function (data)
        {
            stderr += data;
        });

        cp.on('close', function (code, signal)
        {
            if (code === 0)
            {
                cb(null, json ? JSON.parse(stdout) : stdout);
            }
            else
            {
                cb(new Error(stderr || ('exited with ' + (code || signal))));
            }
        });

        cp.on('err', cb);
    },

    generate = function (header, payload, cb)
    {
        spawn(util.format("generate('%j', '%j', '%j')",
                          header, payload, priv_pem),
              false,
              cb);
    },

    verify = function (sjws, cb)
    {
        spawn(util.format("verify('%j', '%j')", sjws, pub_pem),
              true,
              cb);
    };

    /*jslint unparam: false */

    pub_keys.python_jws = verify;
    priv_keys.python_jws = generate;
    generate_verify.setup(['RS256', 'RS512', 'PS256', 'PS512']);
    delete pub_keys.python_jws;
    delete priv_keys.python_jws;
});
<commit_msg>Pass only PYTHONPATH down in test rather than modifying global env<commit_after>/*global it: false,
         describe: false,
         pub_keys: false,
         priv_keys: false,
         pub_pem: false,
         priv_pem: false */
/*jslint node: true, nomen: true */
"use strict";

var generate_verify = require('./generate_verify_spec'),
    child_process = require('child_process'),
    path = require('path'),
    util = require('util');

describe('python-jws-interop', function ()
{
    /*jslint unparam: true */

    this.timeout(60*1000);

    var spawn = function (cmd, json, cb)
    {
        var stdout = '', stderr = '',

        cp = child_process.spawn(
                'python',
                ['-c', 'from fixtures import *; ' + cmd],
                { env: {
                    PYTHONPATH: __dirname + path.delimiter +
                                path.join(__dirname, '..', 'python-jws')
                }});

        cp.stdout.on('data', function (data)
        {
            stdout += data;
        });

        cp.stderr.on('data', function (data)
        {
            stderr += data;
        });

        cp.on('close', function (code, signal)
        {
            if (code === 0)
            {
                cb(null, json ? JSON.parse(stdout) : stdout);
            }
            else
            {
                cb(new Error(stderr || ('exited with ' + (code || signal))));
            }
        });

        cp.on('err', cb);
    },

    generate = function (header, payload, cb)
    {
        spawn(util.format("generate('%j', '%j', '%j')",
                          header, payload, priv_pem),
              false,
              cb);
    },

    verify = function (sjws, cb)
    {
        spawn(util.format("verify('%j', '%j')", sjws, pub_pem),
              true,
              cb);
    };

    /*jslint unparam: false */

    pub_keys.python_jws = verify;
    priv_keys.python_jws = generate;
    generate_verify.setup(['RS256', 'RS512', 'PS256', 'PS512']);
    delete pub_keys.python_jws;
    delete priv_keys.python_jws;
});
<|endoftext|>