<commit_before>var hbs = require('express-hbs');
var fs = require('fs');
var slideshows = require('./slideshows.json');

/***
Articles should have a directory defined in slideshows.json or we check for a
directory with the same name as the articleId.
If the file "sprite.jpg" exists in the slideshow directory, it will be used to
make the pagination thumbnails.
***/
registerHelper = function (){
    hbs.registerHelper("slideshow", function(articleId) {
        if (slideshows.articles && slideshows.articles[articleId] &&
            slideshows.articles[articleId].imgDir) {
            var dir = slideshows.rootDir + slideshows.articles[articleId].imgDir;
            var urlPath = slideshows.urlPath + slideshows.articles[articleId].imgDir;
        } else {
            var dir = slideshows.rootDir + articleId + "/";
            var urlPath = slideshows.urlPath + articleId + "/";
        }

        if (!fs.existsSync(dir)) {
            return new hbs.SafeString(' ');
        }

        var dirList = fs.readdirSync(dir);
        if (fs.existsSync(dir + "sprite.jpg")) {
            var out = '
';
        } else {
            var out = '
';
        }
        out += '
\n';
        out += '
\n';
        out += '\n';
        out += '
\n';
        for(var i=1, l=dirList.length; i<l; i++) {
            out += '
\n';
            out += '\n';
            out += '
\n';
        }
        return new hbs.SafeString(out + '
\n
\n');
    });
}

module.exports = registerHelper;
<commit_msg>Make sure not to print directories in slideshow list.<commit_after>var hbs = require('express-hbs');
var fs = require('fs');
var slideshows = require('./slideshows.json');

/***
Articles should have a directory defined in slideshows.json or we check for a
directory with the same name as the articleId.
If the file "sprite.jpg" exists in the slideshow directory, it will be used to
make the pagination thumbnails.
***/
registerHelper = function (){
    hbs.registerHelper("slideshow", function(articleId) {
        if (slideshows.articles && slideshows.articles[articleId] &&
            slideshows.articles[articleId].imgDir) {
            var dir = slideshows.rootDir + slideshows.articles[articleId].imgDir;
            var urlPath = slideshows.urlPath + slideshows.articles[articleId].imgDir;
        } else {
            var dir = slideshows.rootDir + articleId + "/";
            var urlPath = slideshows.urlPath + articleId + "/";
        }

        if (!fs.existsSync(dir)) {
            return new hbs.SafeString(' ');
        }

        var dirList = fs.readdirSync(dir);
        if (fs.existsSync(dir + "sprite.jpg")) {
            var out = '
';
        } else {
            var out = '
';
        }

        for (var i=0, l=dirList.length; i<l; i++) {
            if (fs.lstatSync(dir + dirList[i]).isDirectory()) {
                continue;
            }
            if (i == 0) {
                out += '
\n';
                out += '
\n';
                out += '\n';
                out += '
\n';

            } else {
                out += '
\n';
                out += '\n';
                out += '
\n';
            }
        }
        return new hbs.SafeString(out + '
\n
\n');
    });
}

module.exports = registerHelper;
<|endoftext|>


<commit_before>define(function () {

    function RunQuery (bezl, queryName) {

        switch (queryName) {
            case "TaskTypes":
                // Pull in the task types
                bezl.dataService.add('TaskTypes','brdb','sales-rep-queries','ExecuteQuery', {
                    "QueryName": "GetTaskTypes",
                    "Parameters": [
                        { "Key": "EmailAddress", "Value": bezl.env.currentUser }
                    ] },0);
                break;
            case "Tasks":
                bezl.vars.loading = true;

                // Pull in the accounts list for the logged in user
                bezl.dataService.add('Tasks','brdb','sales-rep-queries','ExecuteQuery', {
                    "QueryName": "GetAccountTasks",
                    "Parameters": [
                        { "Key": "EmailAddress", "Value": bezl.env.currentUser },
                        { "Key": "ID", "Value": bezl.vars.selectedAccount.ID }
                    ] },0);
                break;
            default:
                break;
        }
    }

    function Select(bezl, task) {
        task.Selected = !task.Selected;
    }

    function AddTask (bezl) {
        // Since alternate systems may require different columns for newly added tasks, direct to
        // the libraries folder
        if (bezl.vars.Platform == "Epicor10" || bezl.vars.Platform == "Epicor905") {
            require(['https://cdn.rawgit.com/bezlio/bezlio-apps/1.6/libraries/epicor/crm.js'], function(functions) {
                var taskType = '';
                if (bezl.data.TaskTypes) {
                    taskType = bezl.data.TaskTypes[0].TaskType;
                }

                bezl.vars.selectedAccount.Tasks.push(
                    functions.getNewTask(bezl.vars.selectedAccount.CustNum,
                                        bezl.vars.selectedAccount.SalesRep,
                                        taskType)
                );

                // Order the added tasks to the top
                bezl.vars.selectedAccount.Tasks.sort(function(a, b) {
                    if (a.RowState && a.RowState == 'Added') {
                        return -1;
                    } else {
                        return 1;
                    }
                });
            });
        }
    }

    function CancelAddTask (bezl, task) {
        for (var i = 0; i < bezl.vars.selectedAccount.Tasks.length; i++) {
            if (bezl.vars.selectedAccount.Tasks[i] == task) {
                bezl.vars.selectedAccount.Tasks.splice(i, 1);
            }
        }
    }

    function UpdateTasks (bezl) {
        // Since alternate systems may require different columns for newly added tasks, direct to
        // the libraries folder
        if (bezl.vars.Platform == "Epicor10" || bezl.vars.Platform == "Epicor905") {
            require(['https://cdn.rawgit.com/bezlio/bezlio-apps/1.6/libraries/epicor/crm.js'], function(functions) {
                functions.updateTasks(bezl,
                                        bezl.vars.selectedAccount.Tasks);

                bezl.notificationService.showSuccess('Task changes are being saved.  You will be notified if any errors occurs.');
            });
        }

        localStorage.setItem('selectedAccount', JSON.stringify(bezl.vars.selectedAccount));
    }

    return {
        runQuery: RunQuery,
        select: Select,
        addTask: AddTask,
        cancelAddTask: CancelAddTask,
        updateTasks: UpdateTasks
    }
});
<commit_msg>Because we removed an item in the array we are itterating over we need to decrement our current index by one.<commit_after>define(function () {

    function RunQuery (bezl, queryName) {

        switch (queryName) {
            case "TaskTypes":
                // Pull in the task types
                bezl.dataService.add('TaskTypes','brdb','sales-rep-queries','ExecuteQuery', {
                    "QueryName": "GetTaskTypes",
                    "Parameters": [
                        { "Key": "EmailAddress", "Value": bezl.env.currentUser }
                    ] },0);
                break;
            case "Tasks":
                bezl.vars.loading = true;

                // Pull in the accounts list for the logged in user
                bezl.dataService.add('Tasks','brdb','sales-rep-queries','ExecuteQuery', {
                    "QueryName": "GetAccountTasks",
                    "Parameters": [
                        { "Key": "EmailAddress", "Value": bezl.env.currentUser },
                        { "Key": "ID", "Value": bezl.vars.selectedAccount.ID }
                    ] },0);
                break;
            default:
                break;
        }
    }

    function Select(bezl, task) {
        task.Selected = !task.Selected;
    }

    function AddTask (bezl) {
        // Since alternate systems may require different columns for newly added tasks, direct to
        // the libraries folder
        if (bezl.vars.Platform == "Epicor10" || bezl.vars.Platform == "Epicor905") {
            require(['https://cdn.rawgit.com/bezlio/bezlio-apps/1.6/libraries/epicor/crm.js'], function(functions) {
                var taskType = '';
                if (bezl.data.TaskTypes) {
                    taskType = bezl.data.TaskTypes[0].TaskType;
                }

                bezl.vars.selectedAccount.Tasks.push(
                    functions.getNewTask(bezl.vars.selectedAccount.CustNum,
                                        bezl.vars.selectedAccount.SalesRep,
                                        taskType)
                );

                // Order the added tasks to the top
                bezl.vars.selectedAccount.Tasks.sort(function(a, b) {
                    if (a.RowState && a.RowState == 'Added') {
                        return -1;
                    } else {
                        return 1;
                    }
                });
            });
        }
    }

    function CancelAddTask (bezl, task) {
        for (var i = 0; i < bezl.vars.selectedAccount.Tasks.length; i++) {
            if (bezl.vars.selectedAccount.Tasks[i] == task) {
                bezl.vars.selectedAccount.Tasks.splice(i, 1);
                // Because we removed an item in the array we are iterating
                // over we need to decrement our current index by one
                i--;
            }
        }
    }

    function UpdateTasks (bezl) {
        // Since alternate systems may require different columns for newly added tasks, direct to
        // the libraries folder
        if (bezl.vars.Platform == "Epicor10" || bezl.vars.Platform == "Epicor905") {
            require(['https://cdn.rawgit.com/bezlio/bezlio-apps/1.6/libraries/epicor/crm.js'], function(functions) {
                functions.updateTasks(bezl,
                                        bezl.vars.selectedAccount.Tasks);

                bezl.notificationService.showSuccess('Task changes are being saved.  You will be notified if any errors occurs.');
            });
        }

        localStorage.setItem('selectedAccount', JSON.stringify(bezl.vars.selectedAccount));
    }

    return {
        runQuery: RunQuery,
        select: Select,
        addTask: AddTask,
        cancelAddTask: CancelAddTask,
        updateTasks: UpdateTasks
    }
});
<|endoftext|>


<commit_before>(function () {
  'use strict';

  angular
    .module('openSenseMapApp')
    .controller('EditBoxLocationController', EditBoxLocationController);

  EditBoxLocationController.$inject = ['$scope', 'boxData', 'notifications', 'AccountService'];

  function EditBoxLocationController ($scope, boxData, notifications, AccountService) {
    var vm = this;
    vm.editMarkerInput = {};
    vm.originalPosition = {};

    vm.save = save;
    vm.resetPosition = resetPosition;

    activate();

    ////

    function activate () {
      vm.boxPosition = {
        lng: parseFloat(boxData.currentLocation.coordinates[0].toFixed(6)),
        lat: parseFloat(boxData.currentLocation.coordinates[1].toFixed(6)),
        height: boxData.currentLocation.coordinates[2],
        draggable: true,
        zoom: 17,
        icon: {
          markerColor: 'green'
        }
      };

      angular.copy(vm.boxPosition, vm.originalPosition);

      vm.editMarker = {
        m1: angular.copy(vm.boxPosition)
      };
      angular.copy(vm.boxPosition, vm.editMarkerInput);
    }

    function save () {
      return AccountService.updateBox(boxData._id, {location: vm.editMarker.m1})
        .then(function (response) {
          angular.copy(response.data, boxData);
          notifications.addAlert('info', 'NOTIFICATION_BOX_UPDATE_SUCCESS');
        })
        .catch(function (error) {
          notifications.addAlert('danger', 'NOTIFICATION_BOX_UPDATE_FAILED');
        });
    }

    function resetPosition () {
      vm.editMarker = { m1: angular.copy(vm.originalPosition) };
      vm.editMarkerInput =  angular.copy(vm.originalPosition);
      vm.editMarker.m1.draggable = true;
    }

    function setCoordinates (coords) {
      vm.editMarker = {
        m1 : angular.copy(vm.originalPosition)
      };
      vm.editMarker.m1.lng = parseFloat(coords.lng.toFixed(6));
      vm.editMarker.m1.lat = parseFloat(coords.lat.toFixed(6));
      vm.editMarker.m1.height = coords.height;
      vm.editMarkerInput.lng = vm.editMarker.m1.lng;
      vm.editMarkerInput.lat = vm.editMarker.m1.lat;
    }

    ////

    $scope.$on('osemMapClick.map_edit', function (e, args) {
      setCoordinates(args.latlng);
    });

    $scope.$on('osemMarkerDragend.map_edit', function (e, args) {
      setCoordinates(args.target._latlng);
    });

    $scope.$watchCollection('location.editMarkerInput', function (newValue) {
      if (newValue && newValue.lat && newValue.lng) {
        setCoordinates({
          lng: newValue.lng,
          lat: newValue.lat,
          height: newValue.height,
        });
      }
    });
  }
})();
<commit_msg>fix(edit): fix marker in editing<commit_after>(function () {
  'use strict';

  angular
    .module('openSenseMapApp')
    .controller('EditBoxLocationController', EditBoxLocationController);

  EditBoxLocationController.$inject = ['$scope', 'boxData', 'notifications', 'AccountService'];

  function EditBoxLocationController ($scope, boxData, notifications, AccountService) {
    var vm = this;
    vm.editMarkerInput = {};
    vm.originalPosition = {};

    vm.save = save;
    vm.resetPosition = resetPosition;

    activate();

    ////

    function activate () {
      if (boxData.exposure === 'indoor' || boxData.exposure === 'outdoor') {
        var icon = 'cube';
        var color = 'green';
      }

      if (boxData.exposure === 'mobile') {
        var icon = 'rocket';
        var color = 'blue';
      }

      var icon = L.AwesomeMarkers.icon({
        type: 'awesomeMarker',
        prefix: 'fa',
        icon: icon,
        markerColor: color
      });

      var lat = parseFloat(boxData.currentLocation.coordinates[1].toFixed(6));
      var lng = parseFloat(boxData.currentLocation.coordinates[0].toFixed(6));

      vm.boxPosition = {
        layerName: 'registration',
        lng: lng,
        lat: lat,
        latLng: [lat, lng],
        height: boxData.currentLocation.coordinates[2],
        draggable: true,
        zoom: 17,
        icon: icon
      };

      angular.copy(vm.boxPosition, vm.originalPosition);

      vm.editMarker = {
        m1: angular.copy(vm.boxPosition)
      };
      angular.copy(vm.boxPosition, vm.editMarkerInput);
    }

    function save () {
      return AccountService.updateBox(boxData._id, {location: vm.editMarker.m1})
        .then(function (response) {
          angular.copy(response.data, boxData);
          notifications.addAlert('info', 'NOTIFICATION_BOX_UPDATE_SUCCESS');
        })
        .catch(function (error) {
          notifications.addAlert('danger', 'NOTIFICATION_BOX_UPDATE_FAILED');
        });
    }

    function resetPosition () {
      vm.editMarker = { m1: angular.copy(vm.originalPosition) };
      vm.editMarkerInput =  angular.copy(vm.originalPosition);
      vm.editMarker.m1.draggable = true;
    }

    function setCoordinates (coords) {
      vm.editMarker = {
        m1 : angular.copy(vm.originalPosition)
      };
      var lng = parseFloat(coords.lng.toFixed(6));
      var lat = parseFloat(coords.lat.toFixed(6));
      vm.editMarker.m1.lng = lng;
      vm.editMarker.m1.lat = lat;
      vm.editMarker.m1.latLng = [lat, lng];
      vm.editMarker.m1.height = coords.height;
      vm.editMarkerInput.lng = vm.editMarker.m1.lng;
      vm.editMarkerInput.lat = vm.editMarker.m1.lat;
    }

    ////

    $scope.$on('osemMapClick.map_edit', function (e, args) {
      setCoordinates(args.latlng);
    });

    $scope.$on('osemMarkerDragend.map_edit', function (e, args) {
      setCoordinates(args.target._latlng);
    });

    $scope.$watchCollection('location.editMarkerInput', function (newValue) {
      if (newValue && newValue.lat && newValue.lng) {
        setCoordinates({
          lng: newValue.lng,
          lat: newValue.lat,
          height: newValue.height,
        });
      }
    });
  }
})();
<|endoftext|>


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

  var PI2 = 2 * Math.PI;

  var canvas, context;

  // Formations coordinates array.
  var formations = [];
  var formation = [];

  var config = {
    // Unit count.
    count: 10,
    spacing: {
      rank: 10,
      file: 20
    }
  };

  /*
    Three states for drawing a formation:

             <--  1. RANK  -->       ^
      ^      [] [] [] [] [] []       |
      |      [] [] [] [] [] []       |
    2. FILE  [] [] [] [] [] []       |
      |      [] [] [] [] [] []       |
      v      [] [] [] [] [] []  3. DIRECTION

      A rank is horizontal and a file is vertical. In the above diagram,
      the formation is 5 ranks deep and 6 files wide.
   */

  var State = {
    RANK: 0,
    FILE: 1,
    DIRECTION: 2
  };

  var state = State.RANK;

  var mouse = {
    x: 0,
    y: 0,

    // Initial points.
    xi: 0,
    yi: 0,

    down: false
  };

  function Formation( x0, y0, x1, y1, x2, y2 ) {
    this.x0 = x0;
    this.y0 = y0;
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;

    // First edge (width).
    var dx = x1 - x0,
        dy = y1 - y0;

    this.angle = Math.atan2( -dy, dx );
    this.width = Math.sqrt( dx * dx + dy * dy );

    // Second edge (height).
    var point = this.toLocal( x2 - x1, y2 - y1 );
    this.height = point.y;

    Object.freeze( this );
  }

  Formation.prototype.toWorld = function( x, y ) {
    var cos, sin;
    var rx, ry;

    if ( this.angle ) {
      cos = Math.cos( -this.angle );
      sin = Math.sin( -this.angle );

      rx = cos * x - sin * y;
      ry = sin * x + cos * y;

      x = rx;
      y = ry;
    }

    return {
      x: x + this.x0,
      y: y + this.y0
    };
  };

  Formation.prototype.toLocal = function( x, y ) {
    x -= this.x0;
    y -= this.y0;

    var cos, sin;
    var rx, ry;

    if ( this.angle ) {
      cos = Math.cos( this.angle );
      sin = Math.sin( this.angle );

      rx = cos * x - sin * y;
      ry = sin * x + cos * y;

      x = rx;
      y = ry;
    }

    return {
      x: x,
      y: y
    };
  };

  function drawRectFromPoints( ctx, x0, y0, x1, y1, x2, y2 ) {
    // First edge (width).
    var dx0 = x1 - x0,
        dy0 = y1 - y0;

    var angle = Math.atan2( -dy0, dx0 );
    var width = Math.sqrt( dx0 * dx0 + dy0 * dy0 );

    // Second edge (height).
    var dx1 = x2 - x1,
        dy1 = y2 - y1;

    var cos, sin;
    var rx, ry;
    if ( angle ) {
      cos = Math.cos( angle );
      sin = Math.sin( angle );

      rx = cos * dx1 - sin * dy1;
      ry = sin * dx1 + cos * dy1;

      dx1 = rx;
      dy1 = ry;
    }

    ctx.save();

    ctx.translate( x0, y0 );
    ctx.rotate( -angle );

    ctx.beginPath();
    ctx.rect( 0, 0, width, dy1 );

    ctx.restore();
  }

  function draw( ctx ) {
    ctx.clearRect( 0, 0, ctx.canvas.width, ctx.canvas.height );

    ctx.lineWidth = 1;
    ctx.strokeStyle = '#fff';
    ctx.fillStyle = '#fff';
    ctx.font = '16pt "Helvetica Neue", Helvetica, Arial, sans-serif';

    // Mouse.
    ctx.beginPath();
    ctx.arc( mouse.x, mouse.y, 10, 0, PI2 );
    ctx.stroke();

    // Formations.
    formations.forEach(function( formation ) {
      var x0 = formation[0][0],
          y0 = formation[0][1],
          x1 = formation[1][0],
          y1 = formation[1][1],
          x2 = formation[2][0],
          y2 = formation[2][1];

      drawRectFromPoints( ctx, x0, y0, x1, y1, x2, y2 );
      ctx.stroke();
    });

    var x0, y0,
        x1, y1,
        x2, y2;
    if ( formation.length ) {
      x0 = formation[0][0];
      y0 = formation[0][1];
      x1 = formation[1][0];
      y1 = formation[1][1];

      if ( formation.length > 2 ) {
        x2 = formation[2][0];
        y2 = formation[2][1];
      }

      var dx = x1 - x0,
          dy = y1 - y0;

      var angle = Math.atan2( -dy, dx );
      ctx.fillText( Math.round( angle * 180 / Math.PI ), 300, 40 );
    }

    if ( mouse.down && state === State.RANK ) {
      ctx.beginPath();
      ctx.moveTo( mouse.xi, mouse.yi );
      ctx.lineTo( mouse.x, mouse.y );
      ctx.stroke();
    } else if ( state === State.FILE ) {
      drawRectFromPoints( ctx, x0, y0, x1, y1, mouse.x, mouse.y );
      ctx.stroke();
    } else if ( state === State.DIRECTION ) {
      drawRectFromPoints( ctx, x0, y0, x1, y1, x2, y2 );
      ctx.moveTo( x0, y0 );
      ctx.lineTo( mouse.x, mouse.y );
      ctx.moveTo( x1, y1 );
      ctx.lineTo( mouse.x, mouse.y );
      ctx.stroke();
    }
    ctx.fillText( 'state: ' + state, 32, 32 );
    ctx.fillText( config.count, 32, 72 );
  }

  (function init() {
    canvas  = document.createElement( 'canvas' );
    context = canvas.getContext( '2d' );

    document.body.appendChild( canvas );

    canvas.width  = window.innerWidth;
    canvas.height = window.innerHeight;

    function mousePosition( event ) {
      mouse.x = event.pageX - canvas.offsetLeft;
      mouse.y = event.pageY - canvas.offsetTop;
    }

    window.addEventListener( 'mousedown', function( event ) {
      mousePosition( event );
      mouse.xi = mouse.x;
      mouse.yi = mouse.y;

      mouse.down = true;

      if ( state === State.DIRECTION ) {
        formations.push( formation );
        formation = [];
        state = State.RANK;
      }
    });

    window.addEventListener( 'mousemove', function( event ) {
      mousePosition( event );
      draw( context );
    });

    window.addEventListener( 'mouseup', function() {
      mousePosition( event );
      mouse.down = false;

      if ( state === State.RANK ) {
        var dx = mouse.x - mouse.xi,
            dy = mouse.y - mouse.yi;

        if ( !dx && !dy ) {
          return;
        }

        formation = [
          [ mouse.xi, mouse.yi ],
          [ mouse.x, mouse.y ]
        ];

        state = State.FILE;
      } else if ( state === State.FILE ) {
        formation[2] = [ mouse.x, mouse.y ];
        state = State.DIRECTION;
      }
    });

    document.addEventListener( 'keydown', function( event ) {
      // Up arrow.
      if ( event.which === 38 ) {
        config.count++;
      }

      // Down arrow.
      if ( event.which === 40 ) {
        config.count = Math.max( config.count - 1, 0 );
      }

      // ESC.
      // Reset everything.
      if ( event.which === 27 ) {
        formation = [];
        state = State.RANK;
      }

      draw( context );
    });

    draw( context );
  }) ();
}) ( window, document );
<commit_msg>strategy[maneuvers]: Add Formation applyTransform() and draw() methods.<commit_after>(function( window, document, undefined ) {
  'use strict';

  var PI2 = 2 * Math.PI;

  var canvas, context;

  // Formations coordinates array.
  var formations = [];
  var formation = [];

  var config = {
    // Unit count.
    count: 10,
    spacing: {
      rank: 10,
      file: 20
    }
  };

  /*
    Three states for drawing a formation:

             <--  1. RANK  -->       ^
      ^      [] [] [] [] [] []       |
      |      [] [] [] [] [] []       |
    2. FILE  [] [] [] [] [] []       |
      |      [] [] [] [] [] []       |
      v      [] [] [] [] [] []  3. DIRECTION

      A rank is horizontal and a file is vertical. In the above diagram,
      the formation is 5 ranks deep and 6 files wide.
   */

  var State = {
    RANK: 0,
    FILE: 1,
    DIRECTION: 2
  };

  var state = State.RANK;

  var mouse = {
    x: 0,
    y: 0,

    // Initial points.
    xi: 0,
    yi: 0,

    down: false
  };

  function Formation( x0, y0, x1, y1, x2, y2 ) {
    this.x0 = x0;
    this.y0 = y0;
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;

    // First edge (width).
    var dx = x1 - x0,
        dy = y1 - y0;

    this.angle = Math.atan2( -dy, dx );
    this.width = Math.sqrt( dx * dx + dy * dy );

    // Second edge (height).
    var point = this.toLocal( x2 - x1, y2 - y1 );
    this.height = point.y;

    Object.freeze( this );
  }

  Formation.prototype.applyTransform = function( ctx ) {
    ctx.translate( this.x0, this.y0 );
    ctx.rotate( -this.angle );
  };

  Formation.prototype.draw = function( ctx ) {
    ctx.save();

    this.applyTransform();
    ctx.rect( 0, 0, this.width, this.height );

    ctx.restore();
  };

  Formation.prototype.toWorld = function( x, y ) {
    var cos, sin;
    var rx, ry;

    if ( this.angle ) {
      cos = Math.cos( -this.angle );
      sin = Math.sin( -this.angle );

      rx = cos * x - sin * y;
      ry = sin * x + cos * y;

      x = rx;
      y = ry;
    }

    return {
      x: x + this.x0,
      y: y + this.y0
    };
  };

  Formation.prototype.toLocal = function( x, y ) {
    x -= this.x0;
    y -= this.y0;

    var cos, sin;
    var rx, ry;

    if ( this.angle ) {
      cos = Math.cos( this.angle );
      sin = Math.sin( this.angle );

      rx = cos * x - sin * y;
      ry = sin * x + cos * y;

      x = rx;
      y = ry;
    }

    return {
      x: x,
      y: y
    };
  };

  function drawRectFromPoints( ctx, x0, y0, x1, y1, x2, y2 ) {
    // First edge (width).
    var dx0 = x1 - x0,
        dy0 = y1 - y0;

    var angle = Math.atan2( -dy0, dx0 );
    var width = Math.sqrt( dx0 * dx0 + dy0 * dy0 );

    // Second edge (height).
    var dx1 = x2 - x1,
        dy1 = y2 - y1;

    var cos, sin;
    var rx, ry;
    if ( angle ) {
      cos = Math.cos( angle );
      sin = Math.sin( angle );

      rx = cos * dx1 - sin * dy1;
      ry = sin * dx1 + cos * dy1;

      dx1 = rx;
      dy1 = ry;
    }

    ctx.save();

    ctx.translate( x0, y0 );
    ctx.rotate( -angle );

    ctx.beginPath();
    ctx.rect( 0, 0, width, dy1 );

    ctx.restore();
  }

  function draw( ctx ) {
    ctx.clearRect( 0, 0, ctx.canvas.width, ctx.canvas.height );

    ctx.lineWidth = 1;
    ctx.strokeStyle = '#fff';
    ctx.fillStyle = '#fff';
    ctx.font = '16pt "Helvetica Neue", Helvetica, Arial, sans-serif';

    // Mouse.
    ctx.beginPath();
    ctx.arc( mouse.x, mouse.y, 10, 0, PI2 );
    ctx.stroke();

    // Formations.
    formations.forEach(function( formation ) {
      var x0 = formation[0][0],
          y0 = formation[0][1],
          x1 = formation[1][0],
          y1 = formation[1][1],
          x2 = formation[2][0],
          y2 = formation[2][1];

      drawRectFromPoints( ctx, x0, y0, x1, y1, x2, y2 );
      ctx.stroke();
    });

    var x0, y0,
        x1, y1,
        x2, y2;
    if ( formation.length ) {
      x0 = formation[0][0];
      y0 = formation[0][1];
      x1 = formation[1][0];
      y1 = formation[1][1];

      if ( formation.length > 2 ) {
        x2 = formation[2][0];
        y2 = formation[2][1];
      }

      var dx = x1 - x0,
          dy = y1 - y0;

      var angle = Math.atan2( -dy, dx );
      ctx.fillText( Math.round( angle * 180 / Math.PI ), 300, 40 );
    }

    if ( mouse.down && state === State.RANK ) {
      ctx.beginPath();
      ctx.moveTo( mouse.xi, mouse.yi );
      ctx.lineTo( mouse.x, mouse.y );
      ctx.stroke();
    } else if ( state === State.FILE ) {
      drawRectFromPoints( ctx, x0, y0, x1, y1, mouse.x, mouse.y );
      ctx.stroke();
    } else if ( state === State.DIRECTION ) {
      drawRectFromPoints( ctx, x0, y0, x1, y1, x2, y2 );
      ctx.moveTo( x0, y0 );
      ctx.lineTo( mouse.x, mouse.y );
      ctx.moveTo( x1, y1 );
      ctx.lineTo( mouse.x, mouse.y );
      ctx.stroke();
    }
    ctx.fillText( 'state: ' + state, 32, 32 );
    ctx.fillText( config.count, 32, 72 );
  }

  (function init() {
    canvas  = document.createElement( 'canvas' );
    context = canvas.getContext( '2d' );

    document.body.appendChild( canvas );

    canvas.width  = window.innerWidth;
    canvas.height = window.innerHeight;

    function mousePosition( event ) {
      mouse.x = event.pageX - canvas.offsetLeft;
      mouse.y = event.pageY - canvas.offsetTop;
    }

    window.addEventListener( 'mousedown', function( event ) {
      mousePosition( event );
      mouse.xi = mouse.x;
      mouse.yi = mouse.y;

      mouse.down = true;

      if ( state === State.DIRECTION ) {
        formations.push( formation );
        formation = [];
        state = State.RANK;
      }
    });

    window.addEventListener( 'mousemove', function( event ) {
      mousePosition( event );
      draw( context );
    });

    window.addEventListener( 'mouseup', function() {
      mousePosition( event );
      mouse.down = false;

      if ( state === State.RANK ) {
        var dx = mouse.x - mouse.xi,
            dy = mouse.y - mouse.yi;

        if ( !dx && !dy ) {
          return;
        }

        formation = [
          [ mouse.xi, mouse.yi ],
          [ mouse.x, mouse.y ]
        ];

        state = State.FILE;
      } else if ( state === State.FILE ) {
        formation[2] = [ mouse.x, mouse.y ];
        state = State.DIRECTION;
      }
    });

    document.addEventListener( 'keydown', function( event ) {
      // Up arrow.
      if ( event.which === 38 ) {
        config.count++;
      }

      // Down arrow.
      if ( event.which === 40 ) {
        config.count = Math.max( config.count - 1, 0 );
      }

      // ESC.
      // Reset everything.
      if ( event.which === 27 ) {
        formation = [];
        state = State.RANK;
      }

      draw( context );
    });

    draw( context );
  }) ();
}) ( window, document );
<|endoftext|>


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

var http = require('http');
var $rdf = require('rdflib');
var fs = require('fs');
var forge = require('node-forge');
var BigInteger = forge.jsbn.BigInteger;

var domain = 'gitpay.org';

/*
* encrypt gets response in turtle for a given user
*
* @param {String} argv[2] key
* @param {String} argv[3] message
* @callback {bin~cb} callback
**/
function encrypt(argv, callback) {
  var key = argv[2];
  if (!key) {
    console.log('key is required');
    process.exit(-1);
  }

  var message = argv[3];
  if (!message) {
    console.log('message is required');
    process.exit(-1);
  }

  var TIMEOUT = 2000;
  var CERT  = $rdf.Namespace("http://www.w3.org/ns/auth/cert#");

  var g = $rdf.graph();
  var f = $rdf.fetcher(g, TIMEOUT);

  var url = key.split('#')[0];
  url = 'http://gitpay.org/deiu';
  f.nowOrWhenFetched(url, null, function() {
    var pub = {};
    pub.exponent = g.any($rdf.sym(key), CERT('exponent'), null,  $rdf.sym(url));
    pub.modulus = g.any($rdf.sym(key), CERT('modulus'), null,  $rdf.sym(url));
    pub.key = g.statementsMatching($rdf.sym(key), null, null,  $rdf.sym(url));
    pub.publicKey = forge.pki.setRsaPublicKey(new BigInteger(pub.modulus.value, 16), new BigInteger(pub.exponent.value));
    var buffer = forge.util.createBuffer(message, 'utf8');
    var encrypted = pub.publicKey.encrypt(buffer);
    buffer = forge.util.createBuffer(encrypted, 'utf8');
    callback(null, buffer.toHex());
  });

}

/*
* encrypt as a command
*
* @param {String} argv[2] login
* @callback {bin~cb} callback
**/

function bin(argv) {
  encrypt(argv, function(err, res) {
    console.log(res);
  });
}

// If one import this file, this is a module, otherwise a library
if (require.main === module) {
  bin(process.argv);
}

module.exports = encrypt;
<commit_msg>bugfix<commit_after>#!/usr/bin/env node

var http = require('http');
var $rdf = require('rdflib');
var fs = require('fs');
var forge = require('node-forge');
var BigInteger = forge.jsbn.BigInteger;

var domain = 'gitpay.org';

/*
* encrypt gets response in turtle for a given user
*
* @param {String} argv[2] key
* @param {String} argv[3] message
* @callback {bin~cb} callback
**/
function encrypt(argv, callback) {
  var key = argv[2];
  if (!key) {
    console.log('key is required');
    process.exit(-1);
  }

  var message = argv[3];
  if (!message) {
    console.log('message is required');
    process.exit(-1);
  }

  var TIMEOUT = 2000;
  var CERT  = $rdf.Namespace("http://www.w3.org/ns/auth/cert#");

  var g = $rdf.graph();
  var f = $rdf.fetcher(g, TIMEOUT);

  var url = key.split('#')[0];
  f.nowOrWhenFetched(url, null, function() {
    var pub = {};
    pub.exponent = g.any($rdf.sym(key), CERT('exponent'), null,  $rdf.sym(url));
    pub.modulus = g.any($rdf.sym(key), CERT('modulus'), null,  $rdf.sym(url));
    pub.key = g.statementsMatching($rdf.sym(key), null, null,  $rdf.sym(url));
    pub.publicKey = forge.pki.setRsaPublicKey(new BigInteger(pub.modulus.value, 16), new BigInteger(pub.exponent.value));
    var buffer = forge.util.createBuffer(message, 'utf8');
    var encrypted = pub.publicKey.encrypt(buffer);
    buffer = forge.util.createBuffer(encrypted, 'utf8');
    callback(null, buffer.toHex());
  });

}

/*
* encrypt as a command
*
* @param {String} argv[2] login
* @callback {bin~cb} callback
**/

function bin(argv) {
  encrypt(argv, function(err, res) {
    console.log(res);
  });
}

// If one import this file, this is a module, otherwise a library
if (require.main === module) {
  bin(process.argv);
}

module.exports = encrypt;
<|endoftext|>


<commit_before>import querystring from "querystring";

/**
 *  This is the core strategy.
 *  despite the differing methods, Implicit OAuth always returns the token in a specific way in the hash fragment.
 *  we also store the token in localStorage in the same way.
 *  Therefore we can abstract those bits.
 *
 *  Also the concept of whether we are "local" i.e. in the page, or "remote", i.e.
 *  in the popup/frame/redirection process will be common, it's a bit like a "fork"
 *
 *  One branch of code is for the local, another for the remote.
 */

const createKey = clientId => key => `___${clientId}:${key}`;
const parseQuerystring = qs => querystring.parse(qs.replace(/^\?/, ""));
const parseFragment = fragment => querystring.parse(fragment.replace(/^#/, ""));
const getOrigin = (l = window.location) =>
    !l.origin
        ? l.protocol + "//" + l.hostname + (l.port ? ":" + l.port : "")
        : l.origin;
const defaultRedirectUri = () => getOrigin() + "/";

export default function createOauthStrategy(implementation) {
    return ({
        clientId,
        url: baseURL,
        redirectUri = defaultRedirectUri(),
        logoutUri,
        logoutReturnUrl,
        clearStorageOnLogout = true,
        ...options
    }) => {
        const key = createKey(clientId);
        const TOKEN_KEY = key("token");
        const token = {
            accessToken: null,
            meta: {}
        };
        const tokenIfOK = () => {
            if (token.accessToken) {
                return token;
            }
        };

        const url =
            baseURL +
            (baseURL.indexOf("?") > -1 ? "&" : "?") +
            querystring.stringify({
                client_id: clientId,
                redirect_url: redirectUri
            });

        const clear = () => window.localStorage.removeItem(TOKEN_KEY);

        const logout = tok => {
            if (clearStorageOnLogout) {
                clear();
            }
            return (
                logoutUri +
                "?" +
                querystring.stringify({
                    clientid_token: clientId + "." + tok,
                    return_url: logoutReturnUrl
                })
            );
        };

        //create our strategy for getting tokens.
        const strategy = implementation({
            clientId,
            url,
            key,
            redirectUri,
            ...options
        });

        //turns out these are useful to the consumer as well.
        const baseReturnValue = {
            clear,
            isRemote: () => strategy.isRemote(),
            isLocal: () => !strategy.isRemote()
        };

        if (strategy.isRemote()) {
            let error;
            //we are in the remote path. That means that we *SHOULD*
            //be checking for the token in the url fragment
            const frag = parseFragment(window.location.hash);
            if (frag.access_token) {
                token.accessToken = frag.access_token;
                const expiry =
                    Date.now() + parseInt(frag.expires_in, 10) * 1000;
                if (!isNaN(expiry)) {
                    token.meta.expiry = expiry;
                }
            } else {
                const {
                    error: errorType,
                    error_description: errDescription
                } = parseQuerystring(window.location.search);
                if (errorType && errDescription) {
                    token.meta.error = errDescription;
                    token.meta.errorType = errorType;
                    error = new Error(errDescription);
                    error.type = errorType;
                }
            }
            window.localStorage.setItem(TOKEN_KEY, JSON.stringify(token));

            //remote version of check.
            return Object.assign(baseReturnValue, {
                check() {
                    try {
                        strategy.callLocalCallback(error, tokenIfOK());
                    } catch (e) {
                        console.error(e);
                    }
                },
                request() {
                    //nothing to do here
                },
                logout() {
                    //nothing on remote side
                }
            });
        } else {
            // we are in the local path
            // try and pull from localstorage;
            let error = null;
            try {
                const fromStorage = JSON.parse(
                    window.localStorage.getItem(TOKEN_KEY)
                );
                if (
                    fromStorage.meta.expiry &&
                    fromStorage.meta.expiry < Date.now()
                ) {
                    //token expired, silently remove.
                } else if (fromStorage.meta.error) {
                    error = new Error(fromStorage.meta.error);
                    error.type = fromStorage.meta.errorType;
                    token.meta = fromStorage.meta;
                } else if (fromStorage.accessToken) {
                    token.accessToken = fromStorage.accessToken;
                    token.meta = fromStorage.meta;
                }
            } catch (e) {
                //do nothing.
            }

            //keep hold of the current token, so we can log it out.
            let currentToken = token && token.accessToken;

            return Object.assign(baseReturnValue, {
                //local version of check, just grabs the already present values.
                check(callback) {
                    callback(error, tokenIfOK());
                },
                //local version of request should trigger the oauth
                request(callback) {
                    return strategy.requestToken((err, tok) => {
                        //update our local knowledge of the token
                        currentToken = tok && tok.accessToken;
                        return callback(err, tok);
                    });
                },
                logout() {
                    // use the currentToken to logout.
                    const uri = logout(currentToken);
                    if (typeof strategy.logout === "function") {
                        strategy.logout(uri);
                    } else {
                        window.location.href = uri;
                    }
                }
            });
        }
    };
}
<commit_msg>#164208234: remove token from logout uri<commit_after>import querystring from "querystring";

/**
 *  This is the core strategy.
 *  despite the differing methods, Implicit OAuth always returns the token in a specific way in the hash fragment.
 *  we also store the token in localStorage in the same way.
 *  Therefore we can abstract those bits.
 *
 *  Also the concept of whether we are "local" i.e. in the page, or "remote", i.e.
 *  in the popup/frame/redirection process will be common, it's a bit like a "fork"
 *
 *  One branch of code is for the local, another for the remote.
 */

const createKey = clientId => key => `___${clientId}:${key}`;
const parseQuerystring = qs => querystring.parse(qs.replace(/^\?/, ""));
const parseFragment = fragment => querystring.parse(fragment.replace(/^#/, ""));
const getOrigin = (l = window.location) =>
    !l.origin
        ? l.protocol + "//" + l.hostname + (l.port ? ":" + l.port : "")
        : l.origin;
const defaultRedirectUri = () => getOrigin() + "/";

export default function createOauthStrategy(implementation) {
    return ({
        clientId,
        url: baseURL,
        redirectUri = defaultRedirectUri(),
        logoutUri,
        logoutReturnUrl,
        clearStorageOnLogout = true,
        ...options
    }) => {
        const key = createKey(clientId);
        const TOKEN_KEY = key("token");
        const token = {
            accessToken: null,
            meta: {}
        };
        const tokenIfOK = () => {
            if (token.accessToken) {
                return token;
            }
        };

        const url =
            baseURL +
            (baseURL.indexOf("?") > -1 ? "&" : "?") +
            querystring.stringify({
                client_id: clientId,
                redirect_url: redirectUri
            });

        const clear = () => window.localStorage.removeItem(TOKEN_KEY);

        const logout = () => {
            if (clearStorageOnLogout) {
                clear();
            }
            return (
                logoutUri +
                "?" +
                querystring.stringify({
                    return_url: logoutReturnUrl
                })
            );
        };

        //create our strategy for getting tokens.
        const strategy = implementation({
            clientId,
            url,
            key,
            redirectUri,
            ...options
        });

        //turns out these are useful to the consumer as well.
        const baseReturnValue = {
            clear,
            isRemote: () => strategy.isRemote(),
            isLocal: () => !strategy.isRemote()
        };

        if (strategy.isRemote()) {
            let error;
            //we are in the remote path. That means that we *SHOULD*
            //be checking for the token in the url fragment
            const frag = parseFragment(window.location.hash);
            if (frag.access_token) {
                token.accessToken = frag.access_token;
                const expiry =
                    Date.now() + parseInt(frag.expires_in, 10) * 1000;
                if (!isNaN(expiry)) {
                    token.meta.expiry = expiry;
                }
            } else {
                const {
                    error: errorType,
                    error_description: errDescription
                } = parseQuerystring(window.location.search);
                if (errorType && errDescription) {
                    token.meta.error = errDescription;
                    token.meta.errorType = errorType;
                    error = new Error(errDescription);
                    error.type = errorType;
                }
            }
            window.localStorage.setItem(TOKEN_KEY, JSON.stringify(token));

            //remote version of check.
            return Object.assign(baseReturnValue, {
                check() {
                    try {
                        strategy.callLocalCallback(error, tokenIfOK());
                    } catch (e) {
                        console.error(e);
                    }
                },
                request() {
                    //nothing to do here
                },
                logout() {
                    //nothing on remote side
                }
            });
        } else {
            // we are in the local path
            // try and pull from localstorage;
            let error = null;
            try {
                const fromStorage = JSON.parse(
                    window.localStorage.getItem(TOKEN_KEY)
                );
                if (
                    fromStorage.meta.expiry &&
                    fromStorage.meta.expiry < Date.now()
                ) {
                    //token expired, silently remove.
                } else if (fromStorage.meta.error) {
                    error = new Error(fromStorage.meta.error);
                    error.type = fromStorage.meta.errorType;
                    token.meta = fromStorage.meta;
                } else if (fromStorage.accessToken) {
                    token.accessToken = fromStorage.accessToken;
                    token.meta = fromStorage.meta;
                }
            } catch (e) {
                //do nothing.
            }

            return Object.assign(baseReturnValue, {
                //local version of check, just grabs the already present values.
                check(callback) {
                    callback(error, tokenIfOK());
                },
                //local version of request should trigger the oauth
                request(callback) {
                    return strategy.requestToken((err, tok) => {
                        return callback(err, tok);
                    });
                },
                logout() {
                    const uri = logout();
                    if (typeof strategy.logout === "function") {
                        strategy.logout(uri);
                    } else {
                        window.location.href = uri;
                    }
                }
            });
        }
    };
}
<|endoftext|>


<commit_before>const dom = require('@nymag/dom'),
  edit = require('../services/edit'),
  events = require('../services/events'),
  focus = require('../decorators/focus'),
  pane = require('../services/pane'),
  site = require('../services/site'),
  state = require('../services/page-state'),
  progress = require('../services/progress'),
  rules = require('../validators'),
  validation = require('../services/publish-validation');

let EditorToolbar;

/**
 * Open the new page pane
 * note: if there's only one possible page, it'll just create it instead
 * @returns {Promise}
 */
function createPage() {
  return edit.getDataOnly(`${site.get('prefix')}/lists/new-pages`)
    .then(function (pages) {
      // if there are multiple types of pages for a site, open a dialog pane to select the page type
      // otherwise, just create a new page
      // currently 'Press' is the only site that has only one page type
      if (pages.length > 1) {
        return focus.unfocus()
          .then(pane.openNewPage)
          .catch(function () {
            progress.done('error');
            progress.open('error', 'Issue with opening page options.', true);
          });
      } else {
        return edit.createPage(pages[0].id).then(function (url) { // only one page type, so just create a 'new' page
          location.href = url;
        });
      }
    });
}

/**
 * @class EditorToolbar
 * @param {Element} el
 * @property {Element} el
 */
EditorToolbar = function (el) {

  this.statusEl = dom.find(el, '.kiln-status');
  this.progressEl = dom.find(el, '.kiln-progress');
  this.toolbar = dom.find(el, '.kiln-toolbar');

  events.add(this.toolbar, {
    '.user-icon click': 'onUserClick',
    '.new click': 'onNewClick',
    '.preview click': 'onPreviewClick',
    '.history click': 'onHistoryClick',
    '.publish click': 'onPublishClick'
  }, this);

  // stop users from leaving the page if they have an unsaved form open!
  window.addEventListener('beforeunload', function (e) {
    if (focus.hasCurrentFocus()) {
      e.returnValue = 'Are you sure you want to leave this page? Your data may not be saved.';
    }
  });

  // close ANY open forms if user hits ESC
  document.addEventListener('keydown', function (e) {
    if (e.keyCode === 27) {
      focus.unfocus();
      // note: this will work even if there isn't a current form open
      // fun fact: it'll unselect components as well, in case the user has a form closed
      // but a component selected, and they don't want that
    }
  });

  return state.get().then(function (res) {
    if (res.scheduled) {
      state.openDynamicSchedule(res.scheduledAt, res.publishedUrl);
    } else if (res.published) {
      progress.open('publish', `Page is currently live: <a href="${res.publishedUrl}" target="_blank">View Page</a>`);
    }
  });
};

/**
 * @lends EditorToolbar#
 */
EditorToolbar.prototype = {
  onUserClick: function (e) {
    // nothing yet
    e.preventDefault();
    e.stopPropagation();
  },

  onNewClick: function () {
    if (focus.hasCurrentFocus()) {
      if(window.confirm('Are you sure you want to create a new page? Your data on this page may not be saved.')) { // eslint-disable-line
        return createPage();
      } // else don't leave
    } else {
      return createPage();
    }
  },

  onPreviewClick: function () {
    return focus.unfocus()
      .then(pane.openPreview)
      .catch(function () {
        progress.done('error');
        progress.open('error', 'Data could not be saved. Please review your open form.', true);
      });
  },

  onHistoryClick: function openHistoryPane() {
    // open the history pane if it's not already open (close other panes first)
  },

  // open the publish pane if it's not already open (close other panes first)
  onPublishClick: function () {
    return focus.unfocus()
      .then(function () {
        // validate before opening the publish pane
        return validation.validate(rules).then(function (results) {
          if (results.errors.length) {
            progress.done('error');
            pane.openValidationErrors(results);
          } else {
            pane.openPublish(results.warnings);
          }
        });
      })
      .catch(function () {
        // if we can't unfocus the current form...
        progress.done('error');
        progress.open('error', 'Data could not be saved. Please review your open form.', true);
      });
  }
};

module.exports = EditorToolbar;
<commit_msg>always open pane when hitting new page (#479)<commit_after>const dom = require('@nymag/dom'),
  events = require('../services/events'),
  focus = require('../decorators/focus'),
  pane = require('../services/pane'),
  state = require('../services/page-state'),
  progress = require('../services/progress'),
  rules = require('../validators'),
  validation = require('../services/publish-validation');

let EditorToolbar;

/**
 * Open the new page pane
 * note: if there's only one possible page, it'll just create it instead
 * @returns {Promise}
 */
function createPage() {
  return focus.unfocus()
    .then(pane.openNewPage)
    .catch(function () {
      progress.done('error');
      progress.open('error', 'Issue with opening page options.', true);
    });
}

/**
 * @class EditorToolbar
 * @param {Element} el
 * @property {Element} el
 */
EditorToolbar = function (el) {

  this.statusEl = dom.find(el, '.kiln-status');
  this.progressEl = dom.find(el, '.kiln-progress');
  this.toolbar = dom.find(el, '.kiln-toolbar');

  events.add(this.toolbar, {
    '.user-icon click': 'onUserClick',
    '.new click': 'onNewClick',
    '.preview click': 'onPreviewClick',
    '.history click': 'onHistoryClick',
    '.publish click': 'onPublishClick'
  }, this);

  // stop users from leaving the page if they have an unsaved form open!
  window.addEventListener('beforeunload', function (e) {
    if (focus.hasCurrentFocus()) {
      e.returnValue = 'Are you sure you want to leave this page? Your data may not be saved.';
    }
  });

  // close ANY open forms if user hits ESC
  document.addEventListener('keydown', function (e) {
    if (e.keyCode === 27) {
      focus.unfocus();
      // note: this will work even if there isn't a current form open
      // fun fact: it'll unselect components as well, in case the user has a form closed
      // but a component selected, and they don't want that
    }
  });

  return state.get().then(function (res) {
    if (res.scheduled) {
      state.openDynamicSchedule(res.scheduledAt, res.publishedUrl);
    } else if (res.published) {
      progress.open('publish', `Page is currently live: <a href="${res.publishedUrl}" target="_blank">View Page</a>`);
    }
  });
};

/**
 * @lends EditorToolbar#
 */
EditorToolbar.prototype = {
  onUserClick: function (e) {
    // nothing yet
    e.preventDefault();
    e.stopPropagation();
  },

  onNewClick: function () {
    if (focus.hasCurrentFocus()) {
      if(window.confirm('Are you sure you want to create a new page? Your data on this page may not be saved.')) { // eslint-disable-line
        return createPage();
      } // else don't leave
    } else {
      return createPage();
    }
  },

  onPreviewClick: function () {
    return focus.unfocus()
      .then(pane.openPreview)
      .catch(function () {
        progress.done('error');
        progress.open('error', 'Data could not be saved. Please review your open form.', true);
      });
  },

  onHistoryClick: function openHistoryPane() {
    // open the history pane if it's not already open (close other panes first)
  },

  // open the publish pane if it's not already open (close other panes first)
  onPublishClick: function () {
    return focus.unfocus()
      .then(function () {
        // validate before opening the publish pane
        return validation.validate(rules).then(function (results) {
          if (results.errors.length) {
            progress.done('error');
            pane.openValidationErrors(results);
          } else {
            pane.openPublish(results.warnings);
          }
        });
      })
      .catch(function () {
        // if we can't unfocus the current form...
        progress.done('error');
        progress.open('error', 'Data could not be saved. Please review your open form.', true);
      });
  }
};

module.exports = EditorToolbar;
<|endoftext|>


<commit_before>elation.component.add("engine.things.turret", function(args) {
  this.postinit = function() {
    //this.initControllable();

    this.defineProperties({
      'pitch':           { type: 'angle', default: 0 },
      'yaw':             { type: 'angle', default: 0 },
      'pitchspeed':      { type: 'angle', default: Math.PI / 2 },
      'yawspeed':        { type: 'angle', default: Math.PI / 2 },
      'maxpitchdegrees': { type: 'angle', default: 90 },
      'minpitchdegrees': { type: 'angle', default: -44 },
      'reloadtime':      { type: 'integer', default: 2000 },
      'muzzleoffset':    { type: 'vector3', default: [0,0,0] },
      'muzzlespeed':     { type: 'float', default: 150.0 },
      'range':           { type: 'float', default: 300.0 },
      'render.scene':    { default: '/media/space/models/turret/A1 Turret.js' },
    });
    this.defineActions({
      'pitch': this.pitch,
      'yaw': this.yaw,
      'fire': this.fire,
      'aim': this.aim
    });

    this.pitchvel = new THREE.Vector3();
    this.yawvel = new THREE.Vector3();

    elation.events.add(this, 'thing_load', this);
  }
  this.pitch = function(amount) {
    this.pitchvel.set(amount * this.properties.pitchspeed,0,0);
    this.hinges['gun'].updateState();
  }
  this.yaw = function(amount) {
    this.yawvel.set(0, 0, amount * this.properties.yawspeed);
    this.hinges['mount'].updateState();
  }
  this.fire = function(amount) {
    console.log('bang!');
    //this.spawn('turret_bullet', {}, false);
  }
  this.aim = function() {
    if (!this.parts || !this.parts['Turret_gun']) return;
    var aimpos = this.parts['Turret_gun'].localToWorld(this.properties.muzzleoffset.clone());
    var gunpos = new THREE.Vector3().getPositionFromMatrix(this.parts['Turret_gun'].matrixWorld);
    var aimvel = this.parts['Turret_gun'].localToWorld(new THREE.Vector3(0,1,0)).sub(gunpos).normalize();
    return {position: aimpos, velocity: aimvel};
  }
  this.thing_load = function(ev) {
    this.hinges = {};
    this.hinges['gun'] = new elation.physics.rigidbody({
      position: this.parts['Turret_gun'].position,
      orientation: this.parts['Turret_gun'].quaternion,
      mass: 0,
      angular: this.pitchvel,
      object: this
    });
    elation.physics.system.add(this.hinges['gun']);

    this.hinges['mount'] = new elation.physics.rigidbody({
      position: this.parts['Turret_mount'].position,
      orientation: this.parts['Turret_mount'].quaternion,
      mass: 0,
      angular: this.yawvel,
      object: this
    });
    elation.physics.system.add(this.hinges['mount']);

    this.spawn("turretcontroller", {persist: false});
  }
}, elation.engine.things.generic);

/* BEGIN AI */

elation.component.add("engine.things.turretcontroller", function(args) {
  this.postinit = function() {
    this.initAIController();
    this.defineActions({
      'setTarget': this.setTarget
    });
    this.defineProperties({
      'target': { type: 'thing', comment: 'Active target' }
    });
    this.addBehavior('track_and_fire', this.track_and_fire, 100);
    this.setBehavior('track_and_fire');
    //this.engine.systems.get('world').scene['world-3d'].add(this.helpers.aim);
  }
  this.track_and_fire = function() {
    // Ideal solution:
    //  - calculate flighttime for projectile to reach target, given muzzle velocity
    //  - extrapolate target position + target velocity * flighttime
    //  - determine necessary pitch/yaw amounts

    var deadzone = Math.PI/32;

    // FIXME - target is hardcoded as camera for now; need proper target acquisition logic
    var turret = this.parent,
        target = this.engine.systems.get('render').views['main'].camera; //this.properties.target;
    if (turret && target) {
      var aim = turret.aim();
      if (!aim) return;

      var dist = aim.position.distanceTo(target.position);
      if (dist < turret.properties.range) {
        var targetpos = new THREE.Vector3().getPositionFromMatrix(target.matrixWorld);
        var mypos = new THREE.Vector3().getPositionFromMatrix(this.parent.objects['3d'].matrixWorld);
        var targetdir = turret.parts['Turret_mount'].worldToLocal(targetpos).normalize();
        var aimdir = turret.parts['Turret_mount'].worldToLocal(aim.velocity.clone().add(mypos)).normalize();

        var t = new THREE.Vector3(targetdir.x, 0, targetdir.y).normalize();
        var a = new THREE.Vector3(aimdir.x, 0, aimdir.y).normalize();
        var yaw = Math.atan((t.x - a.x) / (t.z - a.z));
        var yaw2 = Math.acos(t.dot(a));
        var yawspeed = yaw / (turret.properties.yawspeed * this.thinktime/1000);
        var yaw3 = yaw2 * (yaw / Math.abs(yaw)) / (turret.properties.yawspeed * this.thinktime/1000);
        //console.log('yaw is', yaw, yaw2, yaw3);
        yawspeed = yaw3;

        turret.yaw(this.deadzone(yawspeed, deadzone, 1));
        /*
        var curpitch = new THREE.Vector3().setEulerFromQuaternion(turret.parts['Turret_gun'].quaternion);
        if ((curpitch.x > turret.properties.maxpitchdegrees * Math.PI/180 && pitch > 0) ||
            (curpitch.x < turret.properties.minpitchdegrees * Math.PI/180) && pitch < 0) {
          turret.pitch(0);
        } else {
          turret.pitch(this.deadzone(pitch, deadzone, 1));
        }
        */
      } else {
        //turret.state['firing'] = false;
      }
    }
  }

  this.deadzone = function(angle, deadzone, max) {
    return (Math.abs(angle) < deadzone ? 0 : Math.max(-max, Math.min(max, angle)));
  }

}, elation.engine.things.aicontroller);

<commit_msg>Fixed and reenabled turret firing<commit_after>elation.component.add("engine.things.turret", function(args) {
  this.postinit = function() {
    //this.initControllable();

    this.defineProperties({
      'pitch':           { type: 'angle', default: 0 },
      'yaw':             { type: 'angle', default: 0 },
      'pitchspeed':      { type: 'angle', default: Math.PI / 2 },
      'yawspeed':        { type: 'angle', default: Math.PI / 2 },
      'maxpitchdegrees': { type: 'angle', default: 90 },
      'minpitchdegrees': { type: 'angle', default: -44 },
      'reloadtime':      { type: 'integer', default: 2000 },
      'muzzleoffset':    { type: 'vector3', default: [0,0,0] },
      'muzzlespeed':     { type: 'float', default: 150.0 },
      'range':           { type: 'float', default: 300.0 },
      'render.scene':    { default: '/media/space/models/turret/A1 Turret.js' },
    });
    this.defineActions({
      'pitch': this.pitch,
      'yaw': this.yaw,
      'fire': this.fire,
      'aim': this.aim
    });

    this.lastfire = 0;
    this.pitchvel = new THREE.Vector3();
    this.yawvel = new THREE.Vector3();

    elation.events.add(this, 'thing_load', this);
  }
  this.pitch = function(amount) {
    this.pitchvel.set(amount * this.properties.pitchspeed,0,0);
    this.hinges['gun'].updateState();
  }
  this.yaw = function(amount) {
    this.yawvel.set(0, 0, amount * this.properties.yawspeed);
    this.hinges['mount'].updateState();
  }
  this.fire = function(amount) {
    var now = new Date().getTime();
    if (now > this.lastfire + this.properties.reloadtime) {
      var aim = this.aim();
      var bullet = this.spawn('turret_bullet', null, {position: aim.position.toArray(), velocity: aim.velocity.multiplyScalar(this.properties.muzzlespeed).toArray()}, true);
      setTimeout(elation.bind(bullet, bullet.die), this.properties.reloadtime * 4);
      this.lastfire = now;
    }
  }
  this.aim = function() {
    if (!this.parts || !this.parts['Turret_gun']) return;
    var aimpos = this.parts['Turret_gun'].localToWorld(this.properties.muzzleoffset.clone());
    var gunpos = new THREE.Vector3().getPositionFromMatrix(this.parts['Turret_gun'].matrixWorld);
    var aimvel = this.parts['Turret_gun'].localToWorld(new THREE.Vector3(0,1,0)).sub(gunpos).normalize();
    return {position: aimpos, velocity: aimvel};
  }
  this.thing_load = function(ev) {
    this.hinges = {};
    this.hinges['gun'] = new elation.physics.rigidbody({
      position: this.parts['Turret_gun'].position,
      orientation: this.parts['Turret_gun'].quaternion,
      mass: 0,
      angular: this.pitchvel,
      object: this
    });
    elation.physics.system.add(this.hinges['gun']);

    this.hinges['mount'] = new elation.physics.rigidbody({
      position: this.parts['Turret_mount'].position,
      orientation: this.parts['Turret_mount'].quaternion,
      mass: 0,
      angular: this.yawvel,
      object: this
    });
    elation.physics.system.add(this.hinges['mount']);

    this.spawn("turretcontroller", null, {persist: false});
  }
}, elation.engine.things.generic);

/* BEGIN AI */

elation.component.add("engine.things.turretcontroller", function(args) {
  this.postinit = function() {
    this.initAIController();
    this.defineActions({
      'setTarget': this.setTarget
    });
    this.defineProperties({
      'target': { type: 'thing', comment: 'Active target' }
    });
    this.addBehavior('track_and_fire', this.track_and_fire, 100);
    this.setBehavior('track_and_fire');
    //this.engine.systems.world.scene['world-3d'].add(this.helpers.aim);
  }
  this.track_and_fire = function() {
    // Ideal solution:
    //  - calculate flighttime for projectile to reach target, given muzzle velocity
    //  - extrapolate target position + target velocity * flighttime
    //  - determine necessary pitch/yaw amounts

    var deadzone = Math.PI/32;

    // FIXME - target is hardcoded as camera for now; need proper target acquisition logic
    var turret = this.parent,
        target = this.engine.systems.render.views['main'].camera; //this.properties.target;
    if (turret && target) {
      var aim = turret.aim();
      if (!aim) return;

      var dist = aim.position.distanceTo(target.position);
      if (dist < turret.properties.range) {
        var targetpos = new THREE.Vector3().getPositionFromMatrix(target.matrixWorld);
        var mypos = new THREE.Vector3().getPositionFromMatrix(this.parent.objects['3d'].matrixWorld);
        var targetdir = turret.parts['Turret_mount'].worldToLocal(targetpos).normalize();
        var aimdir = turret.parts['Turret_mount'].worldToLocal(aim.velocity.clone().add(mypos)).normalize();

        var t = new THREE.Vector3(targetdir.x, 0, targetdir.y).normalize();
        var a = new THREE.Vector3(aimdir.x, 0, aimdir.y).normalize();
        var yaw = Math.atan((t.x - a.x) / (t.z - a.z));
        var yaw2 = Math.acos(t.dot(a));
        var yawspeed = yaw / (turret.properties.yawspeed * this.thinktime/1000);
        var yaw3 = yaw2 * (yaw / Math.abs(yaw)) / (turret.properties.yawspeed * this.thinktime/1000);
        //console.log('yaw is', yaw, yaw2, yaw3);
        yawspeed = yaw3;

        turret.yaw(this.deadzone(yawspeed, deadzone, 1));
        /*
        var curpitch = new THREE.Vector3().setEulerFromQuaternion(turret.parts['Turret_gun'].quaternion);
        if ((curpitch.x > turret.properties.maxpitchdegrees * Math.PI/180 && pitch > 0) ||
            (curpitch.x < turret.properties.minpitchdegrees * Math.PI/180) && pitch < 0) {
          turret.pitch(0);
        } else {
          turret.pitch(this.deadzone(pitch, deadzone, 1));
        }
        */
        if (Math.abs(yaw3) < deadzone) {
          turret.fire();
        }
        //turret.state['firing'] = false;
      } else {
        //turret.state['firing'] = false;
      }
    }
  }

  this.deadzone = function(angle, deadzone, max) {
    return (Math.abs(angle) < deadzone ? 0 : Math.max(-max, Math.min(max, angle)));
  }

}, elation.engine.things.aicontroller);

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Mathieu Turcotte
 * Licensed under the MIT license.
 */

var util = require('util');

var BackoffStrategy = require('./strategy');

/**
 * Fibonnaci backoff strategy.
 * @extends BackoffStrategy
 */
function FibonnaciBackoffStrategy(options) {
    BackoffStrategy.call(this, options);
    this.backoffDelay_ = 0;
    this.nextBackoffDelay_ = this.getInitialDelay();
}
util.inherits(FibonnaciBackoffStrategy, BackoffStrategy);

/** @inheritDoc */
FibonnaciBackoffStrategy.prototype.next_ = function() {
    var backoffDelay = Math.min(this.nextBackoffDelay_, this.getMaxDelay());
    this.nextBackoffDelay_ += this.backoffDelay_;
    this.backoffDelay_ = backoffDelay;
    return backoffDelay;
};

/** @inheritDoc */
FibonnaciBackoffStrategy.prototype.reset_ = function() {
    this.nextBackoffDelay_ = this.getInitialDelay();
    this.backoffDelay_ = 0;
};

module.exports = FibonnaciBackoffStrategy;

<commit_msg>Fix Fibonacci spelling.<commit_after>/*
 * Copyright (c) 2012 Mathieu Turcotte
 * Licensed under the MIT license.
 */

var util = require('util');

var BackoffStrategy = require('./strategy');

/**
 * Fibonacci backoff strategy.
 * @extends BackoffStrategy
 */
function FibonacciBackoffStrategy(options) {
    BackoffStrategy.call(this, options);
    this.backoffDelay_ = 0;
    this.nextBackoffDelay_ = this.getInitialDelay();
}
util.inherits(FibonacciBackoffStrategy, BackoffStrategy);

/** @inheritDoc */
FibonacciBackoffStrategy.prototype.next_ = function() {
    var backoffDelay = Math.min(this.nextBackoffDelay_, this.getMaxDelay());
    this.nextBackoffDelay_ += this.backoffDelay_;
    this.backoffDelay_ = backoffDelay;
    return backoffDelay;
};

/** @inheritDoc */
FibonacciBackoffStrategy.prototype.reset_ = function() {
    this.nextBackoffDelay_ = this.getInitialDelay();
    this.backoffDelay_ = 0;
};

module.exports = FibonacciBackoffStrategy;

<|endoftext|>


<commit_before>function ResponsesIndexWindow(surveyID) {
  var ResponsesIndexView = require('ui/common/responses/ResponsesIndexView')
  var ResponseShowView = require('ui/common/responses/ResponseShowView')
  var ResponseShowWindow = require('ui/handheld/android/ResponseShowWindow')
  var SurveyDetailsWindow = require('ui/handheld/android/SurveyDetailsWindow')
  var Survey = require('models/survey');
  var NetworkHelper = require('helpers/NetworkHelper');

  var self = Ti.UI.createWindow({
    navBarHidden : true,
    backgroundColor : "#fff",

    activity : {
      onCreateOptionsMenu : function(e) {
        var menu = e.menu;
        var menuItemSync = menu.add({
          title : "Sync"
        });
        menuItemSync.addEventListener('click', function() {
          survey = Survey.findOneById(surveyID)
          NetworkHelper.pingSurveyWebWithLoggedInCheck( onSuccess = function() {
            survey.syncResponses();
          });
        });
        menuItemSync.setIcon("images/refresh.png");
      }
    }
  });

  var view = new ResponsesIndexView(surveyID);
  self.add(view);

  view.addEventListener('ResponsesIndexView:table_row_clicked', function(e) {
    new ResponseShowWindow(e.responseID).open();
  });

  var syncHandler = function(data) {
    Ti.App.removeEventListener("survey.responses.sync", syncHandler);
    self.close();
    if (data.message)
      alert(data.message);
    else
      alert("successes: " + (data.successes || 0) + "\nerrors: " + (data.errors || 0));
  };
  Ti.App.addEventListener("survey.responses.sync", syncHandler);

  self.addEventListener('close', function() {
    Ti.App.removeEventListener("survey.responses.sync", syncHandler);
  });

  return self;
}

module.exports = ResponsesIndexWindow;
<commit_msg>Disable sync response button(menu) in the Response#Index<commit_after>function ResponsesIndexWindow(surveyID) {
  var ResponsesIndexView = require('ui/common/responses/ResponsesIndexView')
  var ResponseShowView = require('ui/common/responses/ResponseShowView')
  var ResponseShowWindow = require('ui/handheld/android/ResponseShowWindow')
  var SurveyDetailsWindow = require('ui/handheld/android/SurveyDetailsWindow')
  var Survey = require('models/survey');
  var NetworkHelper = require('helpers/NetworkHelper');
  var loggedIn = require('helpers/LoginHelper').loggedIn;

  var self = Ti.UI.createWindow({
    navBarHidden : true,
    backgroundColor : "#fff",

    activity : {
      onCreateOptionsMenu : function(e) {
        var menu = e.menu;
        var menuItemSync = menu.add({
          title : "Sync",
          groupId : 1
        });
        menuItemSync.addEventListener('click', function() {
          survey = Survey.findOneById(surveyID)
          NetworkHelper.pingSurveyWebWithLoggedInCheck( onSuccess = function() {
            survey.syncResponses();
          });
        });
        menuItemSync.setIcon("images/refresh.png");
      },
      onPrepareOptionsMenu : function(e) {
        var menu = e.menu;
        menu.setGroupEnabled(1, loggedIn());
      }
    }
  });

  var view = new ResponsesIndexView(surveyID);
  self.add(view);

  view.addEventListener('ResponsesIndexView:table_row_clicked', function(e) {
    new ResponseShowWindow(e.responseID).open();
  });

  var syncHandler = function(data) {
    Ti.App.removeEventListener("survey.responses.sync", syncHandler);
    self.close();
    if (data.message)
      alert(data.message);
    else
      alert("successes: " + (data.successes || 0) + "\nerrors: " + (data.errors || 0));
  };
  Ti.App.addEventListener("survey.responses.sync", syncHandler);

  self.addEventListener('close', function() {
    Ti.App.removeEventListener("survey.responses.sync", syncHandler);
  });

  return self;
}

module.exports = ResponsesIndexWindow;
<|endoftext|>


<commit_before>var needle = require('../'),
    path   = require('path');

var image = 'https://upload.wikimedia.org/wikipedia/commons/a/af/Tux.png';

function upload(obj, cb) {
  console.log('Uploading image...');

  var url = 'http://deviantsart.com';

  var opts = {
    timeout:  10000,
    follow:    true,
    multipart: true
  };

  var params = {
    file: obj
  }

  needle.post(url, params, opts, function(err, resp) {
    if (err || !resp.body.match('url'))
      return cb(err || new Error('No image URL found.'))

    cb(null, JSON.parse(resp.body).url)
  })
}

function download(url, cb) {
  console.log('Getting ' + url);
  needle.get(url, function(err, resp) {
    if (err) throw err;

    cb(null, resp.body);
  })
}

////////////////////////////////////////
// ok, now go.

download(image, function(err, buffer) {
  if (err) throw err;

  var obj = { buffer: buffer, content_type: 'image/png' };

  upload(obj, function(err, url) {
    if (err) throw err;

    console.log('Image uploaded to ' + url);
  })
})
<commit_msg>Update upload-image.js<commit_after>var needle = require('../'),
    path   = require('path');

var image = 'https://upload.wikimedia.org/wikipedia/commons/a/af/Tux.png';

function upload(obj, cb) {
  console.log('Uploading image...');

  var url = 'http://deviantsart.com';

  var opts = {
    timeout:  10000,
    follow:    3,
    multipart: true
  };

  var params = {
    file: obj
  }

  needle.post(url, params, opts, function(err, resp) {
    if (err || !resp.body.match('url'))
      return cb(err || new Error('No image URL found.'))

    cb(null, JSON.parse(resp.body).url)
  })
}

function download(url, cb) {
  console.log('Getting ' + url);
  needle.get(url, function(err, resp) {
    if (err) throw err;

    cb(null, resp.body);
  })
}

////////////////////////////////////////
// ok, now go.

download(image, function(err, buffer) {
  if (err) throw err;

  var obj = { buffer: buffer, content_type: 'image/png' };

  upload(obj, function(err, url) {
    if (err) throw err;

    console.log('Image uploaded to ' + url);
  })
})
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import cx from 'classnames';
import s from './Display.scss';
import Alert from '../../Alert';
import withStyles from '../../../decorators/withStyles';

@withStyles(s)
class Configurator extends Component {

	static propTypes = {
		id: PropTypes.string,
		products: PropTypes.array,
		className: PropTypes.string,
		window: PropTypes.object,
	};

	constructor() {
		super();

		this.state = {};
	}

	componentDidMount() {
		this.props.window.onerror = () => {
			this.setState({
				error: `No image of vehicle with parts available.`,
			});
		};
	}

	componentDidUpdate() {
		if (window.ICAPP) {
			window.ICAPP.getRefVehicle();
		}
	}

	render() {
		if (this.state.error) {
			const err = {
				message: this.state.error,
			};

			return
<Alert error={err} />
;
		}

		const prods = this.props.products.map((p) => p.part_number);
		console.log(prods.join(','));

		return (

		);
	}

}

export default Configurator;
<commit_msg>removed console statement<commit_after>import React, { Component, PropTypes } from 'react';
import cx from 'classnames';
import s from './Display.scss';
import Alert from '../../Alert';
import withStyles from '../../../decorators/withStyles';

@withStyles(s)
class Configurator extends Component {

	static propTypes = {
		id: PropTypes.string,
		products: PropTypes.array,
		className: PropTypes.string,
		window: PropTypes.object,
	};

	constructor() {
		super();

		this.state = {};
	}

	componentDidMount() {
		this.props.window.onerror = () => {
			this.setState({
				error: `No image of vehicle with parts available.`,
			});
		};
	}

	componentDidUpdate() {
		if (window.ICAPP) {
			window.ICAPP.getRefVehicle();
		}
	}

	render() {
		if (this.state.error) {
			const err = {
				message: this.state.error,
			};

			return
<Alert error={err} />
;
		}

		const prods = this.props.products.map((p) => p.part_number);

		return (

		);
	}

}

export default Configurator;
<|endoftext|>


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

document.addEventListener('DOMContentLoaded', function() {
  ActionChoice.load();
});

/**
 * The main ActionChoice object.
 * @param {HTMLElement} dom Container.
 * @param {FileSystem} filesystem Local file system.
 * @param {Object} params Parameters.
 * @constructor
 */
function ActionChoice(dom, filesystem, params) {
  this.filesystem_ = filesystem;
  this.dom_ = dom;
  this.document_ = this.dom_.ownerDocument;
  this.metadataCache_ = params.metadataCache;
  this.volumeManager_ = VolumeManager.getInstance();
  this.volumeManager_.addEventListener('externally-unmounted',
     this.onDeviceUnmounted_.bind(this));

  this.initDom_();
  this.checkDrive_();
  this.loadSource_(params.source);
}

ActionChoice.prototype = { __proto__: cr.EventTarget.prototype };

/**
 * The number of previews shown.
 */
ActionChoice.PREVIEW_COUNT = 3;

/**
 * Loads app in the document body.
 * @param {FileSystem=} opt_filesystem Local file system.
 * @param {Object=} opt_params Parameters.
 */
ActionChoice.load = function(opt_filesystem, opt_params) {
  ImageUtil.metrics = metrics;

  var hash = location.hash ? decodeURI(location.hash.substr(1)) : '';
  var params = opt_params || {};
  if (!params.source) params.source = hash;
  if (!params.metadataCache) params.metadataCache = MetadataCache.createFull();

  var onFilesystem = function(filesystem) {
    var dom = document.querySelector('.action-choice');
    ActionChoice.instance = new ActionChoice(dom, filesystem, params);
  };

  chrome.fileBrowserPrivate.getStrings(function(strings) {
    loadTimeData.data = strings;

    i18nTemplate.process(document, loadTimeData);

    if (opt_filesystem) {
      onFilesystem(opt_filesystem);
    } else {
      chrome.fileBrowserPrivate.requestLocalFileSystem(onFilesystem);
    }
  });
};

/**
 * One-time initialization of dom elements.
 * @private
 */
ActionChoice.prototype.initDom_ = function() {
  this.previews_ = this.document_.querySelector('.previews');
  this.counter_ = this.document_.querySelector('.counter');

  this.document_.querySelector('button.ok').addEventListener('click',
      this.onOk_.bind(this));

  var choices = this.document_.querySelectorAll('.choices div');
  for (var index = 0; index < choices.length; index++) {
    choices[index].addEventListener('dblclick', this.onOk_.bind(this));
  }

  this.document_.addEventListener('keydown', this.onKeyDown_.bind(this));

  metrics.startInterval('PhotoImport.Load');
  this.dom_.setAttribute('loading', '');

  this.document_.querySelectorAll('.choices input')[0].focus();

  util.disableBrowserShortcutKeys(this.document_);
};

/**
 * Checks whether Drive is reachable.
 * @private
 */
ActionChoice.prototype.checkDrive_ = function() {
  var driveLabel = this.dom_.querySelector('label[for=import-photos-to-drive]');
  var driveChoice = this.dom_.querySelector('#import-photos-to-drive');
  var driveDiv = driveChoice.parentNode;
  driveChoice.disabled = true;
  driveDiv.setAttribute('disabled', '');

  var onMounted = function() {
    driveChoice.disabled = false;
    driveDiv.removeAttribute('disabled');
    driveLabel.textContent =
        loadTimeData.getString('ACTION_CHOICE_PHOTOS_DRIVE');
  };

  if (this.volumeManager_.isMounted(RootDirectory.DRIVE)) {
    onMounted();
  } else {
    this.volumeManager_.mountDrive(onMounted, function() {});
  }
};

/**
 * Load the source contents.
 * @param {string} source Path to source.
 * @private
 */
ActionChoice.prototype.loadSource_ = function(source) {
  var onTraversed = function(results) {
    metrics.recordInterval('PhotoImport.Scan');
    var videos = results.filter(FileType.isVideo);
    var videoLabel = this.dom_.querySelector('label[for=watch-single-video]');
    if (videos.length == 1) {
      videoLabel.textContent = loadTimeData.getStringF(
          'ACTION_CHOICE_WATCH_SINGLE_VIDEO', videos[0].name);
      this.singleVideo_ = videos[0];
    } else {
      videoLabel.parentNode.style.display = 'none';
    }

    var mediaFiles = results.filter(FileType.isImageOrVideo);
    if (mediaFiles.length == 0) {
      this.dom_.querySelector('#import-photos-to-drive').parentNode.
          style.display = 'none';

      // If we have no media files, the only choice is view files. So, don't
      // confuse user with a single choice, and just open file manager.
      this.viewFiles_();
      this.recordAction_('view-files-auto');
      this.close_();
    }

    if (mediaFiles.length < ActionChoice.PREVIEW_COUNT) {
      this.counter_.textContent = loadTimeData.getStringF(
          'ACTION_CHOICE_COUNTER_NO_MEDIA', results.length);
    } else {
      this.counter_.textContent = loadTimeData.getStringF(
          'ACTION_CHOICE_COUNTER', mediaFiles.length);
    }
    var previews = mediaFiles.length ? mediaFiles : results;
    var previewsCount = Math.min(ActionChoice.PREVIEW_COUNT, previews.length);
    this.renderPreview_(previews, previewsCount);
  }.bind(this);

  var onEntry = function(entry) {
    this.sourceEntry_ = entry;
    this.document_.querySelector('title').textContent = entry.name;

    var deviceType = this.volumeManager_.getDeviceType(entry.fullPath);
    if (deviceType != 'sd') deviceType = 'usb';
    this.dom_.querySelector('.device-type').setAttribute('device-type',
        deviceType);
    this.dom_.querySelector('.loading-text').textContent =
        loadTimeData.getString('ACTION_CHOICE_LOADING_' +
                               deviceType.toUpperCase());

    util.traverseTree(entry, onTraversed, 0 /* infinite depth */,
        FileType.isVisible);
  }.bind(this);

  var onReady = function() {
    util.resolvePath(this.filesystem_.root, source, onEntry, function() {
      this.recordAction_('error');
      this.close_();
    }.bind(this));
  }.bind(this);

  this.sourceEntry_ = null;
  metrics.startInterval('PhotoImport.Scan');
  if (!this.volumeManager_.isReady())
    this.volumeManager_.addEventListener('ready', onReady);
  else
    onReady();
};

/**
 * Renders a preview for a media entry.
 * @param {Array.<FileEntry>} entries The entries.
 * @param {number} count Remaining count.
 * @private
 */
ActionChoice.prototype.renderPreview_ = function(entries, count) {
  var entry = entries.shift();
  var box = this.document_.createElement('div');
  box.className = 'img-container';

  var done = function() {
    this.dom_.removeAttribute('loading');
    metrics.recordInterval('PhotoImport.Load');
  }.bind(this);

  var onSuccess = function() {
    this.previews_.appendChild(box);
    if (--count == 0) {
      done();
    } else {
      this.renderPreview_(entries, count);
    }
  }.bind(this);

  var onError = function() {
    if (entries.length == 0) {
      // Append one image with generic thumbnail.
      this.previews_.appendChild(box);
      done();
    } else {
      this.renderPreview_(entries, count);
    }
  }.bind(this);

  this.metadataCache_.get(entry, 'thumbnail|filesystem',
      function(metadata) {
        new ThumbnailLoader(entry.toURL(),
                            ThumbnailLoader.LoaderType.IMAGE,
                            metadata).load(
            box,
            ThumbnailLoader.FillMode.FILL,
            ThumbnailLoader.OptimizationMode.NEVER_DISCARD,
            onSuccess,
            onError,
            onError);
      });
};

/**
 * Closes the window.
 * @private
 */
ActionChoice.prototype.close_ = function() {
  window.close();
};

/**
 * Keydown event handler.
 * @param {Event} e The event.
 * @private
 */
ActionChoice.prototype.onKeyDown_ = function(e) {
  switch (util.getKeyModifiers(e) + e.keyCode) {
    case '13':
      this.onOk_();
      return;
    case '27':
      this.recordAction_('close');
      this.close_();
      return;
  }
};

/**
 * Called when OK button clicked.
 * @param {Event} event The event object.
 * @private
 */
ActionChoice.prototype.onOk_ = function(event) {
  // Check for click on the disabled choice.
  var input = event.currentTarget.querySelector('input');
  if (input && input.disabled) return;

  if (this.document_.querySelector('#import-photos-to-drive').checked) {
    var url = util.platform.getURL('photo_import.html') +
        '#' + this.sourceEntry_.fullPath;
    var width = 728;
    var height = 656;
    var top = Math.round((window.screen.availHeight - height) / 2);
    var left = Math.round((window.screen.availWidth - width) / 2);
    util.platform.createWindow(url,
        {height: height, width: width, left: left, top: top});
    this.recordAction_('import-photos-to-drive');
  } else if (this.document_.querySelector('#view-files').checked) {
    this.viewFiles_();
    this.recordAction_('view-files');
  } else if (this.document_.querySelector('#watch-single-video').checked) {
    chrome.fileBrowserPrivate.viewFiles([this.singleVideo_.toURL()], 'watch',
        function(success) {});
    this.recordAction_('watch-single-video');
  }
  this.close_();
};

/**
 * Called when some device is unmounted.
 * @param {Event} event Event object.
 * @private
 */
ActionChoice.prototype.onDeviceUnmounted_ = function(event) {
  if (this.sourceEntry_ && event.mountPath == this.sourceEntry_.fullPath) {
    util.platform.closeWindow();
  }
};

/**
 * Perform the 'view files' action.
 * @private
 */
ActionChoice.prototype.viewFiles_ = function() {
  var path = this.sourceEntry_.fullPath;
  if (util.platform.v2()) {
    chrome.runtime.getBackgroundPage(function(bg) {
      bg.launchFileManager({defaultPath: path});
    });
  } else {
    var url = util.platform.getURL('main.html') + '#' + path;
    util.platform.createWindow(url);
  }
};

/**
 * Records an action chosen.
 * @param {string} action Action name.
 * @private
 */
ActionChoice.prototype.recordAction_ = function(action) {
  metrics.recordEnum('PhotoImport.Action', action,
      ['import-photos-to-drive',
       'view-files',
       'view-files-auto',
       'watch-single-video',
       'error',
       'close']);
};
<commit_msg>Fixed issue with too small Files.app window opened from the action choose dialog.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

document.addEventListener('DOMContentLoaded', function() {
  ActionChoice.load();
});

/**
 * The main ActionChoice object.
 * @param {HTMLElement} dom Container.
 * @param {FileSystem} filesystem Local file system.
 * @param {Object} params Parameters.
 * @constructor
 */
function ActionChoice(dom, filesystem, params) {
  this.filesystem_ = filesystem;
  this.dom_ = dom;
  this.document_ = this.dom_.ownerDocument;
  this.metadataCache_ = params.metadataCache;
  this.volumeManager_ = VolumeManager.getInstance();
  this.volumeManager_.addEventListener('externally-unmounted',
     this.onDeviceUnmounted_.bind(this));

  this.initDom_();
  this.checkDrive_();
  this.loadSource_(params.source);
}

ActionChoice.prototype = { __proto__: cr.EventTarget.prototype };

/**
 * The number of previews shown.
 */
ActionChoice.PREVIEW_COUNT = 3;

/**
 * Loads app in the document body.
 * @param {FileSystem=} opt_filesystem Local file system.
 * @param {Object=} opt_params Parameters.
 */
ActionChoice.load = function(opt_filesystem, opt_params) {
  ImageUtil.metrics = metrics;

  var hash = location.hash ? decodeURI(location.hash.substr(1)) : '';
  var params = opt_params || {};
  if (!params.source) params.source = hash;
  if (!params.metadataCache) params.metadataCache = MetadataCache.createFull();

  var onFilesystem = function(filesystem) {
    var dom = document.querySelector('.action-choice');
    ActionChoice.instance = new ActionChoice(dom, filesystem, params);
  };

  chrome.fileBrowserPrivate.getStrings(function(strings) {
    loadTimeData.data = strings;

    i18nTemplate.process(document, loadTimeData);

    if (opt_filesystem) {
      onFilesystem(opt_filesystem);
    } else {
      chrome.fileBrowserPrivate.requestLocalFileSystem(onFilesystem);
    }
  });
};

/**
 * One-time initialization of dom elements.
 * @private
 */
ActionChoice.prototype.initDom_ = function() {
  this.previews_ = this.document_.querySelector('.previews');
  this.counter_ = this.document_.querySelector('.counter');

  this.document_.querySelector('button.ok').addEventListener('click',
      this.onOk_.bind(this));

  var choices = this.document_.querySelectorAll('.choices div');
  for (var index = 0; index < choices.length; index++) {
    choices[index].addEventListener('dblclick', this.onOk_.bind(this));
  }

  this.document_.addEventListener('keydown', this.onKeyDown_.bind(this));

  metrics.startInterval('PhotoImport.Load');
  this.dom_.setAttribute('loading', '');

  this.document_.querySelectorAll('.choices input')[0].focus();

  util.disableBrowserShortcutKeys(this.document_);
};

/**
 * Checks whether Drive is reachable.
 * @private
 */
ActionChoice.prototype.checkDrive_ = function() {
  var driveLabel = this.dom_.querySelector('label[for=import-photos-to-drive]');
  var driveChoice = this.dom_.querySelector('#import-photos-to-drive');
  var driveDiv = driveChoice.parentNode;
  driveChoice.disabled = true;
  driveDiv.setAttribute('disabled', '');

  var onMounted = function() {
    driveChoice.disabled = false;
    driveDiv.removeAttribute('disabled');
    driveLabel.textContent =
        loadTimeData.getString('ACTION_CHOICE_PHOTOS_DRIVE');
  };

  if (this.volumeManager_.isMounted(RootDirectory.DRIVE)) {
    onMounted();
  } else {
    this.volumeManager_.mountDrive(onMounted, function() {});
  }
};

/**
 * Load the source contents.
 * @param {string} source Path to source.
 * @private
 */
ActionChoice.prototype.loadSource_ = function(source) {
  var onTraversed = function(results) {
    metrics.recordInterval('PhotoImport.Scan');
    var videos = results.filter(FileType.isVideo);
    var videoLabel = this.dom_.querySelector('label[for=watch-single-video]');
    if (videos.length == 1) {
      videoLabel.textContent = loadTimeData.getStringF(
          'ACTION_CHOICE_WATCH_SINGLE_VIDEO', videos[0].name);
      this.singleVideo_ = videos[0];
    } else {
      videoLabel.parentNode.style.display = 'none';
    }

    var mediaFiles = results.filter(FileType.isImageOrVideo);
    if (mediaFiles.length == 0) {
      this.dom_.querySelector('#import-photos-to-drive').parentNode.
          style.display = 'none';

      // If we have no media files, the only choice is view files. So, don't
      // confuse user with a single choice, and just open file manager.
      this.viewFiles_();
      this.recordAction_('view-files-auto');
      this.close_();
    }

    if (mediaFiles.length < ActionChoice.PREVIEW_COUNT) {
      this.counter_.textContent = loadTimeData.getStringF(
          'ACTION_CHOICE_COUNTER_NO_MEDIA', results.length);
    } else {
      this.counter_.textContent = loadTimeData.getStringF(
          'ACTION_CHOICE_COUNTER', mediaFiles.length);
    }
    var previews = mediaFiles.length ? mediaFiles : results;
    var previewsCount = Math.min(ActionChoice.PREVIEW_COUNT, previews.length);
    this.renderPreview_(previews, previewsCount);
  }.bind(this);

  var onEntry = function(entry) {
    this.sourceEntry_ = entry;
    this.document_.querySelector('title').textContent = entry.name;

    var deviceType = this.volumeManager_.getDeviceType(entry.fullPath);
    if (deviceType != 'sd') deviceType = 'usb';
    this.dom_.querySelector('.device-type').setAttribute('device-type',
        deviceType);
    this.dom_.querySelector('.loading-text').textContent =
        loadTimeData.getString('ACTION_CHOICE_LOADING_' +
                               deviceType.toUpperCase());

    util.traverseTree(entry, onTraversed, 0 /* infinite depth */,
        FileType.isVisible);
  }.bind(this);

  var onReady = function() {
    util.resolvePath(this.filesystem_.root, source, onEntry, function() {
      this.recordAction_('error');
      this.close_();
    }.bind(this));
  }.bind(this);

  this.sourceEntry_ = null;
  metrics.startInterval('PhotoImport.Scan');
  if (!this.volumeManager_.isReady())
    this.volumeManager_.addEventListener('ready', onReady);
  else
    onReady();
};

/**
 * Renders a preview for a media entry.
 * @param {Array.<FileEntry>} entries The entries.
 * @param {number} count Remaining count.
 * @private
 */
ActionChoice.prototype.renderPreview_ = function(entries, count) {
  var entry = entries.shift();
  var box = this.document_.createElement('div');
  box.className = 'img-container';

  var done = function() {
    this.dom_.removeAttribute('loading');
    metrics.recordInterval('PhotoImport.Load');
  }.bind(this);

  var onSuccess = function() {
    this.previews_.appendChild(box);
    if (--count == 0) {
      done();
    } else {
      this.renderPreview_(entries, count);
    }
  }.bind(this);

  var onError = function() {
    if (entries.length == 0) {
      // Append one image with generic thumbnail.
      this.previews_.appendChild(box);
      done();
    } else {
      this.renderPreview_(entries, count);
    }
  }.bind(this);

  this.metadataCache_.get(entry, 'thumbnail|filesystem',
      function(metadata) {
        new ThumbnailLoader(entry.toURL(),
                            ThumbnailLoader.LoaderType.IMAGE,
                            metadata).load(
            box,
            ThumbnailLoader.FillMode.FILL,
            ThumbnailLoader.OptimizationMode.NEVER_DISCARD,
            onSuccess,
            onError,
            onError);
      });
};

/**
 * Closes the window.
 * @private
 */
ActionChoice.prototype.close_ = function() {
  window.close();
};

/**
 * Keydown event handler.
 * @param {Event} e The event.
 * @private
 */
ActionChoice.prototype.onKeyDown_ = function(e) {
  switch (util.getKeyModifiers(e) + e.keyCode) {
    case '13':
      this.onOk_();
      return;
    case '27':
      this.recordAction_('close');
      this.close_();
      return;
  }
};

/**
 * Called when OK button clicked.
 * @param {Event} event The event object.
 * @private
 */
ActionChoice.prototype.onOk_ = function(event) {
  // Check for click on the disabled choice.
  var input = event.currentTarget.querySelector('input');
  if (input && input.disabled) return;

  if (this.document_.querySelector('#import-photos-to-drive').checked) {
    var url = util.platform.getURL('photo_import.html') +
        '#' + this.sourceEntry_.fullPath;
    var width = 728;
    var height = 656;
    var top = Math.round((window.screen.availHeight - height) / 2);
    var left = Math.round((window.screen.availWidth - width) / 2);
    util.platform.createWindow(url,
        {height: height, width: width, left: left, top: top});
    this.recordAction_('import-photos-to-drive');
  } else if (this.document_.querySelector('#view-files').checked) {
    this.viewFiles_();
    this.recordAction_('view-files');
  } else if (this.document_.querySelector('#watch-single-video').checked) {
    chrome.fileBrowserPrivate.viewFiles([this.singleVideo_.toURL()], 'watch',
        function(success) {});
    this.recordAction_('watch-single-video');
  }
  this.close_();
};

/**
 * Called when some device is unmounted.
 * @param {Event} event Event object.
 * @private
 */
ActionChoice.prototype.onDeviceUnmounted_ = function(event) {
  if (this.sourceEntry_ && event.mountPath == this.sourceEntry_.fullPath) {
    util.platform.closeWindow();
  }
};

/**
 * Perform the 'view files' action.
 * @private
 */
ActionChoice.prototype.viewFiles_ = function() {
  var path = this.sourceEntry_.fullPath;
  if (util.platform.v2()) {
    chrome.runtime.getBackgroundPage(function(bg) {
      bg.launchFileManager({defaultPath: path});
    });
  } else {
    var url = util.platform.getURL('main.html') + '#' + path;
    chrome.fileBrowserPrivate.openNewWindow(url);
  }
};

/**
 * Records an action chosen.
 * @param {string} action Action name.
 * @private
 */
ActionChoice.prototype.recordAction_ = function(action) {
  metrics.recordEnum('PhotoImport.Action', action,
      ['import-photos-to-drive',
       'view-files',
       'view-files-auto',
       'watch-single-video',
       'error',
       'close']);
};
<|endoftext|>