<commit_before>// Require libs
var UI = require('ui');
var Vector2 = require('vector2');
var ajax = require('ajax');
var Vibe = require('ui/vibe');

// Variables
var config_url = "";
var main_window = new UI.Window();
var info_text = new UI.Text({
	position: new Vector2(0, 50),
	size: new Vector2(144, 30),
	font: 'gothic-24-bold',
	text: 'Uber Now',
	textAlign: 'center'
});

var anykey_text = new UI.Text({
  position: new Vector2(0, 114),
  size: new Vector2(144, 30),
  font: 'gothic-14-bold',
  text: 'Press any key to update',
  textAlign: 'center'
});

var locationOptions = {"timeout": 15000, "maximumAge": 30000,
                       "enableHighAccuracy": true};

function locationSuccess(pos) {
  console.log(JSON.stringify(pos.coords));
  fetchUber(pos.coords);
}

function locationError(err) {
  console.warn('location error (' + err.code + '): ' + err.message);
  info_text.text('Can\'t get location.');
  info_text.font('gothic-18-bold');
}

function showUber(times) {

  if (times.length === 0) {
    info_text.text('No cars available');
    info_text.font('gothic-24-bold');
    return;
  }

	var items = [];
	times.forEach(function(product) {
    product.surge_multiplier = product.surge_multiplier || 1;
    var title = product.display_name;
    if (product.surge_multiplier !== 1) {
      title += ' x ' + Number(product.surge_multiplier).toFixed(2);
    }
		var item = {
			title: title,
			subtitle: 'pick up time: ' +
                Math.ceil(product.estimate / 60) + ' mins',
      product_id: product.product_id
		};
		items.push(item);
	});

	var menu = new UI.Menu({
	  sections: [{
	    items: items
	  }]
	});

  menu.on('select', function(e) {
    console.log(JSON.stringify(e.item));
    var url = 'uber://?action=setPickup&product_id=' + e.item.product_id +
              '&pickup=my_location';
    config_url = url;
    console.log(config_url);
  });

  menu.on('click', 'back', function() {
    console.log('menu back');
    window.navigator.geolocation.watchPosition(locationSuccess,
                                               locationError, locationOptions);
  });

	menu.show();
}

function fetchUber(coords) {
	var params = 'latitude=' + coords.latitude +
               '&longitude=' + coords.longitude;
	ajax({ url: 'http://pebble-uber.yulun.me/?' + params, type: 'json' },
	  function(data) {
      info_text.text('Uber Now');
      info_text.font('gothic-24-bold');
      Vibe.vibrate('double');
	  	showUber(data.times);
  	},
    function() {
      info_text.text('Connection Error');
      info_text.font('gothic-18-bold');
    }
  );
}

function update() {
  info_text.text('Updating...');
  info_text.font('gothic-24-bold');
  window.navigator.geolocation.watchPosition(locationSuccess,
                                             locationError, locationOptions);
}

Pebble.addEventListener("showConfiguration", function() {
  Pebble.openURL(config_url);
});

main_window.on('click', 'up', update);
main_window.on('click', 'down', update);
main_window.on('click', 'select', update);

// Init
main_window.add(anykey_text);
main_window.add(info_text);
main_window.show();
update();
<commit_msg>update surge pricing style<commit_after>// Require libs
var UI = require('ui');
var Vector2 = require('vector2');
var ajax = require('ajax');
var Vibe = require('ui/vibe');

// Variables
var config_url = "";
var main_window = new UI.Window();
var info_text = new UI.Text({
	position: new Vector2(0, 50),
	size: new Vector2(144, 30),
	font: 'gothic-24-bold',
	text: 'Uber Now',
	textAlign: 'center'
});

var anykey_text = new UI.Text({
  position: new Vector2(0, 114),
  size: new Vector2(144, 30),
  font: 'gothic-14-bold',
  text: 'Press any key to update',
  textAlign: 'center'
});

var locationOptions = {"timeout": 15000, "maximumAge": 30000,
                       "enableHighAccuracy": true};

function locationSuccess(pos) {
  console.log(JSON.stringify(pos.coords));
  fetchUber(pos.coords);
}

function locationError(err) {
  console.warn('location error (' + err.code + '): ' + err.message);
  info_text.text('Can\'t get location.');
  info_text.font('gothic-18-bold');
}

function showUber(times) {

  if (times.length === 0) {
    info_text.text('No cars available');
    info_text.font('gothic-24-bold');
    return;
  }

	var items = [];
	times.forEach(function(product) {
    product.surge_multiplier = product.surge_multiplier || 1;
    var title = product.display_name;
    if (product.surge_multiplier !== 1) {
      title += ' *' + Number(product.surge_multiplier).toFixed(2);
    }
		var item = {
			title: title,
			subtitle: 'pick up time: ' +
                Math.ceil(product.estimate / 60) + ' mins',
      product_id: product.product_id
		};
		items.push(item);
	});

	var menu = new UI.Menu({
	  sections: [{
	    items: items
	  }]
	});

  menu.on('select', function(e) {
    console.log(JSON.stringify(e.item));
    var url = 'uber://?action=setPickup&product_id=' + e.item.product_id +
              '&pickup=my_location';
    config_url = url;
    console.log(config_url);
  });

  menu.on('click', 'back', function() {
    console.log('menu back');
    window.navigator.geolocation.watchPosition(locationSuccess,
                                               locationError, locationOptions);
  });

	menu.show();
}

function fetchUber(coords) {
	var params = 'latitude=' + coords.latitude +
               '&longitude=' + coords.longitude;
	ajax({ url: 'http://pebble-uber.yulun.me/?' + params, type: 'json' },
	  function(data) {
      info_text.text('Uber Now');
      info_text.font('gothic-24-bold');
      Vibe.vibrate('double');
	  	showUber(data.times);
  	},
    function() {
      info_text.text('Connection Error');
      info_text.font('gothic-18-bold');
    }
  );
}

function update() {
  info_text.text('Updating...');
  info_text.font('gothic-24-bold');
  window.navigator.geolocation.watchPosition(locationSuccess,
                                             locationError, locationOptions);
}

Pebble.addEventListener("showConfiguration", function() {
  Pebble.openURL(config_url);
});

main_window.on('click', 'up', update);
main_window.on('click', 'down', update);
main_window.on('click', 'select', update);

// Init
main_window.add(anykey_text);
main_window.add(info_text);
main_window.show();
update();
<|endoftext|>


<commit_before>'use strict';

var modRewrite = require('connect-modrewrite');

module.exports = function (grunt) {

  var base = grunt.option('base-dir') || '',
      env = grunt.option('env') || 'development',
      protractorConf = grunt.option('ci') ?
        './tests/e2e/protractor.saucelabs.conf.js' :
        './tests/e2e/protractor.conf.js' ;

  grunt.initConfig({

    pkg: grunt.file.readJSON('./package.json'),

    bower: grunt.file.readJSON('./bower.json'),

    env: grunt.file.readJSON('./env.json')[env],

    config: {
      outputDir: './dist/',
      applicationFiles: grunt.file.readJSON('./scripts.json').application,
      vendorFiles: grunt.file.readJSON('./scripts.json').vendor
    },

    connect: {
      options: {
        hostname: '0.0.0.0',
        port: 8000,
        base: base
      },
      server: {
        options: {
          livereload: true,
          middleware: function ( connect, options, middlewares ) {
            var rules = (base === 'dist') ?
                [ '^/[^\.]*$ /index.html' ] :
            [ '^/app/[^\.]*$ /app/index.html' ];
            middlewares.unshift( modRewrite( rules ) );
            return middlewares;
          }
        }
      },
      servertest: {
        options: {
          keepalive: false,
          livereload: false,
          base: '<%= config.outputDir %>',
          middleware: function ( connect, options, middlewares ) {
            var rules = [ '^/[^\.]*$ /index.html' ];
            middlewares.unshift( modRewrite( rules ) );
            return middlewares;
          }
        }
      }
    },

    watch: {
      options: {
        nospawn: false,
        livereload: true
      },
      css: {
        files: [
          './app/index.html',

          './app/less/*.less',
          './app/less/**/*.less',
          './app/less/**/**/*.less',

          './app/partials/*.html',
          './app/partials/**/*.html',
          './app/partials/**/**/*.html',

          './modules/*.html',
          './modules/**/*.html',
          './modules/**/**/*.html'
        ],
        tasks: ['htmllint','lesslint','less:development']
      },
      javascript: {
        files: [
          './scripts.json',

          './app/js/*.js',
          './app/js/**/*.js',
          './app/js/**/**/*.js',

          './tests/unit/*.js',
          './tests/unit/**/*.js',
          './tests/unit/**/**/*.js'
        ],
        tasks: ['sails-linker', 'test:development']
      }
    },

    less: {
      options: {
        paths: ['./app/less/'],
        cleancss: false,
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today(\'yyyy-mm-dd\') %> */\n'
      },
      development: {
        files: { './app/css/all.css': './app/less/main.less' },
        options: {
          sourceMap: true,
          sourceMapFilename: 'app/css/all.css.map',
          sourceMapURL: 'all.css.map',
          outputSourceFiles: true
        }
      },
      production: {
        files: { '<%= config.outputDir %>css/all.min.css': 'app/less/main.less' },
        options: {
          cleancss: true
        }
      }
    },

    jshint: {
      options: {
        jshintrc: '.jshintrc'
      },
      dist: {
        src: ['<%= config.applicationFiles %>']
      }
    },

    jasmine: {
      options: {
        specs: ['./tests/unit/**/*.js'],
        keepRunner: true,
      },
      development: {
        src: [
          '<%= ngconstant.options.dest %>',
          '<%= config.applicationFiles %>'
        ],
        options: {
          vendor: ['<%= config.vendorFiles %>'],
          helpers:['./app/components/angular-mocks/angular-mocks.js'],
          template: require('grunt-template-jasmine-istanbul'),
          templateOptions: {
            coverage: './coverage/coverage.json',
            report: [
              {
                type: 'lcov',
                options: {
                  dir: './coverage'
                }
              },
              {
                type: 'text-summary'
              }
            ]
          }
        }
      },
      production: {
        src: ['<%= config.outputDir %>js/app.min.js', './app/components/angular-mocks/angular-mocks.js']
      }
    },

    protractor: {
      options: {
        keepAlive: false,
        noColor: false
      },
      dist: {
        options: {
          configFile: protractorConf
        }
      }
    },

    concat: {
      options: {
        sourceMap: true,
        separator: ';',
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today(\'yyyy-mm-dd\') %> */\n'
      },
      production: {
        src: [
          '<%= config.vendorFiles %>',
          '<%= ngconstant.options.dest %>',
          '<%= config.applicationFiles %>'
        ],
        dest: '<%= config.outputDir %>js/app.js'
      }
    },

    uglify: {
      options: {
        sourceMap: true,
        sourceMapIncludeSources: true,
        enclose: { window: 'window' },
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today(\'yyyy-mm-dd\') %> */\n'
      },
      production: {
        files: {
          '<%= config.outputDir %>js/app.min.js': [ '<%= config.outputDir %>js/app.js' ]
        }
      }
    },

    copy: {
      images: {
        files: [{
          expand: true,
          cwd: './app/img',
          src: ['**/*', '!test/**'],
          dest: '<%= config.outputDir %>img/'
        }]
      },
      partials: {
        files: [{
          expand: true,
          cwd: './app/partials',
          src: ['**/*.html', '*.html'],
          dest: '<%= config.outputDir %>partials/'
        }]
      },
      fonts: {
        files: [{
          expand: true,
          cwd: './app/fonts',
          src: ['**/*', '*'],
          dest: '<%= config.outputDir %>fonts/'
        }]
      },
      data: {
        files: [{
          expand: true,
          cwd: './app/data',
          src: ['**/*', '*'],
          dest: '<%= config.outputDir %>data/'
        }]
      }
    },

    clean: {
      beforeBuild: {
        src: ['<%= config.outputDir %>', './docs']
      },
      afterTest: {
        src: ['<%= config.outputDir %>']
      }
    },

    processhtml: {
      options: {
        strip: true,
        data: { url: '<%= env.BASE_URL %>' }
      },
      production: {
        files: { '<%= config.outputDir %>index.html': ['./app/index.html'] }
      },
      e2e: {
        files: { '<%= config.outputDir %>index.html': ['./app/index.html'] },
        options: {
          data: { url: 'http://127.0.0.1:8000/' }
        }
      }
    },

    yuidoc: {
      compile: {
        name: '<%= pkg.name %>',
        description: '<%= pkg.description %>',
        version: '<%= pkg.version %>',
        url: '<%= pkg.homepage %>',
        options: {
          paths: './app/js/',
          themedir: 'node_modules/yuidoc-bootstrap-theme',
          helpers: ['node_modules/yuidoc-bootstrap-theme/helpers/helpers.js'],
          outdir: './docs/'
        }
      }
    },

    bump: {
      options: {
        files: ['./package.json', './bower.json'],
        updateConfigs: ['pkg'],
        commit: true,
        commitFiles: ['-a'],
        createTag: true,
        push: true,
        pushTo: 'origin master'
      }
    },

    ngconstant: {
      options: {
        name: 'config',
        dest: './app/js/config/config.js',
        constants: {
          bower: '<%= bower %>',
          pkg: '<%= pkg %>',
          env: '<%= env %>'
        }
      },
      dist: {}
    },

    'sails-linker': {
      vendorJs: {
        options: {
          startTag: '<!--VENDOR SCRIPTS-->',
          endTag: '<!--VENDOR SCRIPTS END-->',
          fileTmpl: '<script src=\'%s\'></script>',
          appRoot: './app/'
        },
        files: {
          'app/index.html': '<%= config.vendorFiles %>'
        }
      },
      appJs: {
        options: {
          startTag: '<!--SCRIPTS-->',
          endTag: '<!--SCRIPTS END-->',
          fileTmpl: '<script src=\'%s\'></script>',
          appRoot: './app/'
        },
        files: {
          'app/index.html': '<%= config.applicationFiles %>'
        }
      }
    },

    lesslint: {
      src: ['app/less/main.less'],
      options: {
        imports: ['app/less/**/*.less'],
        csslint: {
          csslintrc: 'app/less/.csslintrc',
        }
      }
    },

    /**
     * HTML linter
     * {@link https://github.com/htmllint/htmllint/wiki/Options .htmllintrc options}
     */
    htmllint: {
      options: {
        force: true,
        htmllintrc: 'app/partials/.htmllintrc'
      },
      src: ['app/*.html','app/partials/**/*.html']
    }

  });

  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-yuidoc');
  grunt.loadNpmTasks('grunt-contrib-jasmine');
  grunt.loadNpmTasks('grunt-protractor-runner');
  grunt.loadNpmTasks('grunt-processhtml');
  grunt.loadNpmTasks('grunt-ng-constant');
  grunt.loadNpmTasks('grunt-bump');
  grunt.loadNpmTasks('grunt-sails-linker');
  grunt.loadNpmTasks('grunt-lesslint');
  grunt.loadNpmTasks('grunt-htmllint');

  grunt.registerTask('build', [
    'clean:beforeBuild',
    'htmllint',
    'less:production',
    'ngconstant',
    'minify',
    'copy',
    'processhtml:production'
  ]);

  grunt.registerTask('release', [
    'bump-only',
    'build',
    'bump-commit'
  ]);

  grunt.registerTask('minify', [
    'concat',
    'uglify'
  ]);

  grunt.registerTask('server', [
    'htmllint',
    'less:development',
    'ngconstant',
    'sails-linker',
    'connect:server',
    'watch:css'
  ]);

  grunt.registerTask('serverjs', [
    'htmllint',
    'less:development',
    'ngconstant',
    'sails-linker',
    'connect:server',
    'watch:javascript'
  ]);

  grunt.registerTask('serverall', [
    'htmllint',
    'less:development',
    'ngconstant',
    'sails-linker',
    'connect:server',
    'watch'
  ]);

  grunt.registerTask('test', [
    'clean:beforeBuild',
    'htmllint',
    'lesslint',
    'ngconstant',
    'minify',
    'jshint',
    'jasmine:production',
    'clean:afterTest'
  ]);

  grunt.registerTask('test:development', [
    'htmllint',
    'lesslint',
    'ngconstant',
    'jshint',
    'jasmine:development'
  ]);

  grunt.registerTask('e2e', [
    'clean:beforeBuild',
    'less:production',
    'ngconstant',
    'minify',
    'copy',
    'processhtml:e2e',
    'connect:servertest',
    'protractor:dist',
    'clean:afterTest'
  ]);

  grunt.registerTask('default', ['build']);

};
<commit_msg>use ./ before directories/file paths<commit_after>'use strict';

var modRewrite = require('connect-modrewrite');

module.exports = function (grunt) {

  var base = grunt.option('base-dir') || '',
      env = grunt.option('env') || 'development',
      protractorConf = grunt.option('ci') ?
        './tests/e2e/protractor.saucelabs.conf.js' :
        './tests/e2e/protractor.conf.js' ;

  grunt.initConfig({

    pkg: grunt.file.readJSON('./package.json'),

    bower: grunt.file.readJSON('./bower.json'),

    env: grunt.file.readJSON('./env.json')[env],

    config: {
      outputDir: './dist/',
      applicationFiles: grunt.file.readJSON('./scripts.json').application,
      vendorFiles: grunt.file.readJSON('./scripts.json').vendor
    },

    connect: {
      options: {
        hostname: '0.0.0.0',
        port: 8000,
        base: base
      },
      server: {
        options: {
          livereload: true,
          middleware: function ( connect, options, middlewares ) {
            var rules = (base === 'dist') ?
                [ '^/[^\.]*$ /index.html' ] :
            [ '^/app/[^\.]*$ /app/index.html' ];
            middlewares.unshift( modRewrite( rules ) );
            return middlewares;
          }
        }
      },
      servertest: {
        options: {
          keepalive: false,
          livereload: false,
          base: '<%= config.outputDir %>',
          middleware: function ( connect, options, middlewares ) {
            var rules = [ '^/[^\.]*$ /index.html' ];
            middlewares.unshift( modRewrite( rules ) );
            return middlewares;
          }
        }
      }
    },

    watch: {
      options: {
        nospawn: false,
        livereload: true
      },
      css: {
        files: [
          './app/index.html',

          './app/less/*.less',
          './app/less/**/*.less',
          './app/less/**/**/*.less',

          './app/partials/*.html',
          './app/partials/**/*.html',
          './app/partials/**/**/*.html',

          './modules/*.html',
          './modules/**/*.html',
          './modules/**/**/*.html'
        ],
        tasks: ['htmllint','lesslint','less:development']
      },
      javascript: {
        files: [
          './scripts.json',

          './app/js/*.js',
          './app/js/**/*.js',
          './app/js/**/**/*.js',

          './tests/unit/*.js',
          './tests/unit/**/*.js',
          './tests/unit/**/**/*.js'
        ],
        tasks: ['sails-linker', 'test:development']
      }
    },

    less: {
      options: {
        paths: ['./app/less/'],
        cleancss: false,
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today(\'yyyy-mm-dd\') %> */\n'
      },
      development: {
        files: { './app/css/all.css': './app/less/main.less' },
        options: {
          sourceMap: true,
          sourceMapFilename: 'app/css/all.css.map',
          sourceMapURL: 'all.css.map',
          outputSourceFiles: true
        }
      },
      production: {
        files: { '<%= config.outputDir %>css/all.min.css': 'app/less/main.less' },
        options: {
          cleancss: true
        }
      }
    },

    jshint: {
      options: {
        jshintrc: '.jshintrc'
      },
      dist: {
        src: ['<%= config.applicationFiles %>']
      }
    },

    jasmine: {
      options: {
        specs: ['./tests/unit/**/*.js'],
        keepRunner: true,
      },
      development: {
        src: [
          '<%= ngconstant.options.dest %>',
          '<%= config.applicationFiles %>'
        ],
        options: {
          vendor: ['<%= config.vendorFiles %>'],
          helpers:['./app/components/angular-mocks/angular-mocks.js'],
          template: require('grunt-template-jasmine-istanbul'),
          templateOptions: {
            coverage: './coverage/coverage.json',
            report: [
              {
                type: 'lcov',
                options: {
                  dir: './coverage'
                }
              },
              {
                type: 'text-summary'
              }
            ]
          }
        }
      },
      production: {
        src: ['<%= config.outputDir %>js/app.min.js', './app/components/angular-mocks/angular-mocks.js']
      }
    },

    protractor: {
      options: {
        keepAlive: false,
        noColor: false
      },
      dist: {
        options: {
          configFile: protractorConf
        }
      }
    },

    concat: {
      options: {
        sourceMap: true,
        separator: ';',
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today(\'yyyy-mm-dd\') %> */\n'
      },
      production: {
        src: [
          '<%= config.vendorFiles %>',
          '<%= ngconstant.options.dest %>',
          '<%= config.applicationFiles %>'
        ],
        dest: '<%= config.outputDir %>js/app.js'
      }
    },

    uglify: {
      options: {
        sourceMap: true,
        sourceMapIncludeSources: true,
        enclose: { window: 'window' },
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today(\'yyyy-mm-dd\') %> */\n'
      },
      production: {
        files: {
          '<%= config.outputDir %>js/app.min.js': [ '<%= config.outputDir %>js/app.js' ]
        }
      }
    },

    copy: {
      images: {
        files: [{
          expand: true,
          cwd: './app/img',
          src: ['**/*', '!test/**'],
          dest: '<%= config.outputDir %>img/'
        }]
      },
      partials: {
        files: [{
          expand: true,
          cwd: './app/partials',
          src: ['**/*.html', '*.html'],
          dest: '<%= config.outputDir %>partials/'
        }]
      },
      fonts: {
        files: [{
          expand: true,
          cwd: './app/fonts',
          src: ['**/*', '*'],
          dest: '<%= config.outputDir %>fonts/'
        }]
      },
      data: {
        files: [{
          expand: true,
          cwd: './app/data',
          src: ['**/*', '*'],
          dest: '<%= config.outputDir %>data/'
        }]
      }
    },

    clean: {
      beforeBuild: {
        src: ['<%= config.outputDir %>', './docs']
      },
      afterTest: {
        src: ['<%= config.outputDir %>']
      }
    },

    processhtml: {
      options: {
        strip: true,
        data: { url: '<%= env.BASE_URL %>' }
      },
      production: {
        files: { '<%= config.outputDir %>index.html': ['./app/index.html'] }
      },
      e2e: {
        files: { '<%= config.outputDir %>index.html': ['./app/index.html'] },
        options: {
          data: { url: 'http://127.0.0.1:8000/' }
        }
      }
    },

    yuidoc: {
      compile: {
        name: '<%= pkg.name %>',
        description: '<%= pkg.description %>',
        version: '<%= pkg.version %>',
        url: '<%= pkg.homepage %>',
        options: {
          paths: './app/js/',
          themedir: 'node_modules/yuidoc-bootstrap-theme',
          helpers: ['node_modules/yuidoc-bootstrap-theme/helpers/helpers.js'],
          outdir: './docs/'
        }
      }
    },

    bump: {
      options: {
        files: ['./package.json', './bower.json'],
        updateConfigs: ['pkg'],
        commit: true,
        commitFiles: ['-a'],
        createTag: true,
        push: true,
        pushTo: 'origin master'
      }
    },

    ngconstant: {
      options: {
        name: 'config',
        dest: './app/js/config/config.js',
        constants: {
          bower: '<%= bower %>',
          pkg: '<%= pkg %>',
          env: '<%= env %>'
        }
      },
      dist: {}
    },

    'sails-linker': {
      vendorJs: {
        options: {
          startTag: '<!--VENDOR SCRIPTS-->',
          endTag: '<!--VENDOR SCRIPTS END-->',
          fileTmpl: '<script src=\'%s\'></script>',
          appRoot: './app/'
        },
        files: {
          './app/index.html': '<%= config.vendorFiles %>'
        }
      },
      appJs: {
        options: {
          startTag: '<!--SCRIPTS-->',
          endTag: '<!--SCRIPTS END-->',
          fileTmpl: '<script src=\'%s\'></script>',
          appRoot: './app/'
        },
        files: {
          './app/index.html': '<%= config.applicationFiles %>'
        }
      }
    },

    lesslint: {
      src: ['./app/less/main.less'],
      options: {
        imports: ['app/less/**/*.less'],
        csslint: {
          csslintrc: './app/less/.csslintrc',
        }
      }
    },

    /**
     * HTML linter
     * {@link https://github.com/htmllint/htmllint/wiki/Options .htmllintrc options}
     */
    htmllint: {
      options: {
        force: true,
        htmllintrc: './app/partials/.htmllintrc'
      },
      src: ['./app/*.html','./app/partials/**/*.html']
    }

  });

  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-yuidoc');
  grunt.loadNpmTasks('grunt-contrib-jasmine');
  grunt.loadNpmTasks('grunt-protractor-runner');
  grunt.loadNpmTasks('grunt-processhtml');
  grunt.loadNpmTasks('grunt-ng-constant');
  grunt.loadNpmTasks('grunt-bump');
  grunt.loadNpmTasks('grunt-sails-linker');
  grunt.loadNpmTasks('grunt-lesslint');
  grunt.loadNpmTasks('grunt-htmllint');

  grunt.registerTask('build', [
    'clean:beforeBuild',
    'htmllint',
    'less:production',
    'ngconstant',
    'minify',
    'copy',
    'processhtml:production'
  ]);

  grunt.registerTask('release', [
    'bump-only',
    'build',
    'bump-commit'
  ]);

  grunt.registerTask('minify', [
    'concat',
    'uglify'
  ]);

  grunt.registerTask('server', [
    'htmllint',
    'less:development',
    'ngconstant',
    'sails-linker',
    'connect:server',
    'watch:css'
  ]);

  grunt.registerTask('serverjs', [
    'htmllint',
    'less:development',
    'ngconstant',
    'sails-linker',
    'connect:server',
    'watch:javascript'
  ]);

  grunt.registerTask('serverall', [
    'htmllint',
    'less:development',
    'ngconstant',
    'sails-linker',
    'connect:server',
    'watch'
  ]);

  grunt.registerTask('test', [
    'clean:beforeBuild',
    'htmllint',
    'lesslint',
    'ngconstant',
    'minify',
    'jshint',
    'jasmine:production',
    'clean:afterTest'
  ]);

  grunt.registerTask('test:development', [
    'htmllint',
    'lesslint',
    'ngconstant',
    'jshint',
    'jasmine:development'
  ]);

  grunt.registerTask('e2e', [
    'clean:beforeBuild',
    'less:production',
    'ngconstant',
    'minify',
    'copy',
    'processhtml:e2e',
    'connect:servertest',
    'protractor:dist',
    'clean:afterTest'
  ]);

  grunt.registerTask('default', ['build']);

};
<|endoftext|>


<commit_before>'use strict';

/* eslint-env node, es6 */

const _ = require('underscore');
const fs = require('fs');
const path = require('path');
const initialize = require('./src/js/common/initialize');

// sources variables
const sources_dir = 'src';
const content_dir = path.join(sources_dir, 'content');
const pages_dir = path.join(content_dir, 'pages');
const layouts_dir = path.join(sources_dir, 'layouts');
const helpers_dir = path.join(sources_dir, 'helpers');
const partials_dir = path.join(layouts_dir, 'partials');
const sass_sources_dir = path.join(sources_dir, 'sass');
const js_sources_dir = path.join(sources_dir, 'js');
const applications_sources_dir = path.join(js_sources_dir, 'apps');

// destinations variables
const dest_dir = 'public';
const assets_dest_dir = path.join(dest_dir, 'assets');
const style_dest_dir = path.join(assets_dest_dir, 'css');
const applications_dest_dir = path.join(assets_dest_dir, 'js');

function is_dev() {
    switch (process.env.NODE_ENV) {
    case 'development':
    case 'dev':
        return true;
    default:
        return false;
    }
}

function is_prod() {
    return !is_dev()
}

function create_target(app, apps_source_dir, apps_dest_dir) {
    const sources_dir = path.join(apps_source_dir, app);
    const dest_dir = path.join(apps_dest_dir, app);
    const options = Object.assign(
        {browserifyOptions: {
            debug: true,
            paths: ['node_modules', js_sources_dir]
        }},
        {transform: [['babelify', {
            presets: ['es2015']
        }]]},
        is_prod() ? {plugin: [['minifyify', {map: false, minify: true}]]} : {}
    );
    return _.object([[app, {
        options,
        src: [`${sources_dir}/main.js`],
        dest: `${dest_dir}/app.js`
    }]]);
}

function create_browserify_targets(apps_sources_dir, apps_dest_dir) {
    return fs.readdirSync(apps_sources_dir)
        .filter((entry) => fs.statSync(path.join(apps_sources_dir, entry)).isDirectory())
        .reduce((targets, app) => Object.assign(
            targets,
            create_target(app, apps_sources_dir, apps_dest_dir)
        ), {});
}

module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        ///////////////////////////////////////////////////////////////////////
        // Variables
        sources_dir,
        content_dir,
        pages_dir,
        layouts_dir,
        helpers_dir,
        partials_dir,
        sass_sources_dir,
        js_sources_dir,
        applications_sources_dir,
        dest_dir,
        assets_dest_dir,
        style_dest_dir,
        applications_dest_dir,
        ///////////////////////////////////////////////////////////////////////
        // Configure tasks
        clean: {
            'pages': [
                '<%= dest_dir %>/index.html',
                '<%= dest_dir %>/pages'
            ],
            'scripts': ['<%= applications_dest_dir %>'],
            'style': ['<%= style_dest_dir %>']
        },
        browserify: create_browserify_targets(
            applications_sources_dir,
            applications_dest_dir
        ),
        metalsmith: {
            content: {
                options: {
                    clean: false,
                    metadata: Object.assign(
                        grunt.file.readJSON('config.json'),
                        {year: (new Date()).getFullYear()}
                    ),
                    plugins: [
                        {'metalsmith-discover-helpers': {
                            directory: '<%= helpers_dir %>',
                            pattern: /\.js$/
                        }},
                        {'metalsmith-collections': {}},
                        {'metalsmith-markdown': {}},
                        {'metalsmith-layouts': {
                            directory: '<%= layouts_dir %>',
                            engine: 'handlebars',
                            partials: '<%= partials_dir %>',
                            default: 'layout.html'
                        }}
                    ]
                },
                dest: '<%= dest_dir %>',
                src: '<%= content_dir %>'
            }
        },
        sass: {
            compile: {
                options: {
                    includePaths: [
                        '<%= sass_sources_dir %>',
                        'node_modules/foundation-sites/scss'
                    ],
                    outputStyle: is_dev() ? 'nested' : 'compressed',
                    sourceMap: is_dev()
                },
                files: [{
                    expand: true,
                    cwd: '<%= sass_sources_dir %>',
                    src: [
                        'about/style.scss',
                        'contact/style.scss',
                        'cv/style.scss',
                        'style.scss'
                    ],
                    dest: '<%= style_dest_dir %>',
                    ext: '.css'
                }]
            }
        },
        watch: {
            content: {
                files: [
                    '<%= content_dir %>/**/*.md',
                    '<%= helpers_dir %>/**/*.js',
                    '<%= layouts_dir %>/**/*.html'
                ],
                tasks: ['metalsmith'],
                options: {
                    livereload: true,
                    spawn: true
                }
            },
            scripts: {
                files: [
                    '<%= js_sources_dir %>/**/*.js'
                ],
                tasks: ['browserify'],
                options: {
                    livereload: true,
                    spawn: true
                }
            },
            styles: {
                files: [
                    '<%= sass_sources_dir %>/**/*.scss',
                    '<%= sass_sources_dir %>/**/*.sass'
                ],
                tasks: ['sass'],
                options: {
                    livereload: true,
                    spawn: true
                }
            }
        },
        prompt: {
            init: initialize
        }
    });
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-metalsmith');
    grunt.loadNpmTasks('grunt-notify');
    grunt.loadNpmTasks('grunt-sass');
    grunt.loadNpmTasks('grunt-browserify');
    grunt.loadNpmTasks('grunt-prompt');
    ///////////////////////////////////////////////////////////////////////
    // Register macro task(s).
    grunt.registerTask('default', ['clean', 'metalsmith', 'sass', 'browserify']);
};
<commit_msg>handle articles.<commit_after>'use strict';

/* eslint-env node, es6 */

const _ = require('underscore');
const fs = require('fs');
const path = require('path');
const initialize = require('./src/js/common/initialize');

// sources variables
const sources_dir = 'src';
const content_dir = path.join(sources_dir, 'content');
const pages_dir = path.join(content_dir, 'pages');
const layouts_dir = path.join(sources_dir, 'layouts');
const helpers_dir = path.join(sources_dir, 'helpers');
const partials_dir = path.join(layouts_dir, 'partials');
const sass_sources_dir = path.join(sources_dir, 'sass');
const js_sources_dir = path.join(sources_dir, 'js');
const applications_sources_dir = path.join(js_sources_dir, 'apps');

// destinations variables
const dest_dir = 'public';
const assets_dest_dir = path.join(dest_dir, 'assets');
const style_dest_dir = path.join(assets_dest_dir, 'css');
const applications_dest_dir = path.join(assets_dest_dir, 'js');

function is_dev() {
    switch (process.env.NODE_ENV) {
    case 'development':
    case 'dev':
        return true;
    default:
        return false;
    }
}

function is_prod() {
    return !is_dev()
}

function create_target(app, apps_source_dir, apps_dest_dir) {
    const sources_dir = path.join(apps_source_dir, app);
    const dest_dir = path.join(apps_dest_dir, app);
    const options = Object.assign(
        {browserifyOptions: {
            debug: true,
            paths: ['node_modules', js_sources_dir]
        }},
        {transform: [['babelify', {
            presets: ['es2015']
        }]]},
        is_prod() ? {plugin: [['minifyify', {map: false, minify: true}]]} : {}
    );
    return _.object([[app, {
        options,
        src: [`${sources_dir}/main.js`],
        dest: `${dest_dir}/app.js`
    }]]);
}

function create_browserify_targets(apps_sources_dir, apps_dest_dir) {
    return fs.readdirSync(apps_sources_dir)
        .filter((entry) => fs.statSync(path.join(apps_sources_dir, entry)).isDirectory())
        .reduce((targets, app) => Object.assign(
            targets,
            create_target(app, apps_sources_dir, apps_dest_dir)
        ), {});
}

module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        ///////////////////////////////////////////////////////////////////////
        // Variables
        sources_dir,
        content_dir,
        pages_dir,
        layouts_dir,
        helpers_dir,
        partials_dir,
        sass_sources_dir,
        js_sources_dir,
        applications_sources_dir,
        dest_dir,
        assets_dest_dir,
        style_dest_dir,
        applications_dest_dir,
        ///////////////////////////////////////////////////////////////////////
        // Configure tasks
        clean: {
            'pages': [
                '<%= dest_dir %>/index.html',
                '<%= dest_dir %>/pages'
            ],
            'scripts': ['<%= applications_dest_dir %>'],
            'style': ['<%= style_dest_dir %>']
        },
        browserify: create_browserify_targets(
            applications_sources_dir,
            applications_dest_dir
        ),
        metalsmith: {
            content: {
                options: {
                    clean: false,
                    metadata: Object.assign(
                        grunt.file.readJSON('config.json'),
                        {year: (new Date()).getFullYear()}
                    ),
                    plugins: [
                        {'metalsmith-discover-helpers': {
                            directory: '<%= helpers_dir %>',
                            pattern: /\.js$/
                        }},
                        {'metalsmith-collections': {}},
                        {'metalsmith-markdown': {
                            highlight: (code) => require('highlight.js').highlightAuto(code).value
                        }},
                        {'metalsmith-layouts': {
                            directory: '<%= layouts_dir %>',
                            engine: 'handlebars',
                            partials: '<%= partials_dir %>',
                            default: 'layout.html'
                        }}
                    ]
                },
                dest: '<%= dest_dir %>',
                src: '<%= content_dir %>'
            }
        },
        sass: {
            compile: {
                options: {
                    includePaths: [
                        '<%= sass_sources_dir %>',
                        'node_modules/foundation-sites/scss',
                        'node_modules/highlight.js/styles'
                    ],
                    outputStyle: is_dev() ? 'nested' : 'compressed',
                    sourceMap: is_dev()
                },
                files: [{
                    expand: true,
                    cwd: '<%= sass_sources_dir %>',
                    src: [
                        'about/style.scss',
                        'articles/style.scss',
                        'contact/style.scss',
                        'cv/style.scss',
                        'style.scss'
                    ],
                    dest: '<%= style_dest_dir %>',
                    ext: '.css'
                }]
            }
        },
        watch: {
            content: {
                files: [
                    '<%= content_dir %>/**/*.md',
                    '<%= helpers_dir %>/**/*.js',
                    '<%= layouts_dir %>/**/*.html'
                ],
                tasks: ['metalsmith'],
                options: {
                    livereload: true,
                    spawn: true
                }
            },
            scripts: {
                files: [
                    '<%= js_sources_dir %>/**/*.js'
                ],
                tasks: ['browserify'],
                options: {
                    livereload: true,
                    spawn: true
                }
            },
            styles: {
                files: [
                    '<%= sass_sources_dir %>/**/*.scss',
                    '<%= sass_sources_dir %>/**/*.sass'
                ],
                tasks: ['sass'],
                options: {
                    livereload: true,
                    spawn: true
                }
            }
        },
        prompt: {
            init: initialize
        }
    });
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-metalsmith');
    grunt.loadNpmTasks('grunt-notify');
    grunt.loadNpmTasks('grunt-sass');
    grunt.loadNpmTasks('grunt-browserify');
    grunt.loadNpmTasks('grunt-prompt');
    ///////////////////////////////////////////////////////////////////////
    // Register macro task(s).
    grunt.registerTask('default', ['clean', 'metalsmith', 'sass', 'browserify']);
};
<|endoftext|>


<commit_before>/**
 * Copyright 2013 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 "use strict";

/**
 * @fileoverview Common utility functionality for Google Drive Realtime API,
 * including authorization and file loading. This functionality should serve
 * mostly as a well-documented example, though is usable in its own right.
 */

/**
 * @namespace Realtime client utilities namespace.
 */
var rtclient = rtclient || {}

/**
 * OAuth 2.0 scope for installing Drive Apps.
 * @const
 */
rtclient.INSTALL_SCOPE = 'https://www.googleapis.com/auth/drive.install'

/**
 * OAuth 2.0 scope for opening and creating files.
 * @const
 */
rtclient.FILE_SCOPE = 'https://www.googleapis.com/auth/drive.file'

/**
 * OAuth 2.0 scope for accessing the user's ID.
 * @const
 */
rtclient.OPENID_SCOPE = 'openid'

/**
 * MIME type for newly created Realtime files.
 * @const
 */
rtclient.REALTIME_MIMETYPE = 'application/vnd.google-apps.drive-sdk';

/**
 * Parses the hash parameters to this page and returns them as an object.
 * @function
 */
rtclient.getParams = function() {
  var params = {};
  var hashFragment = window.location.hash;
  if (hashFragment) {
    // split up the query string and store in an object
    var paramStrs = hashFragment.slice(1).split("&");
    for (var i = 0; i < paramStrs.length; i++) {
      var paramStr = paramStrs[i].split("=");
      params[paramStr[0]] = unescape(paramStr[1]);
    }
  }
  console.log(params);
  return params;
}

/**
 * Instance of the query parameters.
 */
rtclient.params = rtclient.getParams();

/**
 * Fetches an option from options or a default value, logging an error if
 * neither is available.
 * @param options {Object} containing options.
 * @param key {string} option key.
 * @param defaultValue {Object} default option value (optional).
 */
rtclient.getOption = function(options, key, defaultValue) {
  var value = options[key] == undefined ? defaultValue : options[key];
  if (value == undefined) {
    console.error(key + ' should be present in the options.');
  }
  console.log(value);
  return value;
}

/**
 * Creates a new Authorizer from the options.
 * @constructor
 * @param options {Object} for authorizer. Two keys are required as mandatory, these are:
 *
 *    1. "clientId", the Client ID from the APIs Console
 */
rtclient.Authorizer = function(options) {
  this.clientId = rtclient.getOption(options, 'clientId');
  // Get the user ID if it's available in the state query parameter.
  this.userId = rtclient.params['userId'];
  this.authButton = document.getElementById(rtclient.getOption(options, 'authButtonElementId'));
}

/**
 * Start the authorization process.
 * @param onAuthComplete {Function} to call once authorization has completed.
 */
rtclient.Authorizer.prototype.start = function(onAuthComplete) {
  var _this = this;
  gapi.load('auth:client,drive-realtime,drive-share', function() {
    _this.authorize(onAuthComplete);
  });
}

/**
 * Reauthorize the client with no callback (used for authorization failure).
 * @param onAuthComplete {Function} to call once authorization has completed.
 */
rtclient.Authorizer.prototype.authorize = function(onAuthComplete) {
  var clientId = this.clientId;
  var userId = this.userId;
  var _this = this;

  var handleAuthResult = function(authResult) {
    if (authResult && !authResult.error) {
      _this.authButton.disabled = true;
      _this.fetchUserId(onAuthComplete);
    } else {
      _this.authButton.disabled = false;
      _this.authButton.onclick = authorizeWithPopup;
    }
  };

  var authorizeWithPopup = function() {
    gapi.auth.authorize({
      client_id: clientId,
      scope: [
        rtclient.INSTALL_SCOPE,
        rtclient.FILE_SCOPE,
        rtclient.OPENID_SCOPE
      ],
      user_id: userId,
      immediate: false
    }, handleAuthResult);
    console.log(clientId);
  };

  // Try with no popups first.
  gapi.auth.authorize({
    client_id: clientId,
    scope: [
      rtclient.INSTALL_SCOPE,
      rtclient.FILE_SCOPE,
      rtclient.OPENID_SCOPE
    ],
    user_id: userId,
    immediate: true
  }, handleAuthResult);
}

/**
 * Fetch the user ID using the UserInfo API and save it locally.
 * @param callback {Function} the callback to call after user ID has been
 *     fetched.
 */
rtclient.Authorizer.prototype.fetchUserId = function(callback) {
  var _this = this;
  gapi.client.load('oauth2', 'v2', function() {
    gapi.client.oauth2.userinfo.get().execute(function(resp) {
      if (resp.id) {
        _this.userId = resp.id;
      }
      if (callback) {
        callback();
      }
    });
  });
};

/**
 * Creates a new Realtime file.
 * @param title {string} title of the newly created file.
 * @param mimeType {string} the MIME type of the new file.
 * @param callback {Function} the callback to call after creation.
 */
rtclient.createRealtimeFile = function(title, mimeType, callback) {
  gapi.client.load('drive', 'v2', function() {
    gapi.client.drive.files.insert({
      'resource': {
        mimeType: mimeType,
        title: title
      }
    }).execute(callback);
  });
}

/**
 * Fetches the metadata for a Realtime file.
 * @param fileId {string} the file to load metadata for.
 * @param callback {Function} the callback to be called on completion, with signature:
 *
 *    function onGetFileMetadata(file) {}
 *
 * where the file parameter is a Google Drive API file resource instance.
 */
rtclient.getFileMetadata = function(fileId, callback) {
  gapi.client.load('drive', 'v2', function() {
    gapi.client.drive.files.get({
      'fileId' : fileId
    }).execute(callback);
  });
}

/**
 * Parses the state parameter passed from the Drive user interface after Open
 * With operations.
 * @param stateParam {Object} the state query parameter as an object or null if
 *     parsing failed.
 */
rtclient.parseState = function(stateParam) {
  try {
    var stateObj = JSON.parse(stateParam);
    return stateObj;
  } catch(e) {
    return null;
  }
}

/**
 * Handles authorizing, parsing query parameters, loading and creating Realtime
 * documents.
 * @constructor
 * @param options {Object} options for loader. Four keys are required as mandatory, these are:
 *
 *    1. "clientId", the Client ID from the APIs Console
 *    2. "initializeModel", the callback to call when the file is loaded.
 *    3. "onFileLoaded", the callback to call when the model is first created.
 *
 * and one key is optional:
 *
 *    1. "defaultTitle", the title of newly created Realtime files.
 */
rtclient.RealtimeLoader = function(options) {
  // Initialize configuration variables.
  this.onFileLoaded = rtclient.getOption(options, 'onFileLoaded');
  this.newFileMimeType = rtclient.getOption(options, 'newFileMimeType', rtclient.REALTIME_MIMETYPE);
  this.initializeModel = rtclient.getOption(options, 'initializeModel');
  this.registerTypes = rtclient.getOption(options, 'registerTypes', function(){});
  this.afterAuth = rtclient.getOption(options, 'afterAuth', function(){})
  this.autoCreate = rtclient.getOption(options, 'autoCreate', false); // This tells us if need to we automatically create a file after auth.
  this.defaultTitle = rtclient.getOption(options, 'defaultTitle', 'New Realtime File');
  this.authorizer = new rtclient.Authorizer(options);
}

/**
 * Redirects the browser back to the current page with an appropriate file ID.
 * @param fileIds {Array.} the IDs of the files to open.
 * @param userId {string} the ID of the user.
 */
rtclient.RealtimeLoader.prototype.redirectTo = function(fileIds, userId) {
  var params = [];
  if (fileIds) {
    params.push('fileIds=' + fileIds.join(','));
  }
  if (userId) {
    params.push('userId=' + userId);
  }

  // Naive URL construction.
  var newUrl = params.length == 0 ? './' : ('./#' + params.join('&'));
  // Using HTML URL re-write if available.
  if (window.history && window.history.replaceState) {
    window.history.replaceState("Google Drive Realtime API Playground", "Google Drive Realtime API Playground", newUrl);
  } else {
    window.location.href = newUrl;
  }
  // We are still here that means the page didn't reload.
  rtclient.params = rtclient.getParams();
  for (var index in fileIds) {
    gapi.drive.realtime.load(fileIds[index], this.onFileLoaded, this.initializeModel, this.handleErrors);
  }
}

/**
 * Starts the loader by authorizing.
 */
rtclient.RealtimeLoader.prototype.start = function() {
  // Bind to local context to make them suitable for callbacks.
  var _this = this;
  this.authorizer.start(function() {
    if (_this.registerTypes) {
      _this.registerTypes();
    }
    if (_this.afterAuth) {
      _this.afterAuth();
    }
    _this.load();
  });
}

/**
 * Handles errors thrown by the Realtime API.
 */
rtclient.RealtimeLoader.prototype.handleErrors = function(e) {
  if(e.type == gapi.drive.realtime.ErrorType.TOKEN_REFRESH_REQUIRED) {
    authorizer.authorize();
  } else if(e.type == gapi.drive.realtime.ErrorType.CLIENT_ERROR) {
    alert("An Error happened: " + e.message);
    window.location.href= "/";
  } else if(e.type == gapi.drive.realtime.ErrorType.NOT_FOUND) {
    alert("The file was not found. It does not exist or you do not have read access to the file.");
    window.location.href= "/";
  }
};

/**
 * Loads or creates a Realtime file depending on the fileId and state query
 * parameters.
 */
rtclient.RealtimeLoader.prototype.load = function() {
  var fileIds = rtclient.params['fileIds'];
  if (fileIds) {
    fileIds = fileIds.split(',');
  }
  var userId = this.authorizer.userId;
  var state = rtclient.params['state'];

  // Creating the error callback.
  var authorizer = this.authorizer;

  // We have file IDs in the query parameters, so we will use them to load a file.
  if (fileIds) {
    for (var index in fileIds) {
      gapi.drive.realtime.load(fileIds[index], this.onFileLoaded, this.initializeModel, this.handleErrors);
    }
    return;
  }

  // We have a state parameter being redirected from the Drive UI. We will parse
  // it and redirect to the fileId contained.
  else if (state) {
    var stateObj = rtclient.parseState(state);
    // If opening a file from Drive.
    if (stateObj.action == "open") {
      fileIds = stateObj.ids;
      userId = stateObj.userId;
      this.redirectTo(fileIds, userId);
      return;
    }
  }

  if (this.autoCreate) {
    this.createNewFileAndRedirect();
  }
}

/**
 * Creates a new file and redirects to the URL to load it.
 */
rtclient.RealtimeLoader.prototype.createNewFileAndRedirect = function() {
  // No fileId or state have been passed. We create a new Realtime file and
  // redirect to it.
  var _this = this;
  rtclient.createRealtimeFile(this.defaultTitle, this.newFileMimeType, function(file) {
    if (file.id) {
      _this.redirectTo([file.id], _this.authorizer.userId);
    }
    // File failed to be created, log why and do not attempt to redirect.
    else {
      console.error('Error creating file.');
      console.error(file);
    }
  });
}
<commit_msg>take event handlers for change on auth need<commit_after>/**
 * Copyright 2013 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 "use strict";

/**
 * @fileoverview Common utility functionality for Google Drive Realtime API,
 * including authorization and file loading. This functionality should serve
 * mostly as a well-documented example, though is usable in its own right.
 */

/**
 * @namespace Realtime client utilities namespace.
 */
var rtclient = rtclient || {}

/**
 * OAuth 2.0 scope for installing Drive Apps.
 * @const
 */
rtclient.INSTALL_SCOPE = 'https://www.googleapis.com/auth/drive.install'

/**
 * OAuth 2.0 scope for opening and creating files.
 * @const
 */
rtclient.FILE_SCOPE = 'https://www.googleapis.com/auth/drive.file'

/**
 * OAuth 2.0 scope for accessing the user's ID.
 * @const
 */
rtclient.OPENID_SCOPE = 'openid'

/**
 * MIME type for newly created Realtime files.
 * @const
 */
rtclient.REALTIME_MIMETYPE = 'application/vnd.google-apps.drive-sdk';

/**
 * Parses the hash parameters to this page and returns them as an object.
 * @function
 */
rtclient.getParams = function() {
  var params = {};
  var hashFragment = window.location.hash;
  if (hashFragment) {
    // split up the query string and store in an object
    var paramStrs = hashFragment.slice(1).split("&");
    for (var i = 0; i < paramStrs.length; i++) {
      var paramStr = paramStrs[i].split("=");
      params[paramStr[0]] = unescape(paramStr[1]);
    }
  }
  console.log(params);
  return params;
}

/**
 * Instance of the query parameters.
 */
rtclient.params = rtclient.getParams();

/**
 * Fetches an option from options or a default value, logging an error if
 * neither is available.
 * @param options {Object} containing options.
 * @param key {string} option key.
 * @param defaultValue {Object} default option value (optional).
 */
rtclient.getOption = function(options, key, defaultValue) {
  var value = options[key] == undefined ? defaultValue : options[key];
  if (value == undefined) {
    console.error(key + ' should be present in the options.');
  }
  console.log(value);
  return value;
}

/**
 * Creates a new Authorizer from the options.
 * @constructor
 * @param options {Object} for authorizer. Two keys are required as mandatory, these are:
 *
 *    1. "clientId", the Client ID from the APIs Console
 */
rtclient.Authorizer = function(options) {
  this.clientId = rtclient.getOption(options, 'clientId');
  // Get the user ID if it's available in the state query parameter.
  this.userId = rtclient.params['userId'];
  this.authButton = document.getElementById(rtclient.getOption(options, 'authButtonElementId'));
  this.onNeedAuth = rtclient.getOption(options, 'onNeedAuth');
  this.onNoNeedAuth = rtclient.getOption(options, 'onNoNeedAuth');
}

/**
 * Start the authorization process.
 * @param onAuthComplete {Function} to call once authorization has completed.
 */
rtclient.Authorizer.prototype.start = function(onAuthComplete) {
  var _this = this;
  gapi.load('auth:client,drive-realtime,drive-share', function() {
    _this.authorize(onAuthComplete);
  });
}

/**
 * Reauthorize the client with no callback (used for authorization failure).
 * @param onAuthComplete {Function} to call once authorization has completed.
 */
rtclient.Authorizer.prototype.authorize = function(onAuthComplete) {
  var clientId = this.clientId;
  var userId = this.userId;
  var _this = this;

  var handleAuthResult = function(authResult) {
    if (authResult && !authResult.error) {
      _this.onNoNeedAuth();
      _this.fetchUserId(onAuthComplete);
    } else {
      _this.onNeedAuth();
    }
  };

  var authorizeWithPopup = function() {
    gapi.auth.authorize({
      client_id: clientId,
      scope: [
        rtclient.INSTALL_SCOPE,
        rtclient.FILE_SCOPE,
        rtclient.OPENID_SCOPE
      ],
      user_id: userId,
      immediate: false
    }, handleAuthResult);
    console.log(clientId);
  };

  // Try with no popups first.
  gapi.auth.authorize({
    client_id: clientId,
    scope: [
      rtclient.INSTALL_SCOPE,
      rtclient.FILE_SCOPE,
      rtclient.OPENID_SCOPE
    ],
    user_id: userId,
    immediate: true
  }, handleAuthResult);
}

/**
 * Fetch the user ID using the UserInfo API and save it locally.
 * @param callback {Function} the callback to call after user ID has been
 *     fetched.
 */
rtclient.Authorizer.prototype.fetchUserId = function(callback) {
  var _this = this;
  gapi.client.load('oauth2', 'v2', function() {
    gapi.client.oauth2.userinfo.get().execute(function(resp) {
      if (resp.id) {
        _this.userId = resp.id;
      }
      if (callback) {
        callback();
      }
    });
  });
};

/**
 * Creates a new Realtime file.
 * @param title {string} title of the newly created file.
 * @param mimeType {string} the MIME type of the new file.
 * @param callback {Function} the callback to call after creation.
 */
rtclient.createRealtimeFile = function(title, mimeType, callback) {
  gapi.client.load('drive', 'v2', function() {
    gapi.client.drive.files.insert({
      'resource': {
        mimeType: mimeType,
        title: title
      }
    }).execute(callback);
  });
}

/**
 * Fetches the metadata for a Realtime file.
 * @param fileId {string} the file to load metadata for.
 * @param callback {Function} the callback to be called on completion, with signature:
 *
 *    function onGetFileMetadata(file) {}
 *
 * where the file parameter is a Google Drive API file resource instance.
 */
rtclient.getFileMetadata = function(fileId, callback) {
  gapi.client.load('drive', 'v2', function() {
    gapi.client.drive.files.get({
      'fileId' : fileId
    }).execute(callback);
  });
}

/**
 * Parses the state parameter passed from the Drive user interface after Open
 * With operations.
 * @param stateParam {Object} the state query parameter as an object or null if
 *     parsing failed.
 */
rtclient.parseState = function(stateParam) {
  try {
    var stateObj = JSON.parse(stateParam);
    return stateObj;
  } catch(e) {
    return null;
  }
}

/**
 * Handles authorizing, parsing query parameters, loading and creating Realtime
 * documents.
 * @constructor
 * @param options {Object} options for loader. Four keys are required as mandatory, these are:
 *
 *    1. "clientId", the Client ID from the APIs Console
 *    2. "initializeModel", the callback to call when the file is loaded.
 *    3. "onFileLoaded", the callback to call when the model is first created.
 *
 * and one key is optional:
 *
 *    1. "defaultTitle", the title of newly created Realtime files.
 */
rtclient.RealtimeLoader = function(options) {
  // Initialize configuration variables.
  this.onFileLoaded = rtclient.getOption(options, 'onFileLoaded');
  this.newFileMimeType = rtclient.getOption(options, 'newFileMimeType', rtclient.REALTIME_MIMETYPE);
  this.initializeModel = rtclient.getOption(options, 'initializeModel');
  this.registerTypes = rtclient.getOption(options, 'registerTypes', function(){});
  this.afterAuth = rtclient.getOption(options, 'afterAuth', function(){})
  this.autoCreate = rtclient.getOption(options, 'autoCreate', false); // This tells us if need to we automatically create a file after auth.
  this.defaultTitle = rtclient.getOption(options, 'defaultTitle', 'New Realtime File');
  this.authorizer = new rtclient.Authorizer(options);
}

/**
 * Redirects the browser back to the current page with an appropriate file ID.
 * @param fileIds {Array.} the IDs of the files to open.
 * @param userId {string} the ID of the user.
 */
rtclient.RealtimeLoader.prototype.redirectTo = function(fileIds, userId) {
  var params = [];
  if (fileIds) {
    params.push('fileIds=' + fileIds.join(','));
  }
  if (userId) {
    params.push('userId=' + userId);
  }

  // Naive URL construction.
  var newUrl = params.length == 0 ? './' : ('./#' + params.join('&'));
  // Using HTML URL re-write if available.
  if (window.history && window.history.replaceState) {
    window.history.replaceState("Google Drive Realtime API Playground", "Google Drive Realtime API Playground", newUrl);
  } else {
    window.location.href = newUrl;
  }
  // We are still here that means the page didn't reload.
  rtclient.params = rtclient.getParams();
  for (var index in fileIds) {
    gapi.drive.realtime.load(fileIds[index], this.onFileLoaded, this.initializeModel, this.handleErrors);
  }
}

/**
 * Starts the loader by authorizing.
 */
rtclient.RealtimeLoader.prototype.start = function() {
  // Bind to local context to make them suitable for callbacks.
  var _this = this;
  this.authorizer.start(function() {
    if (_this.registerTypes) {
      _this.registerTypes();
    }
    if (_this.afterAuth) {
      _this.afterAuth();
    }
    _this.load();
  });
}

/**
 * Handles errors thrown by the Realtime API.
 */
rtclient.RealtimeLoader.prototype.handleErrors = function(e) {
  if(e.type == gapi.drive.realtime.ErrorType.TOKEN_REFRESH_REQUIRED) {
    authorizer.authorize();
  } else if(e.type == gapi.drive.realtime.ErrorType.CLIENT_ERROR) {
    alert("An Error happened: " + e.message);
    window.location.href= "/";
  } else if(e.type == gapi.drive.realtime.ErrorType.NOT_FOUND) {
    alert("The file was not found. It does not exist or you do not have read access to the file.");
    window.location.href= "/";
  }
};

/**
 * Loads or creates a Realtime file depending on the fileId and state query
 * parameters.
 */
rtclient.RealtimeLoader.prototype.load = function() {
  var fileIds = rtclient.params['fileIds'];
  if (fileIds) {
    fileIds = fileIds.split(',');
  }
  var userId = this.authorizer.userId;
  var state = rtclient.params['state'];

  // Creating the error callback.
  var authorizer = this.authorizer;

  // We have file IDs in the query parameters, so we will use them to load a file.
  if (fileIds) {
    for (var index in fileIds) {
      gapi.drive.realtime.load(fileIds[index], this.onFileLoaded, this.initializeModel, this.handleErrors);
    }
    return;
  }

  // We have a state parameter being redirected from the Drive UI. We will parse
  // it and redirect to the fileId contained.
  else if (state) {
    var stateObj = rtclient.parseState(state);
    // If opening a file from Drive.
    if (stateObj.action == "open") {
      fileIds = stateObj.ids;
      userId = stateObj.userId;
      this.redirectTo(fileIds, userId);
      return;
    }
  }

  if (this.autoCreate) {
    this.createNewFileAndRedirect();
  }
}

/**
 * Creates a new file and redirects to the URL to load it.
 */
rtclient.RealtimeLoader.prototype.createNewFileAndRedirect = function() {
  // No fileId or state have been passed. We create a new Realtime file and
  // redirect to it.
  var _this = this;
  rtclient.createRealtimeFile(this.defaultTitle, this.newFileMimeType, function(file) {
    if (file.id) {
      _this.redirectTo([file.id], _this.authorizer.userId);
    }
    // File failed to be created, log why and do not attempt to redirect.
    else {
      console.error('Error creating file.');
      console.error(file);
    }
  });
}
<|endoftext|>


<commit_before>/*
* AUI Base
*/
AUI.add('aui-base', function(A) {

	A.mix(A.Array, {
		remove: function(a, from, to) {
		  var rest = a.slice((to || from) + 1 || a.length);
		  a.length = (from < 0) ? (a.length + from) : from;

		  return a.push.apply(a, rest);
		},

		removeItem: function(a, item) {
			var index = A.Array.indexOf(a, item);

		  	return A.Array.remove(a, index);
		}
	});

}, '@VERSION', { requires: [ 'yui-base' ] });

/*
* AUI Delayed Task
*/

AUI.add('delayed-task', function(A) {

	var DelayedTask = function(fn, scope, args) {
		var instance = this;

		instance._args = args;
		instance._delay = 0;
		instance._fn = fn;
		instance._id = null;
		instance._scope = scope || instance;
		instance._time = 0;

		instance._base = function() {
			var now = instance._getTime();

			if (now - instance._time >= instance._delay) {
				clearInterval(instance._id);

				instance._id = null;

				instance._fn.apply(instance._scope, instance._args || []);
			}
		};
	};

	DelayedTask.prototype = {
		delay: function(delay, newFn, newScope, newArgs) {
			var instance = this;

			if (instance._id && instance._delay != delay) {
				instance.cancel();
			}

			instance._delay = delay || instance._delay;
			instance._time = instance._getTime();

			instance._fn = newFn || instance._fn;
			instance._scope = newScope || instance._scope;
			instance._args = newArgs || instance._args;

			if (!A.Lang.isArray(instance._args)) {
				instance._args = [instance._args];
			}

			if (!instance._id) {
				if (instance._delay > 0) {
					instance._id = setInterval(instance._base, instance._delay);
				}
				else {
					instance._base();
				}
			}
		},

		cancel: function() {
			var instance = this;

			if (instance._id) {
				clearInterval(instance._id);

				instance._id = null;
			}
		},

		_getTime: function() {
			var instance = this;

			return (+new Date());
		}
	};

	A.DelayedTask = DelayedTask;

}, '@VERSION', { requires: [ 'yui-base' ] });

/*
* AUI Node
*/

AUI.add('aui-node', function(A) {

	var Lang = A.Lang,
		isString = Lang.isString,
		isUndefined = Lang.isUndefined,

		INNER_HTML = 'innerHTML';

	A.mix(A.Node.prototype, {
		after: function(content) {
			var instance = this;

			return instance.insertAfter(content);
		},

		appendTo: function(selector) {
			var instance = this;

			A.get(selector).append(instance);
		},

		attr: function(name, value) {
			var instance = this;

			if (!isUndefined(value)) {
				return instance.setAttribute(name, value);
			}
			else {
				return instance.getAttribute(name);
			}
		},

		before: function(content) {
			var instance = this;

			var parent = instance.get('parentNode');

			if (parent) {
				parent.insert(content, instance);
			}

			return instance;
		},

		empty: function() {
			var instance = this;

			instance.queryAll('>*').remove();

			var el = A.Node.getDOMNode(instance);

			while (el.firstChild) {
				el.removeChild(el.firstChild);
			}

			return instance;
		},

		getDOM: function() {
			var instance = this;

			return A.Node.getDOMNode(instance);
		},

		html: function() {
			var args = arguments, length = args.length;

			if (length) {
				this.set(INNER_HTML, args[0]);
			}
			else {
				return this.get(INNER_HTML);
			}

			return this;
		},

		insertAfter: function(content) {
			var instance = this;

			var parent = instance.get('parentNode');

			if (parent) {
				parent.insert(content, instance.get('nextSibling'));
			}

			return instance;
		},

		prependTo: function(selector) {
			var instance = this;

			A.get(selector).prepend(instance);
		},

		text: function(text) {
			var instance = this;

			if (!isUndefined(text)) {
				text = A.DOM._getDoc(A.Node.getDOMNode(instance)).createTextNode(text);

				return instance.empty().append(text);
			}

			var el = A.Node.getDOMNode(instance);

			return instance._getText(el.childNodes);
		},

		_getText: function(childNodes) {
			var instance = this;

			var length = childNodes.length;
			var childNode;

			var str = [];

			for (var i = 0; i < length; i++) {
				childNode = childNodes[i];

				if (childNode && childNode.nodeType != 8) {
					if (childNode.nodeType != 1) {
						str.push(childNode.nodeValue);
					}

					if (childNode.childNodes) {
						str.push(instance._getText(childNode.childNodes));
					}
				}
			}

			return str.join('');
		}
	}, true);

	A.mix(A.Node, {
		globalEval: function(data) {
			if ( data && /\S/.test(data) ) {
				var head = document.getElementsByTagName("head")[0] || document.documentElement;
				var script = document.createElement("script");

				script.type = "text/javascript";

				if (AUI.support.scriptEval) {
					script.appendChild(document.createTextNode(data));
				}
				else {
					script.text = data;
				}

				head.insertBefore(script, head.firstChild);
				head.removeChild(script);
			}
		},

		evalScript: function(elem) {
			if (elem.src) {
				A.io(elem.src, {
					async: false,
					on: {
						complete: function(i, o) {
							A.Node.globalEval(o.responseText);
						}
					}
				});
			}
			else {
				A.Node.globalEval(elem.text || elem.textContent || elem.innerHTML || "");
			}
		},

		clean: function(html) {
			var TPL_NODE = '

',
				IE_FIX_PADDING_NODE = '
_
',
				SCRIPT = 'script';

			// instead of fix all tags to "XHTML"-style, make the firstChild be a valid non-empty tag
			html = IE_FIX_PADDING_NODE + A.Lang.trim(html);

			delete A.DOM._cloneCache[html];

			// wrap in a nodeType == 1, nodeType 11 (document fragment) does not support getElementsByTagName
			var temp = A.Node.create(TPL_NODE).append(
				A.Node.create(html)
			);

			var scripts = temp.getElementsByTagName(SCRIPT);

			scripts.each(function(elem) {
				elem.remove();
			});

			temp.removeChild(A.Node.getDOMNode(temp).firstChild);

			var html = temp.html();

			// avoid IE6 memory leak
			temp = null;

			return [ html, scripts ];
		},

		domManip: function(html, callback) {
			var clean = A.Node.clean(html);
			var content = clean[0];
			var scripts = clean[1];

			if (callback) {
				callback.apply(this, [ content ]);
			}

			scripts.each(function(elem) {
				A.Node.evalScript( A.Node.getDOMNode(elem) );
			});
		}
	});

	A.Node.ATTRS.innerHTML = {
		setter: function(v) {
			var instance = this;

			var defaultSetter = function(value) {
				A.Node.DEFAULT_SETTER.apply(instance, [ INNER_HTML, value ]);
			};

			if (isString(v)) {
				// eval scripts
				v = A.Node.domManip(v, defaultSetter);
			}
			else {
				defaultSetter(v);
			}
		}
	};

	A.NodeList.importMethod(
		A.Node.prototype,
		[
			'after',

			'appendTo',

			'attr',

			'before',

			'empty',

			'html',

			'insertAfter',

			'prepend',

			'prependTo',

			'text'
		]
	);

	A.NodeList.prototype.getDOM = function() {
		return A.NodeList.getDOMNodes(this);
	};

}, '@VERSION', { requires: [ 'node' ] });<commit_msg>Fixes for .after and .before<commit_after>/*
* AUI Base
*/
AUI.add('aui-base', function(A) {

	A.mix(A.Array, {
		remove: function(a, from, to) {
		  var rest = a.slice((to || from) + 1 || a.length);
		  a.length = (from < 0) ? (a.length + from) : from;

		  return a.push.apply(a, rest);
		},

		removeItem: function(a, item) {
			var index = A.Array.indexOf(a, item);

		  	return A.Array.remove(a, index);
		}
	});

}, '@VERSION', { requires: [ 'yui-base' ] });

/*
* AUI Delayed Task
*/

AUI.add('delayed-task', function(A) {

	var DelayedTask = function(fn, scope, args) {
		var instance = this;

		instance._args = args;
		instance._delay = 0;
		instance._fn = fn;
		instance._id = null;
		instance._scope = scope || instance;
		instance._time = 0;

		instance._base = function() {
			var now = instance._getTime();

			if (now - instance._time >= instance._delay) {
				clearInterval(instance._id);

				instance._id = null;

				instance._fn.apply(instance._scope, instance._args || []);
			}
		};
	};

	DelayedTask.prototype = {
		delay: function(delay, newFn, newScope, newArgs) {
			var instance = this;

			if (instance._id && instance._delay != delay) {
				instance.cancel();
			}

			instance._delay = delay || instance._delay;
			instance._time = instance._getTime();

			instance._fn = newFn || instance._fn;
			instance._scope = newScope || instance._scope;
			instance._args = newArgs || instance._args;

			if (!A.Lang.isArray(instance._args)) {
				instance._args = [instance._args];
			}

			if (!instance._id) {
				if (instance._delay > 0) {
					instance._id = setInterval(instance._base, instance._delay);
				}
				else {
					instance._base();
				}
			}
		},

		cancel: function() {
			var instance = this;

			if (instance._id) {
				clearInterval(instance._id);

				instance._id = null;
			}
		},

		_getTime: function() {
			var instance = this;

			return (+new Date());
		}
	};

	A.DelayedTask = DelayedTask;

}, '@VERSION', { requires: [ 'yui-base' ] });

/*
* AUI Node
*/

AUI.add('aui-node', function(A) {

	var Lang = A.Lang,
		isString = Lang.isString,
		isUndefined = Lang.isUndefined,

		INNER_HTML = 'innerHTML';

	A.mix(A.Node.prototype, {
		after: function(content) {
			var instance = this;

			return instance.insertAfter(content);
		},

		appendTo: function(selector) {
			var instance = this;

			A.get(selector).append(instance);
		},

		attr: function(name, value) {
			var instance = this;

			if (!isUndefined(value)) {
				return instance.setAttribute(name, value);
			}
			else {
				return instance.getAttribute(name);
			}
		},

		before: function(content) {
			var instance = this;

			var parent = instance.get('parentNode');

			if (parent) {
				parent.insertBefore(content, instance);
			}

			return instance;
		},

		empty: function() {
			var instance = this;

			instance.queryAll('>*').remove();

			var el = A.Node.getDOMNode(instance);

			while (el.firstChild) {
				el.removeChild(el.firstChild);
			}

			return instance;
		},

		getDOM: function() {
			var instance = this;

			return A.Node.getDOMNode(instance);
		},

		html: function() {
			var args = arguments, length = args.length;

			if (length) {
				this.set(INNER_HTML, args[0]);
			}
			else {
				return this.get(INNER_HTML);
			}

			return this;
		},

		insertAfter: function(content) {
			var instance = this;

			var parent = instance.get('parentNode');

			if (parent) {
				parent.insertBefore(content, instance.get('nextSibling'));
			}

			return instance;
		},

		prependTo: function(selector) {
			var instance = this;

			A.get(selector).prepend(instance);
		},

		text: function(text) {
			var instance = this;

			if (!isUndefined(text)) {
				text = A.DOM._getDoc(A.Node.getDOMNode(instance)).createTextNode(text);

				return instance.empty().append(text);
			}

			var el = A.Node.getDOMNode(instance);

			return instance._getText(el.childNodes);
		},

		_getText: function(childNodes) {
			var instance = this;

			var length = childNodes.length;
			var childNode;

			var str = [];

			for (var i = 0; i < length; i++) {
				childNode = childNodes[i];

				if (childNode && childNode.nodeType != 8) {
					if (childNode.nodeType != 1) {
						str.push(childNode.nodeValue);
					}

					if (childNode.childNodes) {
						str.push(instance._getText(childNode.childNodes));
					}
				}
			}

			return str.join('');
		}
	}, true);

	A.mix(A.Node, {
		globalEval: function(data) {
			if ( data && /\S/.test(data) ) {
				var head = document.getElementsByTagName("head")[0] || document.documentElement;
				var script = document.createElement("script");

				script.type = "text/javascript";

				if (AUI.support.scriptEval) {
					script.appendChild(document.createTextNode(data));
				}
				else {
					script.text = data;
				}

				head.insertBefore(script, head.firstChild);
				head.removeChild(script);
			}
		},

		evalScript: function(elem) {
			if (elem.src) {
				A.io(elem.src, {
					async: false,
					on: {
						complete: function(i, o) {
							A.Node.globalEval(o.responseText);
						}
					}
				});
			}
			else {
				A.Node.globalEval(elem.text || elem.textContent || elem.innerHTML || "");
			}
		},

		clean: function(html) {
			var TPL_NODE = '

',
				IE_FIX_PADDING_NODE = '
_
',
				SCRIPT = 'script';

			// instead of fix all tags to "XHTML"-style, make the firstChild be a valid non-empty tag
			html = IE_FIX_PADDING_NODE + A.Lang.trim(html);

			delete A.DOM._cloneCache[html];

			// wrap in a nodeType == 1, nodeType 11 (document fragment) does not support getElementsByTagName
			var temp = A.Node.create(TPL_NODE).append(
				A.Node.create(html)
			);

			var scripts = temp.getElementsByTagName(SCRIPT);

			scripts.each(function(elem) {
				elem.remove();
			});

			temp.removeChild(A.Node.getDOMNode(temp).firstChild);

			var html = temp.html();

			// avoid IE6 memory leak
			temp = null;

			return [ html, scripts ];
		},

		domManip: function(html, callback) {
			var clean = A.Node.clean(html);
			var content = clean[0];
			var scripts = clean[1];

			if (callback) {
				callback.apply(this, [ content ]);
			}

			scripts.each(function(elem) {
				A.Node.evalScript( A.Node.getDOMNode(elem) );
			});
		}
	});

	A.Node.ATTRS.innerHTML = {
		setter: function(v) {
			var instance = this;

			var defaultSetter = function(value) {
				A.Node.DEFAULT_SETTER.apply(instance, [ INNER_HTML, value ]);
			};

			if (isString(v)) {
				// eval scripts
				v = A.Node.domManip(v, defaultSetter);
			}
			else {
				defaultSetter(v);
			}
		}
	};

	A.NodeList.importMethod(
		A.Node.prototype,
		[
			'after',

			'appendTo',

			'attr',

			'before',

			'empty',

			'html',

			'insertAfter',

			'prepend',

			'prependTo',

			'text'
		]
	);

	A.NodeList.prototype.getDOM = function() {
		return A.NodeList.getDOMNodes(this);
	};

}, '@VERSION', { requires: [ 'node' ] });<|endoftext|>


<commit_before>/**
 * Proudly created by ohad on 25/01/2017.
 */
const express  = require('express'),
      fs       = require('fs'),
      path     = require('path'),
      mongoose = require('mongoose'),
      Customer = require('./auth/customer'),
      Auth     = require('./auth/auth');
let app        = express();

process.env.PORT = process.env.PORT || 5000;
app.set('port', process.env.PORT);
mongoose.connect(process.env.MONGODB_URI);
mongoose.Promise = global.Promise;

const distPath = path.resolve(__dirname, '../../dist');
app.use(express.static(distPath));

app.get('/serve/?:name/?:apiKey/brain.js', (request, response) => {
  //noinspection JSUnresolvedVariable
  const requestCustomer = new Customer({
    apiKey: request.params.apiKey,
    name  : request.params.name,
    url   : (request.headers ? request.headers.referer || '' : '').toLowerCase()
  });
  Auth.auth(requestCustomer).then((actualCustomer) => {
    const brainJsPath =
            path.join(distPath, `${Auth.isDev(request) ? 'dev/' : ''}${actualCustomer.name}.js`);
    fs.exists(brainJsPath, (exists) => {
      if (exists) {
        response.sendFile(brainJsPath);
      } else {
        console.error('Bad news.. could not find brain.js at ' + brainJsPath);
        response.status(500);
        response.type('txt').send('');
      }
    })
  }).catch((error) => {
    if (error) {
      console.error(`Failed to authenticate ${requestCustomer.name} (${requestCustomer.apiKey}) ` +
                    `because ${error.toString()}`);
    } else {
      response.status(403);
      response.type('txt').send('');
    }
  });
});

app.get('*', function (request, response) {
  response.status(404);
  response.type('txt').send('');
});

app.listen(app.get('port'), function () {
  console.log('BrainPal is running on port', app.get('port'));
});

module.exports = app;
<commit_msg>dev serving<commit_after>/**
 * Proudly created by ohad on 25/01/2017.
 */
const express  = require('express'),
      fs       = require('fs'),
      path     = require('path'),
      mongoose = require('mongoose'),
      Customer = require('./auth/customer'),
      Auth     = require('./auth/auth');
let app        = express();

process.env.PORT = process.env.PORT || 5000;
app.set('port', process.env.PORT);
mongoose.connect(process.env.MONGODB_URI);
mongoose.Promise = global.Promise;

const distPath = path.resolve(__dirname, '../../dist');
app.use(express.static(distPath));
console.log('Using static resources at ' + distPath);

app.get('/serve/?:name/?:apiKey/brain.js', (request, response) => {
  //noinspection JSUnresolvedVariable
  const requestCustomer = new Customer({
    apiKey: request.params.apiKey,
    name  : request.params.name,
    url   : (request.headers ? request.headers.referer || '' : '').toLowerCase()
  });
  Auth.auth(requestCustomer).then((actualCustomer) => {
    const brainJsPath =
            path.join(distPath, `${Auth.isDev(request) ? 'dev/' : ''}${actualCustomer.name}.js`);
    fs.exists(brainJsPath, (exists) => {
      if (exists) {
        response.sendFile(brainJsPath);
      } else {
        console.error('Bad news.. could not find brain.js at ' + brainJsPath);
        response.status(500);
        response.type('txt').send('');
      }
    })
  }).catch((error) => {
    if (error) {
      console.error(`Failed to authenticate ${requestCustomer.name} (${requestCustomer.apiKey}) ` +
                    `because ${error.toString()}`);
    } else {
      response.status(403);
      response.type('txt').send('');
    }
  });
});

app.get('*', function (request, response) {
  response.status(404);
  response.type('txt').send('');
});

app.listen(app.get('port'), function () {
  console.log('BrainPal is running on port', app.get('port'));
});

module.exports = app;
<|endoftext|>


<commit_before>/**
 * Created by mcellmi on 30/08/2016.
 */

'use strict';

// Add configuration management
const   fs      = require('fs'),
        path    = require('path'),
        nconf   = require('nconf'),
        _       = require('lodash');

// Create a main logging instance which can be used to co-ordinate logging
// across all modules
const   bunyan          = require('bunyan'),
        PrettyStream    = require('bunyan-prettystream'),
        prettyStdOut    = new PrettyStream();
prettyStdOut.pipe(process.stdout);

nconf.argv().env().file({file: './config/configuration.json'});

const   log             = bunyan.createLogger({
                            name: nconf.get('log:name'),
                            serializers: {
                                reason: bunyan.stdSerializers.err
                            },
                            streams: [{
                                level: nconf.get('log:logLevel'),
                                type: 'raw',
                                stream: prettyStdOut
                            }]
                        });

const Graph = require('../src/graph');
const Search = require('../src/graphSearch');

var express = require('express');
var app = express();
var bodyParser = require('body-parser');

// Create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })

app.use(express.static('public'));

let graph = new Graph({
        log: log,
        dataFile: nconf.get('data:file'),
        maxDepth: nconf.get('search:maxDepth'),
        firstHitOnly: nconf.get('search:firstHitOnly')
    });

graph.readData()
    .then((result) => {

        let search = new Search(graph,{log: log});

        app.get('/index.html', function (req, res) {
            res.sendFile( __dirname + "/" + "index.html" );
        })
        app.get('/bundle.js', function (req, res) {
            res.sendFile( __dirname + "/" + "bundle.js" );
        })

        app.get('/search', function (req, res) {

            // Prepare output in JSON format
            let searchConditions = {
                source:req.query.source,
                destination:req.query.destination,
                searchType:"shortestPath"
            };
            let results = search.getPaths(searchConditions);
            let response = "";
            for (let x = 0; x < results.length; ++x) {
                response = _.join(results[x], "->") + "
";
            }
            console.log(response);
            res.end(JSON.stringify(results));
        })

        app.get('/searchAll', function (req, res) {
            let results = search.revealContacts(req.query.source);

            let numberOfPaths = (_.isArray(results)) ? results.length : 0;
            let response = {numPaths:numberOfPaths, paths:[]};

            if (numberOfPaths > 20){
                numberOfPaths = 20; // max limit
            }

            for (let x = 0; x < numberOfPaths; ++x) {
                response.paths.push(results[x]);
            }
            console.log(response);
            res.end(JSON.stringify(response));
        })

        var server = app.listen(8081, function () {

            var host = server.address().address
            var port = server.address().port

            console.log("Example app listening at http://%s:%s", host, port)

        })

        //
        //
        // search.getPaths({source:"DOUG_BARTOLOMEO", destination:"*"});
        //
        // search.revealContacts("DOUG_BARTOLOMEO");
        //
        // let results = search.getPaths({source:"DOUG_BARTOLOMEO", destination:"JOSPEH_MONTUORI", searchType:"shortestPath"});
        //
        // for (let x = 0; x < results.length; ++x) {
        //     console.log(_.join(results[x],"->"));
        // }
    })
    .catch((error) => {
        log.error(error);
    });

<commit_msg>Added route for node count<commit_after>/**
 * Created by mcellmi on 30/08/2016.
 */

'use strict';

// Add configuration management
const   fs      = require('fs'),
        path    = require('path'),
        nconf   = require('nconf'),
        _       = require('lodash');

// Create a main logging instance which can be used to co-ordinate logging
// across all modules
const   bunyan          = require('bunyan'),
        PrettyStream    = require('bunyan-prettystream'),
        prettyStdOut    = new PrettyStream();
prettyStdOut.pipe(process.stdout);

nconf.argv().env().file({file: './config/configuration.json'});

const   log             = bunyan.createLogger({
                            name: nconf.get('log:name'),
                            serializers: {
                                reason: bunyan.stdSerializers.err
                            },
                            streams: [{
                                level: nconf.get('log:logLevel'),
                                type: 'raw',
                                stream: prettyStdOut
                            }]
                        });

const Graph = require('../src/graph');
const Search = require('../src/graphSearch');

var express = require('express');
var app = express();

app.use(express.static('public'));
app.use(express.static('coverage'));

let graph = new Graph({
        log: log,
        dataFile: nconf.get('data:file'),
        maxDepth: nconf.get('search:maxDepth'),
        firstHitOnly: nconf.get('search:firstHitOnly')
    });

graph.readData()
    .then((result) => {

        let search = new Search(graph,{log: log});

        app.get('/index.html', function (req, res) {
            res.sendFile( __dirname + "/" + "index.html" );
        })
        app.get('/bundle.js', function (req, res) {
            res.sendFile( __dirname + "/" + "bundle.js" );
        })

        app.get('/nodeCount', function (req, res) {
            res.end(JSON.stringify(graph.getNodeCount()));
        })

        app.get('/search', function (req, res) {

            // Prepare output in JSON format
            let searchConditions = {
                source:req.query.source,
                destination:req.query.destination,
                searchType:"shortestPath"
            };
            let results = search.getPaths(searchConditions);
            let response = "";
            for (let x = 0; x < results.length; ++x) {
                response = _.join(results[x], "->") + "
";
            }
            console.log(response);
            res.end(JSON.stringify(results));
        })

        app.get('/searchAll', function (req, res) {
            let results = search.revealContacts(req.query.source);

            let numberOfPaths = (_.isArray(results)) ? results.length : 0;
            let response = {numPaths:numberOfPaths, paths:[]};

            if (numberOfPaths > 20){
                numberOfPaths = 20; // max limit
            }

            for (let x = 0; x < numberOfPaths; ++x) {
                response.paths.push(results[x]);
            }
            console.log(response);
            res.end(JSON.stringify(response));
        })

        var server = app.listen(8081, function () {

            var host = server.address().address
            var port = server.address().port

            console.log("Example app listening at http://%s:%s", host, port)

        })

        //
        //
        // search.getPaths({source:"DOUG_BARTOLOMEO", destination:"*"});
        //
        // search.revealContacts("DOUG_BARTOLOMEO");
        //
        // let results = search.getPaths({source:"DOUG_BARTOLOMEO", destination:"JOSPEH_MONTUORI", searchType:"shortestPath"});
        //
        // for (let x = 0; x < results.length; ++x) {
        //     console.log(_.join(results[x],"->"));
        // }
    })
    .catch((error) => {
        log.error(error);
    });

<|endoftext|>


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

module.exports = ErrorHandler;

function ErrorHandler(type, msg) {
    Error.call(this);

    var i = 1;

    // Write our opts to the object
    this.message = msg;
    this.name = type;

    if(arguments.length === 1) {
        this.name = 'WebdriverJSError';
        this.message = type;
        i = 0;
    }

    if(typeof this.message === 'object') {

        var seleniumStack = this.message;
        this.message = [];

        if(seleniumStack.message && seleniumStack.type && seleniumStack.status) {
            this.message.push(pad('', 6) + '(' + seleniumStack.type + ':' + seleniumStack.status + ') ' + seleniumStack.message);
        }

        if(seleniumStack.orgStatusMessage) {
            var reqPos = seleniumStack.orgStatusMessage.indexOf(',"request"'),
                problem;

            if(reqPos > 0) {
                problem = JSON.parse(seleniumStack.orgStatusMessage.slice(0,reqPos) + '}').errorMessage;
            } else {
                problem = seleniumStack.orgStatusMessage;
            }

            // truncate errorMessage
            if(problem.indexOf('(Session info:')) {
                problem = problem.slice(0,problem.indexOf('(Session info:')).replace(/\n/g,'').trim();
            }

            // make assumption based on experience on certain error messages
            if(problem.indexOf('unknown error: path is not absolute') !== -1) {
                problem = 'you are trying to set a value to an input field with type="file", use the `uploadFile` command instead (Selenium error: ' + problem + ')';
            }

            this.message.push(pad('', 6) + 'Problem: ' + problem);
        }

        this.message = this.name + '\n' + this.message.join('\n');

    } else {
        this.message = this.name + '\n' + pad('', 6) + 'Problem: ' + this.message;
    }

}

util.inherits(ErrorHandler, Error);

/**
 * make stack loggable
 * @return {Object} error log
 */
ErrorHandler.prototype.toJSON = function() {
    return {
        name: this.name,
        message: this.message
    };
};

ErrorHandler.prototype.addToCallStack = function(cmd) {
    if(!this.hasCallStack) {
        this.message += '\x1b[1;30m\n\n' + pad('', 6) + 'Callstack:\n';
        this.hasCallStack = true;
    }

    this.message += pad('-> ', 9) + cmd.name + cmd.args + '\n';
};

ErrorHandler.CommandError = function(msg) {
    return new ErrorHandler('CommandError',msg);
};
ErrorHandler.ProtocolError = function(msg) {
    return new ErrorHandler('ProtocolError',msg);
};
ErrorHandler.RuntimeError = function(msg) {
    return new ErrorHandler('RuntimeError',msg);
};

function pad(str, width) {
    return Array(width - str.length).join(' ') + str;
}<commit_msg>fixed indexOf statement<commit_after>var util = require('util');

module.exports = ErrorHandler;

function ErrorHandler(type, msg) {
    Error.call(this);

    var i = 1;

    // Write our opts to the object
    this.message = msg;
    this.name = type;

    if(arguments.length === 1) {
        this.name = 'WebdriverJSError';
        this.message = type;
        i = 0;
    }

    if(typeof this.message === 'object') {

        var seleniumStack = this.message;
        this.message = [];

        if(seleniumStack.message && seleniumStack.type && seleniumStack.status) {
            this.message.push(pad('', 6) + '(' + seleniumStack.type + ':' + seleniumStack.status + ') ' + seleniumStack.message);
        }

        if(seleniumStack.orgStatusMessage) {
            var reqPos = seleniumStack.orgStatusMessage.indexOf(',"request"'),
                problem;

            if(reqPos > 0) {
                problem = JSON.parse(seleniumStack.orgStatusMessage.slice(0,reqPos) + '}').errorMessage;
            } else {
                problem = seleniumStack.orgStatusMessage;
            }

            // truncate errorMessage
            if(problem.indexOf('(Session info:') > -1) {
                problem = problem.slice(0,problem.indexOf('(Session info:')).replace(/\n/g,'').trim();
            }

            // make assumption based on experience on certain error messages
            if(problem.indexOf('unknown error: path is not absolute') !== -1) {
                problem = 'you are trying to set a value to an input field with type="file", use the `uploadFile` command instead (Selenium error: ' + problem + ')';
            }

            this.message.push(pad('', 6) + 'Problem: ' + problem);
        }

        this.message = this.name + '\n' + this.message.join('\n');

    } else {
        this.message = this.name + '\n' + pad('', 6) + 'Problem: ' + this.message;
    }

}

util.inherits(ErrorHandler, Error);

/**
 * make stack loggable
 * @return {Object} error log
 */
ErrorHandler.prototype.toJSON = function() {
    return {
        name: this.name,
        message: this.message
    };
};

ErrorHandler.prototype.addToCallStack = function(cmd) {
    if(!this.hasCallStack) {
        this.message += '\x1b[1;30m\n\n' + pad('', 6) + 'Callstack:\n';
        this.hasCallStack = true;
    }

    this.message += pad('-> ', 9) + cmd.name + cmd.args + '\n';
};

ErrorHandler.CommandError = function(msg) {
    return new ErrorHandler('CommandError',msg);
};
ErrorHandler.ProtocolError = function(msg) {
    return new ErrorHandler('ProtocolError',msg);
};
ErrorHandler.RuntimeError = function(msg) {
    return new ErrorHandler('RuntimeError',msg);
};

function pad(str, width) {
    return Array(width - str.length).join(' ') + str;
}<|endoftext|>