<commit_before>const { snakeCase } = require('lodash');
const url = require('url');
const Generator = require('../../lib/generator');
const j = require('../../lib/transform');

module.exports = class ConnectionGenerator extends Generator {
  constructor (args, opts) {
    super(args, opts);

    this.dependencies = [];
  }

  _transformCode (code) {
    const { adapter } = this.props;

    const ast = j(code);
    const appDeclaration = ast.findDeclaration('app');
    const configureHooks = ast.findConfigure('hooks');
    const requireCall = `const ${adapter} = require('./${adapter}');`;

    if (appDeclaration.length === 0) {
      throw new Error('Could not find \'app\' variable declaration in app.js to insert database configuration. Did you modify app.js?');
    }

    if (configureHooks.length === 0) {
      throw new Error('Could not find .configure(hooks()) call in app.js after which to insert database configuration. Did you modify app.js?');
    }

    appDeclaration.insertBefore(requireCall);
    configureHooks.insertAfter(`app.configure(${adapter});`);

    return ast.toSource();
  }

  _getConfiguration () {
    const sqlPackages = {
      mariadb: 'mysql',
      mysql: 'mysql2',
      mssql: 'tedious',
      postgres: 'pg',
      sqlite: 'sqlite3'
      // oracle: 'oracle'
    };

    const { connectionString, database, adapter } = this.props;
    const parsed = url.parse(connectionString);

    switch (database) {
    case 'nedb':
      this.dependencies.push('nedb');
      return connectionString.substring(7, connectionString.length);

    case 'rethinkdb':
      this.dependencies.push('rethinkdbdash');
      return {
        db: parsed.path.substring(1, parsed.path.length),
        servers: [
          {
            host: parsed.hostname,
            port: parsed.port
          }
        ]
      };

    case 'memory':
      return null;

    case 'mongodb':
      this.dependencies.push(adapter);
      return connectionString;

    case 'mariadb':
    case 'mysql':
    case 'mssql':
    // case oracle:
    case 'postgres': // eslint-disable-line no-fallthrough
    case 'sqlite':
      this.dependencies.push(adapter);

      if (sqlPackages[database]) {
        this.dependencies.push(sqlPackages[database]);
      }

      if (adapter === 'sequelize') {
        return connectionString;
      }

      return {
        client: sqlPackages[database],
        connection: database === 'sqlite' ? {
          filename: connectionString.substring(9, connectionString.length)
        } : connectionString
      };

    default:
      throw new Error(`Invalid database '${database}'. Cannot assemble configuration.`);
    }
  }

  _writeConfiguration () {
    const { database } = this.props;
    const config = Object.assign({}, this.defaultConfig);
    const configuration = this._getConfiguration();

    if (!config[database]) {
      config[database] = configuration;

      this.conflicter.force = true;
      this.fs.writeJSON(
        this.destinationPath('config', 'default.json'),
        config
      );
    }
  }

  prompting () {
    this.checkPackage();

    const databaseName = snakeCase(this.pkg.name);
    const { defaultConfig } = this;

    const getProps = answers => Object.assign({}, this.props, answers);
    const setProps = props => Object.assign(this.props, props);

    const prompts = [
      {
        type: 'list',
        name: 'database',
        message: 'Which database are you connecting to?',
        default: 'nedb',
        choices: [
          { name: 'MariaDB', value: 'mariadb' },
          { name: 'Memory', value: 'memory' },
          { name: 'MongoDB', value: 'mongodb' },
          { name: 'MySQL', value: 'mysql' },
          { name: 'NeDB', value: 'nedb' },
          // { name: 'Oracle', value: 'oracle' },
          { name: 'PostgreSQL', value: 'postgres' },
          { name: 'RethinkDB', value: 'rethinkdb' },
          { name: 'SQLite', value: 'sqlite' },
          { name: 'SQL Server', value: 'mssql' }
        ],
        when (current) {
          const answers = getProps(current);
          const { database, adapter } = answers;

          if (database) {
            return false;
          }

          switch (adapter) {
          case 'nedb':
          case 'rethinkdb':
          case 'memory':
          case 'mongodb':
            setProps({ database: adapter });
            return false;
          case 'mongoose':
            setProps({ database: 'mongodb' });
            return false;
          }

          return true;
        }
      },
      {
        type: 'list',
        name: 'adapter',
        message: 'Which database adapter would you like to use?',
        default (current) {
          const answers = getProps(current);
          const { database } = answers;

          if (database === 'mongodb') {
            return 'mongoose';
          }

          return 'sequelize';
        },
        choices (current) {
          const answers = getProps(current);
          const { database } = answers;
          const mongoOptions = [
            { name: 'MongoDB Native', value: 'mongodb' },
            { name: 'Mongoose', value: 'mongoose' }
          ];
          const sqlOptions = [
            { name: 'Sequelize', value: 'sequelize' },
            { name: 'KnexJS', value: 'knex' }
          ];

          if (database === 'mongodb') {
            return mongoOptions;
          }

          // It's an SQL DB
          return sqlOptions;
        },
        when (current) {
          const answers = getProps(current);
          const { database, adapter } = answers;

          if (adapter) {
            return false;
          }

          switch (database) {
          case 'nedb':
          case 'rethinkdb':
          case 'memory':
            return false;
          }

          return true;
        }
      },
      {
        name: 'connectionString',
        message: 'What is the database connection string?',
        default (current) {
          const answers = getProps(current);
          const { database } = answers;
          const defaultConnectionStrings = {
            mariadb: `mariadb://root:@localhost:3306/${databaseName}`,
            mongodb: `mongodb://localhost:27017/${databaseName}`,
            mysql: `mysql://root:@localhost:3306/${databaseName}`,
            nedb: 'nedb://../data',
            // oracle: `oracle://root:password@localhost:1521/${databaseName}`,
            postgres: `postgres://postgres:@localhost:5432/${databaseName}`,
            rethinkdb: `rethinkdb://localhost:28015/${databaseName}`,
            sqlite: `sqlite://${databaseName}.sqlite`,
            mssql: `mssql://root:password@localhost:1433/${databaseName}`
          };

          return defaultConnectionStrings[database];
        },
        when (current) {
          const answers = getProps(current);
          const { database } = answers;
          const connection = defaultConfig[database];

          if (connection) {
            if (connection.connection){
              setProps({ connectionString:connection.connection });
            } else if (database === 'rethinkdb' && connection.db) {
              setProps({ connectionString:`rethinkdb://${connection.servers[0].host}:${connection.servers[0].port}/${connection.db}` });
            } else {
              setProps({ connectionString:connection });
            }
            return false;
          }

          return database !== 'memory';
        }
      }
    ];

    return this.prompt(prompts).then(props => {
      this.props = Object.assign(this.props, props);
    });
  }

  writing () {
    let template;
    const { database, adapter } = this.props;
    const context = Object.assign({}, this.props);

    if (database === 'rethinkdb') {
      template = 'rethinkdb.js';
    } else if (adapter && adapter !== 'nedb') {
      template = database === 'mssql' ? `${adapter}-mssql.js` : `${adapter}.js`;
    }

    if (template) {
      const dbFile = `${adapter}.js`;
      const templateExists = this.fs.exists(this.destinationPath(this.libDirectory, dbFile));

      // If the file doesn't exist yet, add it to the app.js
      if (!templateExists) {
        const appjs = this.destinationPath(this.libDirectory, 'app.js');

        this.conflicter.force = true;
        this.fs.write(appjs, this._transformCode(
          this.fs.read(appjs).toString()
        ));
      }

      // Copy template only if connection generate is not composed
      // from the service generator
      if(!templateExists || (templateExists && !this.props.service)) {
        this.fs.copyTpl(
          this.templatePath(template),
          this.destinationPath(this.libDirectory, dbFile),
          context
        );
      }
    }

    this._writeConfiguration();

    this._packagerInstall(this.dependencies, {
      save: true
    });
  }

  end () {
    const { database, connectionString } = this.props;

    // NOTE (EK): If this is the first time we set this up
    // show this nice message.
    if (connectionString && !this.defaultConfig[database]) {
      const databaseName = snakeCase(this.pkg.name);
      this.log();
      this.log(`Woot! We've set up your ${database} database connection!`);

      switch (database) {
      case 'mariadb':
      case 'mongodb':
      case 'mssql':
      case 'mysql':
      // case 'oracle':
      case 'postgres': // eslint-disable-line no-fallthrough
      case 'rethinkdb':
        this.log(`Make sure that your ${database} database is running, the username/role is correct, and the database "${databaseName}" has been created.`);
        this.log('Your configuration can be found in the projects config/ folder.');
        break;
      }
    }
  }
};
<commit_msg>fix(knex): Fix knex + sql server issues when using authentication generator (#257)<commit_after>const { snakeCase } = require('lodash');
const url = require('url');
const Generator = require('../../lib/generator');
const j = require('../../lib/transform');

module.exports = class ConnectionGenerator extends Generator {
  constructor (args, opts) {
    super(args, opts);

    this.dependencies = [];
  }

  _transformCode (code) {
    const { adapter } = this.props;

    const ast = j(code);
    const appDeclaration = ast.findDeclaration('app');
    const configureHooks = ast.findConfigure('hooks');
    const requireCall = `const ${adapter} = require('./${adapter}');`;

    if (appDeclaration.length === 0) {
      throw new Error('Could not find \'app\' variable declaration in app.js to insert database configuration. Did you modify app.js?');
    }

    if (configureHooks.length === 0) {
      throw new Error('Could not find .configure(hooks()) call in app.js after which to insert database configuration. Did you modify app.js?');
    }

    appDeclaration.insertBefore(requireCall);
    configureHooks.insertAfter(`app.configure(${adapter});`);

    return ast.toSource();
  }

  _getConfiguration () {
    const sqlPackages = {
      mariadb: 'mysql',
      mysql: 'mysql2',
      mssql: 'tedious',
      postgres: 'pg',
      sqlite: 'sqlite3'
      // oracle: 'oracle'
    };

    const { connectionString, database, adapter } = this.props;
    const parsed = url.parse(connectionString);

    switch (database) {
    case 'nedb':
      this.dependencies.push('nedb');
      return connectionString.substring(7, connectionString.length);

    case 'rethinkdb':
      this.dependencies.push('rethinkdbdash');
      return {
        db: parsed.path.substring(1, parsed.path.length),
        servers: [
          {
            host: parsed.hostname,
            port: parsed.port
          }
        ]
      };

    case 'memory':
      return null;

    case 'mongodb':
      this.dependencies.push(adapter);
      return connectionString;

    case 'mariadb':
    case 'mysql':
    case 'mssql':
    // case oracle:
    case 'postgres': // eslint-disable-line no-fallthrough
    case 'sqlite':
      this.dependencies.push(adapter);

      if (sqlPackages[database]) {
        this.dependencies.push(sqlPackages[database]);
      }

      if (adapter === 'sequelize') {
        return connectionString;
      }

      return {
        client: sqlPackages[database],
        connection: database === 'sqlite' ? {
          filename: connectionString.substring(9, connectionString.length)
        } : connectionString
      };

    default:
      throw new Error(`Invalid database '${database}'. Cannot assemble configuration.`);
    }
  }

  _writeConfiguration () {
    const { database } = this.props;
    const config = Object.assign({}, this.defaultConfig);
    const configuration = this._getConfiguration();

    if (!config[database]) {
      config[database] = configuration;

      this.conflicter.force = true;
      this.fs.writeJSON(
        this.destinationPath('config', 'default.json'),
        config
      );
    }
  }

  prompting () {
    this.checkPackage();

    const databaseName = snakeCase(this.pkg.name);
    const { defaultConfig } = this;

    const getProps = answers => Object.assign({}, this.props, answers);
    const setProps = props => Object.assign(this.props, props);

    const prompts = [
      {
        type: 'list',
        name: 'database',
        message: 'Which database are you connecting to?',
        default: 'nedb',
        choices: [
          { name: 'MariaDB', value: 'mariadb' },
          { name: 'Memory', value: 'memory' },
          { name: 'MongoDB', value: 'mongodb' },
          { name: 'MySQL', value: 'mysql' },
          { name: 'NeDB', value: 'nedb' },
          // { name: 'Oracle', value: 'oracle' },
          { name: 'PostgreSQL', value: 'postgres' },
          { name: 'RethinkDB', value: 'rethinkdb' },
          { name: 'SQLite', value: 'sqlite' },
          { name: 'SQL Server', value: 'mssql' }
        ],
        when (current) {
          const answers = getProps(current);
          const { database, adapter } = answers;

          if (database) {
            return false;
          }

          switch (adapter) {
          case 'nedb':
          case 'rethinkdb':
          case 'memory':
          case 'mongodb':
            setProps({ database: adapter });
            return false;
          case 'mongoose':
            setProps({ database: 'mongodb' });
            return false;
          }

          return true;
        }
      },
      {
        type: 'list',
        name: 'adapter',
        message: 'Which database adapter would you like to use?',
        default (current) {
          const answers = getProps(current);
          const { database } = answers;

          if (database === 'mongodb') {
            return 'mongoose';
          }

          return 'sequelize';
        },
        choices (current) {
          const answers = getProps(current);
          const { database } = answers;
          const mongoOptions = [
            { name: 'MongoDB Native', value: 'mongodb' },
            { name: 'Mongoose', value: 'mongoose' }
          ];
          const sqlOptions = [
            { name: 'Sequelize', value: 'sequelize' },
            { name: 'KnexJS', value: 'knex' }
          ];

          if (database === 'mongodb') {
            return mongoOptions;
          }

          // It's an SQL DB
          return sqlOptions;
        },
        when (current) {
          const answers = getProps(current);
          const { database, adapter } = answers;

          if (adapter) {
            return false;
          }

          switch (database) {
          case 'nedb':
          case 'rethinkdb':
          case 'memory':
            return false;
          }

          return true;
        }
      },
      {
        name: 'connectionString',
        message: 'What is the database connection string?',
        default (current) {
          const answers = getProps(current);
          const { database } = answers;
          const defaultConnectionStrings = {
            mariadb: `mariadb://root:@localhost:3306/${databaseName}`,
            mongodb: `mongodb://localhost:27017/${databaseName}`,
            mysql: `mysql://root:@localhost:3306/${databaseName}`,
            nedb: 'nedb://../data',
            // oracle: `oracle://root:password@localhost:1521/${databaseName}`,
            postgres: `postgres://postgres:@localhost:5432/${databaseName}`,
            rethinkdb: `rethinkdb://localhost:28015/${databaseName}`,
            sqlite: `sqlite://${databaseName}.sqlite`,
            mssql: `mssql://root:password@localhost:1433/${databaseName}`
          };

          return defaultConnectionStrings[database];
        },
        when (current) {
          const answers = getProps(current);
          const { database } = answers;
          const connection = defaultConfig[database];

          if (connection) {
            if (connection.connection){
              setProps({ connectionString:connection.connection });
            } else if (database === 'rethinkdb' && connection.db) {
              setProps({ connectionString:`rethinkdb://${connection.servers[0].host}:${connection.servers[0].port}/${connection.db}` });
            } else {
              setProps({ connectionString:connection });
            }
            return false;
          }

          return database !== 'memory';
        }
      }
    ];

    return this.prompt(prompts).then(props => {
      this.props = Object.assign(this.props, props);
    });
  }

  writing () {
    let template;
    const { database, adapter } = this.props;
    const context = Object.assign({}, this.props);

    if (database === 'rethinkdb') {
      template = 'rethinkdb.js';
    } else if (database === 'mssql' && adapter === 'sequelize') {
      template = `${adapter}-mssql.js`;
    } else if (adapter && adapter !== 'nedb') {
      template = `${adapter}.js`;
    }

    if (template) {
      const dbFile = `${adapter}.js`;
      const templateExists = this.fs.exists(this.destinationPath(this.libDirectory, dbFile));

      // If the file doesn't exist yet, add it to the app.js
      if (!templateExists) {
        const appjs = this.destinationPath(this.libDirectory, 'app.js');

        this.conflicter.force = true;
        this.fs.write(appjs, this._transformCode(
          this.fs.read(appjs).toString()
        ));
      }

      // Copy template only if connection generate is not composed
      // from the service generator
      if(!templateExists || (templateExists && !this.props.service)) {
        this.fs.copyTpl(
          this.templatePath(template),
          this.destinationPath(this.libDirectory, dbFile),
          context
        );
      }
    }

    this._writeConfiguration();

    this._packagerInstall(this.dependencies, {
      save: true
    });
  }

  end () {
    const { database, connectionString } = this.props;

    // NOTE (EK): If this is the first time we set this up
    // show this nice message.
    if (connectionString && !this.defaultConfig[database]) {
      const databaseName = snakeCase(this.pkg.name);
      this.log();
      this.log(`Woot! We've set up your ${database} database connection!`);

      switch (database) {
      case 'mariadb':
      case 'mongodb':
      case 'mssql':
      case 'mysql':
      // case 'oracle':
      case 'postgres': // eslint-disable-line no-fallthrough
      case 'rethinkdb':
        this.log(`Make sure that your ${database} database is running, the username/role is correct, and the database "${databaseName}" has been created.`);
        this.log('Your configuration can be found in the projects config/ folder.');
        break;
      }
    }
  }
};
<|endoftext|>


<commit_before>var app = angular.module('CBEcalc', []);

app.factory('classList', [function(){
  var o = {
    classList: []
  };
  return o;
}]);

app.factory('classPrefixes', [function(){
  var c = {
    classPrefixes: []
  };
  return c;
}]);

app.controller('MainCtrl', [
  '$scope',
  'classList',
  'classPrefixes',
  function($scope, classList, classPrefixes){
    $scope.classList = classList.classList;
    $scope.previousGPA = [];
    $scope.classPrefixes = classPrefixes.classPrefixes;
    $scope.gpa = (0.0).toFixed(2);
    $scope.totalCredits = 0;

    $scope.addClass = function(){
      if(!$scope.name || $scope.name === ''){
        return;
      }
      if(!$scope.grade || $scope.grade === ''){
        return;
      }
      if(!$scope.credits || $scope.credits === '' || $scope.credits != parseInt($scope.credits, 10)){
        return;
      }

      var gpa = 0;
      var tempGrade = $scope.grade;
      var letter = tempGrade.substring(0,1);
      var mod = '';
      if(tempGrade.length >= 2){
        mod = tempGrade.substring(1,2);
        if(!(mod === '+' || mod ==='-')){
          mod = '';
        }
      }
      if(letter === "a" || letter === 'A'){
        gpa = 4;
      }else if(letter === "b" || letter === 'B'){
        gpa = 3;
      }else if(letter === "c" || letter === 'C'){
        gpa = 2;
      }else if(letter === "d" || letter === 'D'){
        gpa = 1;
      }else if(letter === "f" || letter === 'F'){
        gpa = 0;
      }else{
        return;
      }

      if(mod === '+' && gpa < 4){
        gpa += 0.3;
      }else if(mod === '-'){
        gpa -= 0.3;
      }

      $scope.classList.push({
        name: $scope.name.substring(0,15),
        grade: letter.toUpperCase() + mod,
        gpa: gpa.toFixed(2),
        credits: $scope.credits
      });

      $scope.name = '';
      $scope.grade = '';
      $scope.credits = '';

      $scope.setGpa();

      return;
    };

    $scope.updatePrevious = function() {
      console.log("made it into function");
      console.log($scope.prevGPA);
      console.log($scope.prevCredits);
      if(!$scope.prevGPA || $scope.prevGPA === ''){
        return;
      }
      if(parseInt($scope.prevGPA) > 4){
        return;
      }
      if(!$scope.prevCredits || $scope.prevCredits === ''){
        return;
      }
      if($scope.prevCredits != parseInt($scope.prevCredits, 10)){
        return;
      }
      if($scope.previousGPA.length > 0){
        $scope.previousGPA.splice(0, $scope.previousGPA.length);
      }

      $scope.previousGPA.push({
        gpa: parseFloat($scope.prevGPA).toFixed(2),
        prevCredits: parseInt($scope.prevCredits)
      });

      $scope.prevGPA = '';
      $scope.prevCredits = '';

      $scope.setGpa();

      return;
    };

    $scope.setGpa = function() {
      var gpa = 0.00;
      var credits = 0.00;

      if($scope.previousGPA.length > 0){
        gpa = $scope.previousGPA[0].gpa * $scope.previousGPA[0].prevCredits;
        credits = $scope.previousGPA[0].prevCredits;
      }

      for(var i = 0 ; i < $scope.classList.length ; i++){
        gpa += (+$scope.classList[i].gpa * +$scope.classList[i].credits);
        credits += +$scope.classList[i].credits;
      }
      if(gpa != 0){
        gpa = gpa / credits;
      }
      $scope.totalCredits = credits;
      $scope.gpa = gpa.toFixed(2);
    };

    $scope.removeClass = function(item) {
      var index = $scope.classList.indexOf(item);
      $scope.classList.splice(index, 1);
      $scope.setGpa();
    };
    /* Proof of concept to fetch page content */
    $scope.updateDOMInfo = function(info){
      document.getElementById('total').textContent = info.total;
      document.getElementById('inputs').textContent = info.inputs;
      document.getElementById('buttons').textContent = info.buttons;
      document.getElementById('data').textContent = info.data; //Actual text
    };
    /* Function to scrape text off page and parse out class information */
    $scope.addPrevClasses = function(info){
      var localData = String(info.data);
      console.log(data);
      var lines = localData.split('\n');

      for(var i = 0 ; i < lines.length ; i++){
        $scope.classList.push({
          name: $scope.name,
          grade: 'A',
          gpa: 4,
          credits: 4
        });
      }
    };
  }
]);

// Update the relevant fields with the new data
function setDOMInfo(info) {
  var scope = angular.element(document.getElementById("main")).scope();
  scope.$apply(function(){
    scope.addPrevClasses(info);
  });
}

// Once the DOM is ready...
window.addEventListener('DOMContentLoaded', function () {
  // ...query for the active tab...
  chrome.tabs.query({
    active: true,
    currentWindow: true
  }, function (tabs) {
    // ...and send a request for the DOM info...
    chrome.tabs.sendMessage(
        tabs[0].id,
        {from: 'popup', subject: 'DOMInfo'},
        // ...also specifying a callback to be called
        //    from the receiving end (content script)
        setDOMInfo);
  });
});
<commit_msg>Fixed data not defined error<commit_after>var app = angular.module('CBEcalc', []);

app.factory('classList', [function(){
  var o = {
    classList: []
  };
  return o;
}]);

app.factory('classPrefixes', [function(){
  var c = {
    classPrefixes: []
  };
  return c;
}]);

app.controller('MainCtrl', [
  '$scope',
  'classList',
  'classPrefixes',
  function($scope, classList, classPrefixes){
    $scope.classList = classList.classList;
    $scope.previousGPA = [];
    $scope.classPrefixes = classPrefixes.classPrefixes;
    $scope.gpa = (0.0).toFixed(2);
    $scope.totalCredits = 0;

    $scope.addClass = function(){
      if(!$scope.name || $scope.name === ''){
        return;
      }
      if(!$scope.grade || $scope.grade === ''){
        return;
      }
      if(!$scope.credits || $scope.credits === '' || $scope.credits != parseInt($scope.credits, 10)){
        return;
      }

      var gpa = 0;
      var tempGrade = $scope.grade;
      var letter = tempGrade.substring(0,1);
      var mod = '';
      if(tempGrade.length >= 2){
        mod = tempGrade.substring(1,2);
        if(!(mod === '+' || mod ==='-')){
          mod = '';
        }
      }
      if(letter === "a" || letter === 'A'){
        gpa = 4;
      }else if(letter === "b" || letter === 'B'){
        gpa = 3;
      }else if(letter === "c" || letter === 'C'){
        gpa = 2;
      }else if(letter === "d" || letter === 'D'){
        gpa = 1;
      }else if(letter === "f" || letter === 'F'){
        gpa = 0;
      }else{
        return;
      }

      if(mod === '+' && gpa < 4){
        gpa += 0.3;
      }else if(mod === '-'){
        gpa -= 0.3;
      }

      $scope.classList.push({
        name: $scope.name.substring(0,15),
        grade: letter.toUpperCase() + mod,
        gpa: gpa.toFixed(2),
        credits: $scope.credits
      });

      $scope.name = '';
      $scope.grade = '';
      $scope.credits = '';

      $scope.setGpa();

      return;
    };

    $scope.updatePrevious = function() {
      console.log("made it into function");
      console.log($scope.prevGPA);
      console.log($scope.prevCredits);
      if(!$scope.prevGPA || $scope.prevGPA === ''){
        return;
      }
      if(parseInt($scope.prevGPA) > 4){
        return;
      }
      if(!$scope.prevCredits || $scope.prevCredits === ''){
        return;
      }
      if($scope.prevCredits != parseInt($scope.prevCredits, 10)){
        return;
      }
      if($scope.previousGPA.length > 0){
        $scope.previousGPA.splice(0, $scope.previousGPA.length);
      }

      $scope.previousGPA.push({
        gpa: parseFloat($scope.prevGPA).toFixed(2),
        prevCredits: parseInt($scope.prevCredits)
      });

      $scope.prevGPA = '';
      $scope.prevCredits = '';

      $scope.setGpa();

      return;
    };

    $scope.setGpa = function() {
      var gpa = 0.00;
      var credits = 0.00;

      if($scope.previousGPA.length > 0){
        gpa = $scope.previousGPA[0].gpa * $scope.previousGPA[0].prevCredits;
        credits = $scope.previousGPA[0].prevCredits;
      }

      for(var i = 0 ; i < $scope.classList.length ; i++){
        gpa += (+$scope.classList[i].gpa * +$scope.classList[i].credits);
        credits += +$scope.classList[i].credits;
      }
      if(gpa != 0){
        gpa = gpa / credits;
      }
      $scope.totalCredits = credits;
      $scope.gpa = gpa.toFixed(2);
    };

    $scope.removeClass = function(item) {
      var index = $scope.classList.indexOf(item);
      $scope.classList.splice(index, 1);
      $scope.setGpa();
    };
    /* Proof of concept to fetch page content */
    $scope.updateDOMInfo = function(info){
      document.getElementById('total').textContent = info.total;
      document.getElementById('inputs').textContent = info.inputs;
      document.getElementById('buttons').textContent = info.buttons;
      document.getElementById('data').textContent = info.data; //Actual text
    };
    /* Function to scrape text off page and parse out class information */
    $scope.addPrevClasses = function(info){
      var localData = String(info.data);
      console.log(localData);
      var lines = localData.split('\n');

      for(var i = 0 ; i < lines.length ; i++){
        $scope.classList.push({
          name: $scope.name,
          grade: 'A',
          gpa: 4,
          credits: 4
        });
      }
    };
  }
]);

// Update the relevant fields with the new data
function setDOMInfo(info) {
  var scope = angular.element(document.getElementById("main")).scope();
  scope.$apply(function(){
    scope.addPrevClasses(info);
  });
}

// Once the DOM is ready...
window.addEventListener('DOMContentLoaded', function () {
  // ...query for the active tab...
  chrome.tabs.query({
    active: true,
    currentWindow: true
  }, function (tabs) {
    // ...and send a request for the DOM info...
    chrome.tabs.sendMessage(
        tabs[0].id,
        {from: 'popup', subject: 'DOMInfo'},
        // ...also specifying a callback to be called
        //    from the receiving end (content script)
        setDOMInfo);
  });
});
<|endoftext|>


<commit_before>/**
 * TODO(developer):
 * Add your service key to the current folder.
 * Uncomment and fill in these variables.
 */
// const projectId = 'my-project';
// const locationId = 'global';
// const agentId = 'my-agent';
// const languageCode = 'en'
// const TELEGRAM_TOKEN='1234567898:ABCdfghTtaD8dfghdfgh45sdf65467M';
// const SERVER_URL='https://example.com';

const express = require('express');
const axios = require('axios');
const bodyParser = require('body-parser');

const API_URL = `https://api.telegram.org/bot${TELEGRAM_TOKEN}`;
const URI = `/webhook/${TELEGRAM_TOKEN}`;
const WEBHOOK = SERVER_URL + URI;

const app = express();
app.use(bodyParser.json());

// Imports the Google Cloud Some API library
const {SessionsClient} = require('@google-cloud/dialogflow-cx');
/**
 * Example for regional endpoint:
 *   const location = 'us-central1'
 *   const client = new SessionsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'})
 */
const client = new SessionsClient();

/**
 * Calls the Dialogflow CX API with the specific user query input and returns a string
 * from the API with a response for the users query depending on the matched intent.
 * The console.log() and console.info lines are included purely for debugging purposes
 * and and don't impact the end users experience.
 */
async function detectIntentText(query,chatId) {
  let agentResponse = '';

  const sessionId = chatId;
  const sessionPath = client.projectLocationAgentSessionPath(
      projectId,
      location,
      agentId,
      sessionId
  );
  console.info(sessionPath);

  const request = {
    session: sessionPath,
    queryInput: {
      text: {
        text: query,
      },
      languageCode,
    },
  };
  const [response] = await client.detectIntent(request);
  console.log(`User Query: ${query}`);
  for (const message of response.queryResult.responseMessages) {
    if (message.text) {
      console.log(`${message.text.text}`);
      agentResponse += `${message.text.text}\n`;
    }

  }
  if (response.queryResult.match.intent) {
    console.log(
        `Matched Intent: ${response.queryResult.match.intent.displayName}`
    );
  }
  console.log(
      `Current Page: ${response.queryResult.currentPage.displayName}`
  );

  return agentResponse;
}

const setup = async () => {
    const res = await axios.post(`${API_URL}/setWebhook`, {url: WEBHOOK});
    console.log(res.data);
};

app.post(URI, async (req, res) => {
    console.log(req.body)
    const chatId = req.body.message.chat.id;
    const text = await detectIntentText(req.body.message.text,chatId);
    await axios.post(`${API_URL}/sendMessage`, {
        chat_id: chatId,
        text: text
    });
    return res.send();
});

const listener = app.listen(process.env.PORT, async () => {
    console.log('Your Dialogflow integration server is listening on port '
    + listener.address().port);

    await setup();
});
<commit_msg>Update server.js<commit_after>/**
 * TODO(developer):
 * Add your service key to the current folder.
 * Uncomment and fill in these variables.
 */
// const projectId = 'my-project';
// const locationId = 'global';
// const agentId = 'my-agent';
// const languageCode = 'en'
// const TELEGRAM_TOKEN='1234567898:ABCdfghTtaD8dfghdfgh45sdf65467M';
// const SERVER_URL='https://example.com';

const express = require('express');
const axios = require('axios');
const bodyParser = require('body-parser');

const API_URL = `https://api.telegram.org/bot${TELEGRAM_TOKEN}`;
const URI = `/webhook/${TELEGRAM_TOKEN}`;
const WEBHOOK = SERVER_URL + URI;

const app = express();
app.use(bodyParser.json());

// Imports the Google Cloud Some API library
const {SessionsClient} = require('@google-cloud/dialogflow-cx');
/**
 * Example for regional endpoint:
 *   const location = 'us-central1'
 *   const client = new SessionsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'})
 */
const client = new SessionsClient({apiEndpoint: locationId + '-dialogflow.googleapis.com'});

/**
 * Calls the Dialogflow CX API with the specific user query input and returns a string
 * from the API with a response for the users query depending on the matched intent.
 * The console.log() and console.info lines are included purely for debugging purposes
 * and and don't impact the end users experience.
 */
async function detectIntentText(query,chatId) {
  let agentResponse = '';

  const sessionId = chatId;
  const sessionPath = client.projectLocationAgentSessionPath(
      projectId,
      location,
      agentId,
      sessionId
  );
  console.info(sessionPath);

  const request = {
    session: sessionPath,
    queryInput: {
      text: {
        text: query,
      },
      languageCode,
    },
  };
  const [response] = await client.detectIntent(request);
  console.log(`User Query: ${query}`);
  for (const message of response.queryResult.responseMessages) {
    if (message.text) {
      console.log(`${message.text.text}`);
      agentResponse += `${message.text.text}\n`;
    }

  }
  if (response.queryResult.match.intent) {
    console.log(
        `Matched Intent: ${response.queryResult.match.intent.displayName}`
    );
  }
  console.log(
      `Current Page: ${response.queryResult.currentPage.displayName}`
  );

  return agentResponse;
}

const setup = async () => {
    const res = await axios.post(`${API_URL}/setWebhook`, {url: WEBHOOK});
    console.log(res.data);
};

app.post(URI, async (req, res) => {
    console.log(req.body)
    const chatId = req.body.message.chat.id;
    const text = await detectIntentText(req.body.message.text,chatId);
    await axios.post(`${API_URL}/sendMessage`, {
        chat_id: chatId,
        text: text
    });
    return res.send();
});

const listener = app.listen(process.env.PORT, async () => {
    console.log('Your Dialogflow integration server is listening on port '
    + listener.address().port);

    await setup();
});
<|endoftext|>


<commit_before>import React from 'react';
import Button from '../button/Button';
import PropTypes from 'prop-types';
import DropdownCaret from './DropdownCaret';

const DropdownButton = ({ hasCaret = false, isOpen, children, ...rest }) => {
    return (
        <Button aria-expanded={isOpen} {...rest}>

                {children}
                {hasCaret && <DropdownCaret isOpen={isOpen} />}

        </Button>
    );
};

DropdownButton.propTypes = {
    hasCaret: PropTypes.bool,
    isOpen: PropTypes.bool,
    children: PropTypes.node
};

export default DropdownButton;
<commit_msg>Hotfix - correct size for arrow in dropdown<commit_after>import React from 'react';
import Button from '../button/Button';
import PropTypes from 'prop-types';
import DropdownCaret from './DropdownCaret';
import { classnames } from 'react-components';

const DropdownButton = ({ className = '', hasCaret = false, isOpen, children, ...rest }) => {
    return (
        <Button className={classnames(['flex-item-noshrink', className])} aria-expanded={isOpen} {...rest}>

                {children}
                {hasCaret && <DropdownCaret isOpen={isOpen} />}

        </Button>
    );
};

DropdownButton.propTypes = {
    hasCaret: PropTypes.bool,
    isOpen: PropTypes.bool,
    children: PropTypes.node,
    className: PropTypes.string
};

export default DropdownButton;
<|endoftext|>


<commit_before>var CHART_OPTS = {
    fontName: 'Sans-Serif',
    fontSize: 10,
    width: 400,
    height:420,
    legend: 'bottom',
    colors:['#2F72FF', '#9FC0FF'],
    chartArea:{top:30}
};

function displayGraphWidgetConfig(widgetId, domainLabel, rangeLabel, link, bagName) {
  jQuery('#widgetdata' + widgetId).hide();
  jQuery('#widgetdatanoresults' + widgetId).hide();
  jQuery('#widgetdatawait' + widgetId).show();
  var extraAttr = getExtraValue(widgetId);
  var wsCall = function wsCall(token) {
    var request_data = {
          widget: widgetId,
          list: bagName,
          filter: extraAttr,
          token: token
      };
    jQuery.getJSON(service + "list/chart", request_data, function(res) {
    if (res.results.length != 0) {
      var viz = google.visualization;
      var data = google.visualization.arrayToDataTable(res.results, false);
      var targetElem = document.getElementById("widgetdata" + widgetId);
      var Chart = null;
      var options = jQuery.extend({}, CHART_OPTS, {title: res.title});
      if (res.chartType == "ColumnChart") {
          Chart = viz.ColumnChart;
          jQuery.extend(options, {reverseCategories: true});
      } else if (res.chartType == "BarChart") {
          Chart = viz.BarChart;
          jQuery.extend(options, {isStacked: true, height: 450});
      } else if (res.chartType == "ScatterPlot") {
          Chart = viz.ScatterChart;
      } else if (res.chartType == "PieChart") {
          Chart = viz.PieChart;
      } else if (res.chartType == "XYLineChart") {
          Chart = viz.LineChart;
      }

      if (domainLabel) {
          jQuery.extend(options, {hAxis: {title: domainLabel, titleTextStyle: {fontName: 'Sans-Serif'}}});
      }
      if (rangeLabel) {
          jQuery.extend(options, {vAxis: {title: rangeLabel, titleTextStyle: {fontName: 'Sans-Serif'}}});
      }
      var viz;
      if (Chart) {
          viz = new Chart(targetElem);
          viz.draw(data, options);
          if (link != "") {
            google.visualization.events.addListener(viz, 'select', function() {
              var selection = viz.getSelection();
              for (var i = 0; i < selection.length; i++) {
                var item = selection[i];
                if (item.row != null && item.column != null) {
                    var category = res.results[item.row + 1][0];
                    var series = res.results[0][item.column];
                    window.location.assign(webappUrl + "queryForGraphAction.do?bagName=" + bagName
                      + "&category=" + category + "&series=" + series + "&urlGen=" + link);
                } else if (item.row != null) {
                  category = res.results[item.row + 1][0];
                  window.location.assign(webappUrl + "queryForGraphAction.do?bagName=" + bagName
                          + "&category=" + category + "&series=&urlGen=" + link);
                }
              }
            });
          }
      } else {
          alert("Don't know how to draw " + res.chartType + "s yet!");
      }
      jQuery('#widgetdata' + widgetId).show();
    } else {
        jQuery('#widgetdatanoresults' + widgetId).show();
    }
    jQuery('#widgetdatawait' + widgetId).hide();
    calcNotAnalysed(widgetId, res.notAnalysed);
  });
  }
  AjaxServices.getSingleUseKey(wsCall);
}

function getExtraValue(widgetId) {
  var extraAttr;
  var extraAttrForm = document.getElementById("widgetselect" + widgetId);
  if(extraAttrForm != null) {
    extraAttr = extraAttrForm.value;
  }
  return extraAttr;
 }

function getProcessHTMLWidgetConfig(widgetId, bagName) {
  AjaxServices.getProcessHTMLWidget(widgetId, bagName, handleHTMLWidget);
}

function handleHTMLWidget(widget) {
  jQuery('#widgetdata' + widget.configId).hide();
  jQuery('#widgetdatanoresults' + widget.configId).hide();
  jQuery('#widgetdatawait' + widget.configId).show();
}

function getProcessTableWidgetConfig(widgetId, bagName) {
  AjaxServices.getProcessTableWidget(widgetId,bagName,handleTableWidget);
}

function createTableHeader(widgetId, columns) {
   var $row = jQuery('
');

    // checkbox
    var formName = "widgetaction" + widgetId;
    var $checkBoxAll = jQuery('<input />').attr({'type':'checkbox', 'id':'selected_all' + widgetId,
                                                 'name': 'select_all'});
    $checkBoxAll.click(function(){toggleAllChecks(formName, widgetId)});
    $row.append(jQuery('').append($checkBoxAll));
    // column names
    for(var i = 0; i < columns.length ; i++){
      $row.append(jQuery('').text(columns[i]));
    }
    jQuery("#tablewidget"+widgetId+"head").append($row);
}

function handleTableWidget(widget) {
  jQuery('#widgetdata' + widget.configId).hide();
  jQuery('#widgetdatanoresults' + widget.configId).hide();
  jQuery('#widgetdatawait' + widget.configId).show();
  if(widget.hasResults) {
    jQuery("#tablewidget"+widget.configId+"head").empty();
    jQuery("#tablewidget"+widget.configId+"body").empty();

    createTableHeader(widget.configId, widget.columns);

    for(var i = 0; i < widget.flattenedResults.length ; i++) {
      $row = jQuery("
");
      var columns = widget.flattenedResults[i];
      for(var j = 0; j < columns.length ; j++) {
         var $cell = jQuery("");
         if(columns[j]!=null) {
             if(columns[j][1] != null) {
               $a = jQuery('').text(columns[j][0]);
               $a.attr("href",columns[j][1]);
               $cell.append($a);
             } else {
               $cell.text(columns[j][0]);
             }
         }
         $row.append($cell);
      }
      jQuery("#tablewidget"+widget.configId+"body").append($row);
    }

     jQuery('#widgetdatawait' + widget.configId).hide();
     jQuery('#widgetdata' + widget.configId).show();
  } else {
    jQuery('#widgetdatawait' + widget.configId).hide();
    jQuery('#widgetdatanoresults' + widget.configId).show();
  }
  calcNotAnalysed(widget.configId, widget.notAnalysed);
}

function displayEnrichmentWidgetConfig(widgetId, label, bagName) {
    jQuery('#widgetdata' + widgetId).hide();
    jQuery('#widgetdatanoresults' + widgetId).hide();
    jQuery('#widgetdatawait' + widgetId).show();
    var errorCorrection;
    if($("errorCorrection" + widgetId)!=null) {
      errorCorrection = $("errorCorrection" + widgetId).value;
    }
    var max;
    if($("max" + widgetId)!=null) {
      max = $("max" + widgetId).value;
    }
    var extraAttr = getExtraValue(widgetId);

    var wsCall = function wsCall(token) {
      var request_data = {
            widget: widgetId,
            list: bagName,
            correction: errorCorrection,
            maxp: max,
            filter: extraAttr,
            token: token
      };
      jQuery.getJSON(service + "list/enrichment", request_data, function(res) {
        jQuery("#tablewidget"+widgetId+"head").empty();
        jQuery("#tablewidget"+widgetId+"body").empty();
        var results = res.results;
        if (results.length != 0) {
          var columns = [label, "p-Value", "Matches"];
          createTableHeader(widgetId, columns)

          //table
          var $table = jQuery("#tablewidget"+widgetId+"body").empty();
          var i = 0;
          var externalLink;
          if($("externalLink" + widgetId)!=null) {
           externalLink = $("externalLink" + widgetId).value;
          }

          var externalLinkLabel;
          if($("externalLinkLabel" + widgetId)!=null) {
            externalLinkLabel = $("externalLinkLabel" + widgetId).value;
          }
          for (i in results) {
            $table.append(make_enrichment_row(results[i], externalLink, externalLinkLabel));
          }
          jQuery('#widgetdata' + widgetId).show();
        } else {
          jQuery('#widgetdatanoresults' + widgetId).show();
        }
        jQuery('#widgetdatawait' + widgetId).hide();
        calcNotAnalysed(widgetId, res.notAnalysed);
    });
  }

  AjaxServices.getSingleUseKey(wsCall);
}

function make_enrichment_row(result, externalLink, externalLinkLabel) {
    var $row = jQuery('
');
    var $checkBox = jQuery('<input />').attr({'type':'checkbox', 'id':'selected_' +result.item,
                                             'value': result.item, 'name': 'selected'});
    $row.append(jQuery('').append($checkBox));

    if (result.description) {
        $td = jQuery('').text(result.description + ' ');
        if(externalLink) {
          var label;
          if (externalLinkLabel != undefined) {
            label = externalLinkLabel;
          }
          label = label + result.item;
          $a = jQuery('').addClass('extlink').text('[' + label + ']');
          $a.attr({'target': '_new', 'href': externalLink + result.item});
          $td.append($a);
        }
        $row.append($td);
    } else {
        $row.append(jQuery('').html("no description"));
    }
    $row.append(jQuery('').text(result["p-value"]));
    var $count = jQuery('').addClass("match-count").text(result.matches.length);
    var $matches = jQuery('
');
    $matches.css({"display": "none"});
    var $list = jQuery('
');
    var i = 0;
    for (i in result.matches) {
        $list.append(jQuery('
').text(result.matches[i]));
    }
    $matches.append($list);
    $count.append($matches);
    $count.click(function() {$matches.slideToggle()});
    $row.append(jQuery('').append($count));
    return $row;
}

function checkSelected(formName) {
  var form = document.getElementById(formName);
  var elts = form.getElementsByTagName("input");
  for(var i=0;i<elts.length;i++) {
    if( elts[i].name=='selected' && elts[i].checked) {
      return true;
    }
  }
  return false;
}

function submitWidgetForm(widgetId,type,extra) {
    if (document.getElementById('selected_all' + widgetId) != null) {
        var formName = 'widgetaction'+widgetId;
        if(formName && !checkSelected(formName)) {
            document.getElementById('selected_all' + widgetId).checked = true;
            toggleAllChecks(formName, widgetId);
        }
        $('action'+widgetId).value=type;
        $('export' + widgetId).value=extra;
        $('widgetaction' + widgetId).submit();
    }
}

function calcNotAnalysed(widgetId, notAnalysed) {
    var isMSIE = /*@cc_on!@*/false;
    if (!isMSIE) {
        document.getElementById('widgetnotanalysed' + widgetId).innerHTML=notAnalysed;
    }
}

function toggleAllChecks(formName, widgetId) {
  var checked = document.getElementById('selected_all' + widgetId).checked;
  var form = document.getElementById(formName);
  var elts = form.getElementsByTagName("input");
  for(var i=0;i<elts.length;i++) {
    if( elts[i].name=='selected') {
        elts[i].checked=checked;
    }
  }
}<commit_msg>GraphWIdgets generated automatically starting from a new configuration in the webconfig-model.xml<commit_after>var CHART_OPTS = {
    fontName: 'Sans-Serif',
    fontSize: 09,
    width: 400,
    height:450,
    legend: 'bottom',
    colors:['#2F72FF', '#9FC0FF'],
    chartArea:{top:30}
};

function displayGraphWidgetConfig(widgetId, domainLabel, rangeLabel, link, bagName) {
  jQuery('#widgetdata' + widgetId).hide();
  jQuery('#widgetdatanoresults' + widgetId).hide();
  jQuery('#widgetdatawait' + widgetId).show();
  var extraAttr = getExtraValue(widgetId);
  var wsCall = function wsCall(token) {
    var request_data = {
          widget: widgetId,
          list: bagName,
          filter: extraAttr,
          token: token
      };
    jQuery.getJSON(service + "list/chart", request_data, function(res) {
    if (res.results.length != 0) {
      var viz = google.visualization;
      var data = google.visualization.arrayToDataTable(res.results, false);
      var targetElem = document.getElementById("widgetdata" + widgetId);
      var Chart = null;
      var options = jQuery.extend({}, CHART_OPTS, {title: res.title});
      if (res.chartType == "ColumnChart") {
          Chart = viz.ColumnChart;
          jQuery.extend(options, {reverseCategories: true});
      } else if (res.chartType == "BarChart") {
          Chart = viz.BarChart;
          //jQuery.extend(options, {height: 450});
      } else if (res.chartType == "ScatterPlot") {
          Chart = viz.ScatterChart;
      } else if (res.chartType == "PieChart") {
          Chart = viz.PieChart;
      } else if (res.chartType == "XYLineChart") {
          Chart = viz.LineChart;
      }

      if (domainLabel) {
          jQuery.extend(options, {hAxis: {title: rangeLabel, titleTextStyle: {fontName: 'Sans-Serif'}}});
      }
      if (rangeLabel) {
          jQuery.extend(options, {vAxis: {title: domainLabel, titleTextStyle: {fontName: 'Sans-Serif'}}});
      }
      var viz;
      if (Chart) {
          viz = new Chart(targetElem);
          viz.draw(data, options);
          if (link != "") {
            google.visualization.events.addListener(viz, 'select', function() {
              var selection = viz.getSelection();
              for (var i = 0; i < selection.length; i++) {
                var item = selection[i];
                if (item.row != null && item.column != null) {
                    var category = res.results[item.row + 1][0];
                    var series = res.results[0][item.column];
                    window.location.assign(webappUrl + "queryForGraphAction.do?bagName=" + bagName
                      + "&category=" + category + "&series=" + series + "&urlGen=" + link);
                } else if (item.row != null) {
                  category = res.results[item.row + 1][0];
                  window.location.assign(webappUrl + "queryForGraphAction.do?bagName=" + bagName
                          + "&category=" + category + "&series=&urlGen=" + link);
                }
              }
            });
          }
      } else {
          alert("Don't know how to draw " + res.chartType + "s yet!");
      }
      jQuery('#widgetdata' + widgetId).show();
    } else {
        jQuery('#widgetdatanoresults' + widgetId).show();
    }
    jQuery('#widgetdatawait' + widgetId).hide();
    calcNotAnalysed(widgetId, res.notAnalysed);
  });
  }
  AjaxServices.getSingleUseKey(wsCall);
}

function getExtraValue(widgetId) {
  var extraAttr;
  var extraAttrForm = document.getElementById("widgetselect" + widgetId);
  if(extraAttrForm != null) {
    extraAttr = extraAttrForm.value;
  }
  return extraAttr;
 }

function getProcessHTMLWidgetConfig(widgetId, bagName) {
  AjaxServices.getProcessHTMLWidget(widgetId, bagName, handleHTMLWidget);
}

function handleHTMLWidget(widget) {
  jQuery('#widgetdata' + widget.configId).hide();
  jQuery('#widgetdatanoresults' + widget.configId).hide();
  jQuery('#widgetdatawait' + widget.configId).show();
}

function getProcessTableWidgetConfig(widgetId, bagName) {
  AjaxServices.getProcessTableWidget(widgetId,bagName,handleTableWidget);
}

function createTableHeader(widgetId, columns) {
   var $row = jQuery('
');

    // checkbox
    var formName = "widgetaction" + widgetId;
    var $checkBoxAll = jQuery('<input />').attr({'type':'checkbox', 'id':'selected_all' + widgetId,
                                                 'name': 'select_all'});
    $checkBoxAll.click(function(){toggleAllChecks(formName, widgetId)});
    $row.append(jQuery('').append($checkBoxAll));
    // column names
    for(var i = 0; i < columns.length ; i++){
      $row.append(jQuery('').text(columns[i]));
    }
    jQuery("#tablewidget"+widgetId+"head").append($row);
}

function handleTableWidget(widget) {
  jQuery('#widgetdata' + widget.configId).hide();
  jQuery('#widgetdatanoresults' + widget.configId).hide();
  jQuery('#widgetdatawait' + widget.configId).show();
  if(widget.hasResults) {
    jQuery("#tablewidget"+widget.configId+"head").empty();
    jQuery("#tablewidget"+widget.configId+"body").empty();

    createTableHeader(widget.configId, widget.columns);

    for(var i = 0; i < widget.flattenedResults.length ; i++) {
      $row = jQuery("
");
      var columns = widget.flattenedResults[i];
      for(var j = 0; j < columns.length ; j++) {
         var $cell = jQuery("");
         if(columns[j]!=null) {
             if(columns[j][1] != null) {
               $a = jQuery('').text(columns[j][0]);
               $a.attr("href",columns[j][1]);
               $cell.append($a);
             } else {
               $cell.text(columns[j][0]);
             }
         }
         $row.append($cell);
      }
      jQuery("#tablewidget"+widget.configId+"body").append($row);
    }

     jQuery('#widgetdatawait' + widget.configId).hide();
     jQuery('#widgetdata' + widget.configId).show();
  } else {
    jQuery('#widgetdatawait' + widget.configId).hide();
    jQuery('#widgetdatanoresults' + widget.configId).show();
  }
  calcNotAnalysed(widget.configId, widget.notAnalysed);
}

function displayEnrichmentWidgetConfig(widgetId, label, bagName) {
    jQuery('#widgetdata' + widgetId).hide();
    jQuery('#widgetdatanoresults' + widgetId).hide();
    jQuery('#widgetdatawait' + widgetId).show();
    var errorCorrection;
    if($("errorCorrection" + widgetId)!=null) {
      errorCorrection = $("errorCorrection" + widgetId).value;
    }
    var max;
    if($("max" + widgetId)!=null) {
      max = $("max" + widgetId).value;
    }
    var extraAttr = getExtraValue(widgetId);

    var wsCall = function wsCall(tokenId) {
      var request_data = {
            widget: widgetId,
            list: bagName,
            correction: errorCorrection,
            maxp: max,
            filter: extraAttr,
            token: tokenId
      };
      jQuery.getJSON(service + "list/enrichment", request_data, function(res) {
        jQuery("#tablewidget"+widgetId+"head").empty();
        jQuery("#tablewidget"+widgetId+"body").empty();
        var results = res.results;
        if (results.length != 0) {
          var columns = [label, "p-Value", "Matches"];
          createTableHeader(widgetId, columns)

          //table
          var $table = jQuery("#tablewidget"+widgetId+"body").empty();
          var i = 0;
          var externalLink;
          if($("externalLink" + widgetId)!=null) {
           externalLink = $("externalLink" + widgetId).value;
          }

          var externalLinkLabel;
          if($("externalLinkLabel" + widgetId)!=null) {
            externalLinkLabel = $("externalLinkLabel" + widgetId).value;
          }
          for (i in results) {
            $table.append(make_enrichment_row(results[i], externalLink, externalLinkLabel));
          }
          jQuery('#widgetdata' + widgetId).show();
        } else {
          jQuery('#widgetdatanoresults' + widgetId).show();
        }
        jQuery('#widgetdatawait' + widgetId).hide();
        calcNotAnalysed(widgetId, res.notAnalysed);
    });
  }

  AjaxServices.getSingleUseKey(wsCall);
}

function make_enrichment_row(result, externalLink, externalLinkLabel) {
    var $row = jQuery('
');
    var $checkBox = jQuery('<input />').attr({'type':'checkbox', 'id':'selected_' +result.item,
                                             'value': result.item, 'name': 'selected'});
    $row.append(jQuery('').append($checkBox));

    if (result.description) {
        $td = jQuery('').text(result.description + ' ');
        if(externalLink) {
          var label;
          if (externalLinkLabel != undefined) {
            label = externalLinkLabel;
          }
          label = label + result.item;
          $a = jQuery('').addClass('extlink').text('[' + label + ']');
          $a.attr({'target': '_new', 'href': externalLink + result.item});
          $td.append($a);
        }
        $row.append($td);
    } else {
        $row.append(jQuery('').html("no description"));
    }
    $row.append(jQuery('').text(result["p-value"]));
    var $count = jQuery('').addClass("match-count").text(result.matches.length);
    var $matches = jQuery('
');
    $matches.css({"display": "none"});
    var $list = jQuery('
');
    var i = 0;
    for (i in result.matches) {
        $list.append(jQuery('
').text(result.matches[i]));
    }
    $matches.append($list);
    $count.append($matches);
    $count.click(function() {$matches.slideToggle()});
    $row.append(jQuery('').append($count));
    return $row;
}

function checkSelected(formName) {
  var form = document.getElementById(formName);
  var elts = form.getElementsByTagName("input");
  for(var i=0;i<elts.length;i++) {
    if( elts[i].name=='selected' && elts[i].checked) {
      return true;
    }
  }
  return false;
}

function submitWidgetForm(widgetId,type,extra) {
    if (document.getElementById('selected_all' + widgetId) != null) {
        var formName = 'widgetaction'+widgetId;
        if(formName && !checkSelected(formName)) {
            document.getElementById('selected_all' + widgetId).checked = true;
            toggleAllChecks(formName, widgetId);
        }
        $('action'+widgetId).value=type;
        $('export' + widgetId).value=extra;
        $('widgetaction' + widgetId).submit();
    }
}

function calcNotAnalysed(widgetId, notAnalysed) {
    var isMSIE = /*@cc_on!@*/false;
    if (!isMSIE) {
        document.getElementById('widgetnotanalysed' + widgetId).innerHTML=notAnalysed;
    }
}

function toggleAllChecks(formName, widgetId) {
  var checked = document.getElementById('selected_all' + widgetId).checked;
  var form = document.getElementById(formName);
  var elts = form.getElementsByTagName("input");
  for(var i=0;i<elts.length;i++) {
    if( elts[i].name=='selected') {
        elts[i].checked=checked;
    }
  }
}<|endoftext|>


<commit_before>/**
 * Model
 */

var model = {
	myProduct : { name: null, description: null, price: null },
	yourProduct : { name: null, description: null, price: null },
	remainingExchange : null,
	globalCountDown : null
};

var countDownTimeOut;
var countDown;
var getNewExchangeTimeOut;

$(document).ready(function(){
	$(".clickWrapper").addClass("loading");
	//start a new game
	getNewExchange();

	//click listener on products
	$("#tradeGame .clickWrapper").click(function(){
		if( !$(this).hasClass("checked") && !$(this).hasClass("notchecked")
				&& !$("#myProduct .clickWrapper").hasClass("loading")
				&& !$("#secondProduct .clickWrapper").hasClass("loading") ) {

			$("#tradeGame .clickWrapper").addClass("notchecked");
			$(this).removeClass("notchecked")
			$(this).addClass("checked");

			var choice = !$(this).parent(".thumbnail").is("#myProduct")

			//send request
			$.getJSON("./Exchange/response/?reponse="+choice, function( data ){
				if( data.resultCode == "OK" ){

				}
				else {
					console.log("Error on ./Exchange/response/?reponse="+choice);
				}
			});
		}
		return false;
	});

});

/**
 *
 */
function getNewExchange() {
	$.getJSON("./Exchange/newExchange/", function( data ){
		if ( data.resultCode == "OK") {
			model.myProduct = data.myProduct;
			model.yourProduct = data.yourProduct;
			model.remainingExchange = data.remainingExchange;

			refreshGame();

			//start time out
			countDownTimeOut = setInterval(function(){
				countDown = countDown - 1;
				$("#exchangeCountDown").html( countDown + "s" );
				if( countDown == 0 ) {
					clearInterval( countDownTimeOut );
					getStateExchange();
				}
			},1000);
		}
		else {
			console.log("getNewExchange KO");
			getNewExchangeTimeOut = setTimeout( function() {
				clearTimeout( getNewExchangeTimeOut );
				getNewExchange();
			}, 5000);
		}
	});
}

/**
 *
 */
function refreshGame() {
	//remove checked / denied
	$("#secondProduct .clickWrapper").removeClass("loading");
	$("#tradeGame .clickWrapper").removeClass("notchecked");
	$("#tradeGame .clickWrapper").removeClass("checked");
	// refresh products content
	$("#myProduct").html( model.myProduct.name );
	$("#secondProduct").html( model.yourProduct.name );
	//refresh remaining exchange
	$("#exchangeRemaining span").html( model.remainingExchange )

	//reset countDown
	$("#exchangeCountDown").html( "10s" );
	countDown = 10;

}

function getStateExchange() {
	$.getJSON("./Exchange/stateExchange/", function( data ){
		if (data.resultCode == "OK") {
			if( data.status == "validate" ) {
				//switch products
				model.myProduct = model.yourProduct;
			}
			else {
				// ?
			}
			refreshGame();
			//resultCode loading
			$("#secondProduct .clickWrapper").addClass("loading");
			// new exchange
			getNewExchange();
		}
	});
}<commit_msg>fix click listenning client side<commit_after>/**
 * Model
 */

var model = {
	myProduct : { name: null, description: null, price: null },
	yourProduct : { name: null, description: null, price: null },
	remainingExchange : null,
	globalCountDown : null
};

var countDownTimeOut;
var countDown;
var getNewExchangeTimeOut;

var canClick = false;

$(document).ready(function(){
	$(".clickWrapper").addClass("loading");
	//start a new game
	getNewExchange();

	//click listener on products
	$("#tradeGame .clickWrapper").click(function(){
		if( canClick ) {
			canClick = false;
			$("#tradeGame .clickWrapper").addClass("notchecked");
			$(this).removeClass("notchecked")
			$(this).addClass("checked");

			var choice = !$(this).parent(".thumbnail").is("#myProduct")

			//send request
			$.getJSON("./Exchange/response/?reponse="+choice, function( data ){
				if( data.resultCode == "OK" ){

				}
				else {
					console.log("Error on ./Exchange/response/?reponse="+choice);
					canClick = true;
				}
			});
		}
		return false;
	});

});

/**
 *
 */
function getNewExchange() {
	$.getJSON("./Exchange/newExchange/", function( data ){
		if ( data.resultCode == "OK") {
			model.myProduct = data.myProduct;
			model.yourProduct = data.yourProduct;
			model.remainingExchange = data.remainingExchange;

			refreshGame();

			//start time out
			countDownTimeOut = setInterval(function(){
				countDown = countDown - 1;
				$("#exchangeCountDown").html( countDown + "s" );
				if( countDown == 0 ) {
					clearInterval( countDownTimeOut );
					getStateExchange();
				}
			},1000);
		}
		else {
			console.log("getNewExchange KO");
			getNewExchangeTimeOut = setTimeout( function() {
				clearTimeout( getNewExchangeTimeOut );
				getNewExchange();
			}, 5000);
		}
	});
}

/**
 *
 */
function refreshGame() {
	//remove checked / denied
	$("#secondProduct .clickWrapper").removeClass("loading");
	$("#tradeGame .clickWrapper").removeClass("notchecked");
	$("#tradeGame .clickWrapper").removeClass("checked");
	// refresh products content
	$("#myProduct").html( model.myProduct.name );
	$("#secondProduct").html( model.yourProduct.name );
	//refresh remaining exchange
	$("#exchangeRemaining span").html( model.remainingExchange )

	//reset countDown
	$("#exchangeCountDown").html( "10s" );
	countDown = 10;
	canClick = true;

}

function getStateExchange() {
	$.getJSON("./Exchange/stateExchange/", function( data ){
		if (data.resultCode == "OK") {
			if( data.status == "validate" ) {
				//switch products
				model.myProduct = model.yourProduct;
			}
			else {
				// ?
			}
			refreshGame();
			canClick = false;
			//resultCode loading
			$("#secondProduct .clickWrapper").addClass("loading");
			// new exchange
			getNewExchange();
		}
	});
}<|endoftext|>


<commit_before>/**
 * @file 项目配置
 * @author zdying
 */

module.exports = {
    /**
     * 需要单独打包的第三方库
     * 例如: {lib: ['react', 'react-dom']}
     * 会把'react'和'react-dom'打包到lib.js
     */
    library: {
        lib: ['jquery', 'backbone']
    },
    /**
     * loaders
     */
    loaders: {
        'dev': [
            { test: /\.(mustache|html)$/, loader: 'mustache' }
        ]
    },
    //TODO add next version
    // plugins: {
    //     'webpack': function(webpack){
    //         return [
    //             new webpack.HotModuleReplacementPlugin(),
    //             new webpack.NoErrorsPlugin()
    //         ]
    //     },
    //     'other-plugin': function(otherPlugin){
    //         return new otherPlugin({
    //             option1: 'opt1',
    //             option2: 'opt2'
    //         })
    //     }
    // },
    /**
     * 业务代码入口
     */
    entry: {
        main: "src/main",
    },
    /**
     * 别名
     */
    alias: {
        'root': 'src/'
    }
};<commit_msg>🆕add TODO<commit_after>/**
 * @file 项目配置
 * @author zdying
 */

module.exports = {
    /**
     * 需要单独打包的第三方库
     * 例如: {lib: ['react', 'react-dom']}
     * 会把'react'和'react-dom'打包到lib.js
     */
    library: {
        lib: ['jquery', 'backbone']
    },
    /**
     * loaders
     */
    loaders: {
        'dev': [
            { test: /\.(mustache|html)$/, loader: 'mustache' }
        ],
        //TODO add next version
        // '*': [
        //     { test: /\.(mustache|html)$/, loader: 'mustache' }
        // ]
    },
    //TODO add next version
    // plugins: {
    //     'webpack': function(webpack){
    //         return [
    //             new webpack.HotModuleReplacementPlugin(),
    //             new webpack.NoErrorsPlugin()
    //         ]
    //     },
    //     'other-plugin': function(otherPlugin){
    //         return new otherPlugin({
    //             option1: 'opt1',
    //             option2: 'opt2'
    //         })
    //     },
    //     'plugin1 plugin2': function(Plugin1, Plugin2){
    //         return [
    //              new Plugin1({
    //                  option1: 'opt1',
    //                  option2: 'opt2'
    //              }),
    //              new Plugin2({
    //                  option1: 'opt1',
    //                  option2: 'opt2'
    //              }),
    //     },
    //     'plugin@version': function(Plugin){
    //         return new Plugin()
    //     },
    // },
    /**
     * 业务代码入口
     */
    entry: {
        main: "src/main",
    },
    /**
     * 别名
     */
    alias: {
        'root': 'src/'
    }
};<|endoftext|>


<commit_before>import * as utils from '@interactjs/utils';
import DropEvent from './DropEvent';

function init (scope) {
  const {
    actions,
    /** @lends module:interact */
    interact,
    /** @lends Interactable */
    Interactable,
    interactions,
    defaults,
  } = scope;

  let dynamicDrop = false;

  interactions.signals.on('after-action-start', function ({ interaction, event, iEvent: dragEvent }) {
    if (interaction.prepared.name !== 'drag') { return; }

    const { dropStatus } = interaction;

    // reset active dropzones
    dropStatus.activeDrops = null;
    dropStatus.events = null;

    if (!interaction.dynamicDrop) {
      dropStatus.activeDrops = getActiveDrops(scope, interaction.element);
    }

    dropStatus.events = getDropEvents(interaction, event, dragEvent);

    if (dropStatus.events.activate) {
      fireActivationEvents(dropStatus.activeDrops, dropStatus.events.activate);
    }
  });

  interactions.signals.on('action-move', arg => onEventCreated(arg, scope, dynamicDrop));
  interactions.signals.on('action-end' , arg => onEventCreated(arg, scope, dynamicDrop));

  interactions.signals.on('after-action-move', function ({ interaction }) {
    if (interaction.prepared.name !== 'drag') { return; }

    fireDropEvents(interaction, interaction.dropStatus.events);
    interaction.dropStatus.events = {};
  });

  interactions.signals.on('after-action-end', function ({ interaction }) {
    if (interaction.prepared.name === 'drag') {
      fireDropEvents(interaction, interaction.dropStatus.events);
    }
  });

  interactions.signals.on('stop', function ({ interaction }) {
    interaction.dropStatus.activeDrops = null;
    interaction.dropStatus.events = null;
  });

  /**
   * ```js
   * interact(target)
   * .dropChecker(function(dragEvent,         // related dragmove or dragend event
   *                       event,             // TouchEvent/PointerEvent/MouseEvent
   *                       dropped,           // bool result of the default checker
   *                       dropzone,          // dropzone Interactable
   *                       dropElement,       // dropzone elemnt
   *                       draggable,         // draggable Interactable
   *                       draggableElement) {// draggable element
   *
   *   return dropped && event.target.hasAttribute('allow-drop');
   * }
   * ```
   *
   * ```js
   * interact('.drop').dropzone({
   *   accept: '.can-drop' || document.getElementById('single-drop'),
   *   overlap: 'pointer' || 'center' || zeroToOne
   * }
   * ```
   *
   * Returns or sets whether draggables can be dropped onto this target to
   * trigger drop events
   *
   * Dropzones can receive the following events:
   *  - `dropactivate` and `dropdeactivate` when an acceptable drag starts and ends
   *  - `dragenter` and `dragleave` when a draggable enters and leaves the dropzone
   *  - `dragmove` when a draggable that has entered the dropzone is moved
   *  - `drop` when a draggable is dropped into this dropzone
   *
   * Use the `accept` option to allow only elements that match the given CSS
   * selector or element. The value can be:
   *
   *  - **an Element** - only that element can be dropped into this dropzone.
   *  - **a string**, - the element being dragged must match it as a CSS selector.
   *  - **`null`** - accept options is cleared - it accepts any element.
   *
   * Use the `overlap` option to set how drops are checked for. The allowed
   * values are:
   *
   *   - `'pointer'`, the pointer must be over the dropzone (default)
   *   - `'center'`, the draggable element's center must be over the dropzone
   *   - a number from 0-1 which is the `(intersection area) / (draggable area)`.
   *   e.g. `0.5` for drop to happen when half of the area of the draggable is
   *   over the dropzone
   *
   * Use the `checker` option to specify a function to check if a dragged element
   * is over this Interactable.
   *
   * @param {boolean | object | null} [options] The new options to be set.
   * @return {boolean | Interactable} The current setting or this Interactable
   */
  Interactable.prototype.dropzone = function (options) {
    if (utils.is.object(options)) {
      this.options.drop.enabled = options.enabled === false? false: true;

      if (utils.is.func(options.ondrop)          ) { this.on('drop'          , options.ondrop          ); }
      if (utils.is.func(options.ondropactivate)  ) { this.on('dropactivate'  , options.ondropactivate  ); }
      if (utils.is.func(options.ondropdeactivate)) { this.on('dropdeactivate', options.ondropdeactivate); }
      if (utils.is.func(options.ondragenter)     ) { this.on('dragenter'     , options.ondragenter     ); }
      if (utils.is.func(options.ondragleave)     ) { this.on('dragleave'     , options.ondragleave     ); }
      if (utils.is.func(options.ondropmove)      ) { this.on('dropmove'      , options.ondropmove      ); }

      if (/^(pointer|center)$/.test(options.overlap)) {
        this.options.drop.overlap = options.overlap;
      }
      else if (utils.is.number(options.overlap)) {
        this.options.drop.overlap = Math.max(Math.min(1, options.overlap), 0);
      }
      if ('accept' in options) {
        this.options.drop.accept = options.accept;
      }
      if ('checker' in options) {
        this.options.drop.checker = options.checker;
      }

      return this;
    }

    if (utils.is.bool(options)) {
      this.options.drop.enabled = options;

      if (!options) {
        this.ondragenter = this.ondragleave = this.ondrop
          = this.ondropactivate = this.ondropdeactivate = null;
      }

      return this;
    }

    return this.options.drop;
  };

  Interactable.prototype.dropCheck = function (dragEvent, event, draggable, draggableElement, dropElement, rect) {
    let dropped = false;

    // if the dropzone has no rect (eg. display: none)
    // call the custom dropChecker or just return false
    if (!(rect = rect || this.getRect(dropElement))) {
      return (this.options.drop.checker
        ? this.options.drop.checker(dragEvent, event, dropped, this, dropElement, draggable, draggableElement)
        : false);
    }

    const dropOverlap = this.options.drop.overlap;

    if (dropOverlap === 'pointer') {
      const origin = utils.getOriginXY(draggable, draggableElement, 'drag');
      const page = utils.pointer.getPageXY(dragEvent);

      page.x += origin.x;
      page.y += origin.y;

      const horizontal = (page.x > rect.left) && (page.x < rect.right);
      const vertical   = (page.y > rect.top ) && (page.y < rect.bottom);

      dropped = horizontal && vertical;
    }

    const dragRect = draggable.getRect(draggableElement);

    if (dragRect && dropOverlap === 'center') {
      const cx = dragRect.left + dragRect.width  / 2;
      const cy = dragRect.top  + dragRect.height / 2;

      dropped = cx >= rect.left && cx <= rect.right && cy >= rect.top && cy <= rect.bottom;
    }

    if (dragRect && utils.is.number(dropOverlap)) {
      const overlapArea  = (Math.max(0, Math.min(rect.right , dragRect.right ) - Math.max(rect.left, dragRect.left))
                            * Math.max(0, Math.min(rect.bottom, dragRect.bottom) - Math.max(rect.top , dragRect.top )));

      const overlapRatio = overlapArea / (dragRect.width * dragRect.height);

      dropped = overlapRatio >= dropOverlap;
    }

    if (this.options.drop.checker) {
      dropped = this.options.drop.checker(dragEvent, event, dropped, this, dropElement, draggable, draggableElement);
    }

    return dropped;
  };

  interactions.signals.on('new', function (interaction) {
    interaction.dropStatus = {
      cur: {
        dropzone : null,  // the dropzone a drag target might be dropped into
        element  : null,  // the element at the time of checking
      },
      prev: {
        dropzone : null,  // the dropzone that was recently dragged away from
        element  : null,  // the element at the time of checking
      },
      rejected   : false, // wheather the potential drop was rejected from a listener
      events     : null,  // the drop events related to the current drag event
      activeDrops: null,  // an array of { dropzone, element, rect }
    };
  });

  interactions.signals.on('stop', function ({ interaction: { dropStatus } }) {
    dropStatus.cur.dropzone = dropStatus.cur.element =
      dropStatus.prev.dropzone = dropStatus.prev.element = null;
    dropStatus.rejected = false;
  });

  /**
   * Returns or sets whether the dimensions of dropzone elements are calculated
   * on every dragmove or only on dragstart for the default dropChecker
   *
   * @param {boolean} [newValue] True to check on each move. False to check only
   * before start
   * @return {boolean | interact} The current setting or interact
   */
  interact.dynamicDrop = function (newValue) {
    if (utils.is.bool(newValue)) {
      //if (dragging && dynamicDrop !== newValue && !newValue) {
      //  calcRects(dropzones);
      //}

      dynamicDrop = newValue;

      return interact;
    }
    return dynamicDrop;
  };

  utils.arr.merge(actions.eventTypes, [
    'dragenter',
    'dragleave',
    'dropactivate',
    'dropdeactivate',
    'dropmove',
    'drop',
  ]);
  actions.methodDict.drop = 'dropzone';

  defaults.drop = drop.defaults;
}

function collectDrops ({ interactables }, draggableElement) {
  const drops = [];

  // collect all dropzones and their elements which qualify for a drop
  for (const dropzone of interactables.list) {
    if (!dropzone.options.drop.enabled) { continue; }

    const accept = dropzone.options.drop.accept;

    // test the draggable draggableElement against the dropzone's accept setting
    if ((utils.is.element(accept) && accept !== draggableElement)
        || (utils.is.string(accept)
        && !utils.dom.matchesSelector(draggableElement, accept))) {

      continue;
    }

    // query for new elements if necessary
    const dropElements = utils.is.string(dropzone.target)
      ? dropzone._context.querySelectorAll(dropzone.target)
      : [dropzone.target];

    for (const dropzoneElement of dropElements) {
      if (dropzoneElement !== draggableElement) {
        drops.push({
          dropzone,
          element: dropzoneElement,
        });
      }
    }
  }

  return drops;
}

function fireActivationEvents (activeDrops, event) {
  let prevElement;

  // loop through all active dropzones and trigger event
  for (const { dropzone, element } of activeDrops) {

    // prevent trigger of duplicate events on same element
    if (element !== prevElement) {
      // set current element as event target
      event.target = element;
      dropzone.fire(event);
    }
    prevElement = element;
  }
}

// return a new array of possible drops. getActiveDrops should always be
// called when a drag has just started or a drag event happens while
// dynamicDrop is true
function getActiveDrops (scope, dragElement) {
  // get dropzones and their elements that could receive the draggable
  const activeDrops = collectDrops(scope, dragElement);

  for (const activeDrop of activeDrops) {
    activeDrop.rect = activeDrop.dropzone.getRect(activeDrop.element);
  }

  return activeDrops;
}

function getDrop ({ dropStatus, target: draggable, element: dragElement }, dragEvent, pointerEvent) {
  const validDrops = [];

  // collect all dropzones and their elements which qualify for a drop
  for (const { dropzone, element: dropzoneElement, rect } of dropStatus.activeDrops) {
    validDrops.push(dropzone.dropCheck(dragEvent, pointerEvent, draggable, dragElement, dropzoneElement, rect)
      ? dropzoneElement
      : null);
  }

  // get the most appropriate dropzone based on DOM depth and order
  const dropIndex = utils.dom.indexOfDeepestElement(validDrops);

  return dropStatus.activeDrops[dropIndex] || null;
}

function getDropEvents (interaction, pointerEvent, dragEvent) {
  const { dropStatus } = interaction;
  const dropEvents = {
    enter     : null,
    leave     : null,
    activate  : null,
    deactivate: null,
    move      : null,
    drop      : null,
  };

  if (dragEvent.type === 'dragstart') {
    dropEvents.activate = new DropEvent(dropStatus, dragEvent, 'dropactivate');

    dropEvents.activate.target   = null;
    dropEvents.activate.dropzone = null;
  }
  if (dragEvent.type === 'dragend') {
    dropEvents.deactivate = new DropEvent(dropStatus, dragEvent, 'dropdeactivate');

    dropEvents.deactivate.target   = null;
    dropEvents.deactivate.dropzone = null;
  }

  if (dropStatus.rejected) {
    return dropEvents;
  }

  if (dropStatus.cur.element !== dropStatus.prev.element) {
    // if there was a previous dropzone, create a dragleave event
    if (dropStatus.prev.dropzone) {
      dropEvents.leave = new DropEvent(dropStatus, dragEvent, 'dragleave');

      dragEvent.dragLeave    = dropEvents.leave.target   = dropStatus.prev.element;
      dragEvent.prevDropzone = dropEvents.leave.dropzone = dropStatus.prev.dropzone;
    }
    // if dropzone is not null, create a dragenter event
    if (dropStatus.cur.dropzone) {
      dropEvents.enter = new DropEvent(dropStatus, dragEvent, 'dragenter');

      dragEvent.dragEnter = dropStatus.cur.element;
      dragEvent.dropzone = dropStatus.cur.dropzone;
    }
  }

  if (dragEvent.type === 'dragend' && dropStatus.cur.dropzone) {
    dropEvents.drop = new DropEvent(dropStatus, dragEvent, 'drop');

    dragEvent.dropzone = dropStatus.cur.dropzone;
    dragEvent.relatedTarget = dropStatus.cur.element;
  }
  if (dragEvent.type === 'dragmove' && dropStatus.cur.dropzone) {
    dropEvents.move = new DropEvent(dropStatus, dragEvent, 'dropmove');

    dropEvents.move.dragmove = dragEvent;
    dragEvent.dropzone = dropStatus.cur.dropzone;
  }

  return dropEvents;
}

function fireDropEvents (interaction, events) {
  const { dropStatus } = interaction;
  const {
    activeDrops,
    cur,
    prev,
  } = dropStatus;

  if (events.leave) { prev.dropzone.fire(events.leave); }
  if (events.move ) { cur.dropzone.fire(events.move ); }
  if (events.enter) { cur.dropzone.fire(events.enter); }
  if (events.drop ) { cur.dropzone.fire(events.drop ); }

  if (events.deactivate) {
    fireActivationEvents(activeDrops, events.deactivate);
  }

  dropStatus.prev.dropzone  = cur.dropzone;
  dropStatus.prev.element = cur.element;
}

function onEventCreated ({ interaction, iEvent, event }, scope, dynamicDrop) {
  if (iEvent.type !== 'dragmove' && iEvent.type !== 'dragend') { return; }

  const { dropStatus } = interaction;

  if (dynamicDrop) {
    dropStatus.activeDrops = getActiveDrops(scope, interaction.target, interaction.element);
  }

  const dragEvent = iEvent;
  const dropResult = getDrop(interaction, dragEvent, event);

  // update rejected status
  dropStatus.rejected = dropStatus.rejected &&
    !!dropResult &&
    dropResult.dropzone === dropStatus.cur.dropzone &&
    dropResult.element === dropStatus.cur.element;

  dropStatus.cur.dropzone  = dropResult && dropResult.dropzone;
  dropStatus.cur.element = dropResult && dropResult.element;

  dropStatus.events = getDropEvents(interaction, event, dragEvent);
}

const drop = {
  init,
  getActiveDrops,
  getDrop,
  getDropEvents,
  fireDropEvents,
  defaults: {
    enabled: false,
    accept : null,
    overlap: 'pointer',
  },
};

export default drop;
<commit_msg>actions/drop: rearrange stuff; fix dynamicDrop<commit_after>import * as utils from '@interactjs/utils';
import DropEvent from './DropEvent';

function init (scope) {
  const {
    actions,
    /** @lends module:interact */
    interact,
    /** @lends Interactable */
    Interactable,
    interactions,
    defaults,
  } = scope;

  interactions.signals.on('after-action-start', function ({ interaction, event, iEvent: dragEvent }) {
    if (interaction.prepared.name !== 'drag') { return; }

    const { dropStatus } = interaction;

    // reset active dropzones
    dropStatus.activeDrops = null;
    dropStatus.events = null;

    if (!scope.dynamicDrop) {
      dropStatus.activeDrops = getActiveDrops(scope, interaction.element);
    }

    dropStatus.events = getDropEvents(interaction, event, dragEvent);

    if (dropStatus.events.activate) {
      fireActivationEvents(dropStatus.activeDrops, dropStatus.events.activate);
    }
  });

  interactions.signals.on('action-move', arg => onEventCreated(arg, scope));
  interactions.signals.on('action-end' , arg => onEventCreated(arg, scope));

  interactions.signals.on('after-action-move', function ({ interaction }) {
    if (interaction.prepared.name !== 'drag') { return; }

    fireDropEvents(interaction, interaction.dropStatus.events);
    interaction.dropStatus.events = {};
  });

  interactions.signals.on('after-action-end', function ({ interaction }) {
    if (interaction.prepared.name === 'drag') {
      fireDropEvents(interaction, interaction.dropStatus.events);
    }
  });

  interactions.signals.on('stop', function ({ interaction }) {
    interaction.dropStatus.activeDrops = null;
    interaction.dropStatus.events = null;
  });

  interactions.signals.on('new', function (interaction) {
    interaction.dropStatus = {
      cur: {
        dropzone : null,  // the dropzone a drag target might be dropped into
        element  : null,  // the element at the time of checking
      },
      prev: {
        dropzone : null,  // the dropzone that was recently dragged away from
        element  : null,  // the element at the time of checking
      },
      rejected   : false, // wheather the potential drop was rejected from a listener
      events     : null,  // the drop events related to the current drag event
      activeDrops: null,  // an array of { dropzone, element, rect }
    };
  });

  interactions.signals.on('stop', function ({ interaction: { dropStatus } }) {
    dropStatus.cur.dropzone = dropStatus.cur.element =
      dropStatus.prev.dropzone = dropStatus.prev.element = null;
    dropStatus.rejected = false;
  });

  Interactable.prototype.dropzone = function (options) {
    return dropzoneMethod(this, options);
  };

  Interactable.prototype.dropCheck = function (dragEvent, event, draggable, draggableElement, dropElement, rect) {
    return dropCheckMethod(this, dragEvent, event, draggable, draggableElement, dropElement, rect);
  };

  /**
   * Returns or sets whether the dimensions of dropzone elements are calculated
   * on every dragmove or only on dragstart for the default dropChecker
   *
   * @param {boolean} [newValue] True to check on each move. False to check only
   * before start
   * @return {boolean | interact} The current setting or interact
   */
  interact.dynamicDrop = function (newValue) {
    if (utils.is.bool(newValue)) {
      //if (dragging && scope.dynamicDrop !== newValue && !newValue) {
      //  calcRects(dropzones);
      //}

      scope.dynamicDrop = newValue;

      return interact;
    }
    return scope.dynamicDrop;
  };

  utils.arr.merge(actions.eventTypes, [
    'dragenter',
    'dragleave',
    'dropactivate',
    'dropdeactivate',
    'dropmove',
    'drop',
  ]);
  actions.methodDict.drop = 'dropzone';

  scope.dynamicDrop = false;

  defaults.drop = drop.defaults;
}

function collectDrops ({ interactables }, draggableElement) {
  const drops = [];

  // collect all dropzones and their elements which qualify for a drop
  for (const dropzone of interactables.list) {
    if (!dropzone.options.drop.enabled) { continue; }

    const accept = dropzone.options.drop.accept;

    // test the draggable draggableElement against the dropzone's accept setting
    if ((utils.is.element(accept) && accept !== draggableElement)
        || (utils.is.string(accept)
        && !utils.dom.matchesSelector(draggableElement, accept))) {

      continue;
    }

    // query for new elements if necessary
    const dropElements = utils.is.string(dropzone.target)
      ? dropzone._context.querySelectorAll(dropzone.target)
      : [dropzone.target];

    for (const dropzoneElement of dropElements) {
      if (dropzoneElement !== draggableElement) {
        drops.push({
          dropzone,
          element: dropzoneElement,
        });
      }
    }
  }

  return drops;
}

function fireActivationEvents (activeDrops, event) {
  let prevElement;

  // loop through all active dropzones and trigger event
  for (const { dropzone, element } of activeDrops) {

    // prevent trigger of duplicate events on same element
    if (element !== prevElement) {
      // set current element as event target
      event.target = element;
      dropzone.fire(event);
    }
    prevElement = element;
  }
}

// return a new array of possible drops. getActiveDrops should always be
// called when a drag has just started or a drag event happens while
// dynamicDrop is true
function getActiveDrops (scope, dragElement) {
  // get dropzones and their elements that could receive the draggable
  const activeDrops = collectDrops(scope, dragElement);

  for (const activeDrop of activeDrops) {
    activeDrop.rect = activeDrop.dropzone.getRect(activeDrop.element);
  }

  return activeDrops;
}

function getDrop ({ dropStatus, target: draggable, element: dragElement }, dragEvent, pointerEvent) {
  const validDrops = [];

  // collect all dropzones and their elements which qualify for a drop
  for (const { dropzone, element: dropzoneElement, rect } of dropStatus.activeDrops) {
    validDrops.push(dropzone.dropCheck(dragEvent, pointerEvent, draggable, dragElement, dropzoneElement, rect)
      ? dropzoneElement
      : null);
  }

  // get the most appropriate dropzone based on DOM depth and order
  const dropIndex = utils.dom.indexOfDeepestElement(validDrops);

  return dropStatus.activeDrops[dropIndex] || null;
}

function getDropEvents (interaction, pointerEvent, dragEvent) {
  const { dropStatus } = interaction;
  const dropEvents = {
    enter     : null,
    leave     : null,
    activate  : null,
    deactivate: null,
    move      : null,
    drop      : null,
  };

  if (dragEvent.type === 'dragstart') {
    dropEvents.activate = new DropEvent(dropStatus, dragEvent, 'dropactivate');

    dropEvents.activate.target   = null;
    dropEvents.activate.dropzone = null;
  }
  if (dragEvent.type === 'dragend') {
    dropEvents.deactivate = new DropEvent(dropStatus, dragEvent, 'dropdeactivate');

    dropEvents.deactivate.target   = null;
    dropEvents.deactivate.dropzone = null;
  }

  if (dropStatus.rejected) {
    return dropEvents;
  }

  if (dropStatus.cur.element !== dropStatus.prev.element) {
    // if there was a previous dropzone, create a dragleave event
    if (dropStatus.prev.dropzone) {
      dropEvents.leave = new DropEvent(dropStatus, dragEvent, 'dragleave');

      dragEvent.dragLeave    = dropEvents.leave.target   = dropStatus.prev.element;
      dragEvent.prevDropzone = dropEvents.leave.dropzone = dropStatus.prev.dropzone;
    }
    // if dropzone is not null, create a dragenter event
    if (dropStatus.cur.dropzone) {
      dropEvents.enter = new DropEvent(dropStatus, dragEvent, 'dragenter');

      dragEvent.dragEnter = dropStatus.cur.element;
      dragEvent.dropzone = dropStatus.cur.dropzone;
    }
  }

  if (dragEvent.type === 'dragend' && dropStatus.cur.dropzone) {
    dropEvents.drop = new DropEvent(dropStatus, dragEvent, 'drop');

    dragEvent.dropzone = dropStatus.cur.dropzone;
    dragEvent.relatedTarget = dropStatus.cur.element;
  }
  if (dragEvent.type === 'dragmove' && dropStatus.cur.dropzone) {
    dropEvents.move = new DropEvent(dropStatus, dragEvent, 'dropmove');

    dropEvents.move.dragmove = dragEvent;
    dragEvent.dropzone = dropStatus.cur.dropzone;
  }

  return dropEvents;
}

function fireDropEvents (interaction, events) {
  const { dropStatus } = interaction;
  const {
    activeDrops,
    cur,
    prev,
  } = dropStatus;

  if (events.leave) { prev.dropzone.fire(events.leave); }
  if (events.move ) { cur.dropzone.fire(events.move ); }
  if (events.enter) { cur.dropzone.fire(events.enter); }
  if (events.drop ) { cur.dropzone.fire(events.drop ); }

  if (events.deactivate) {
    fireActivationEvents(activeDrops, events.deactivate);
  }

  dropStatus.prev.dropzone  = cur.dropzone;
  dropStatus.prev.element = cur.element;
}

function onEventCreated ({ interaction, iEvent, event }, scope) {
  if (iEvent.type !== 'dragmove' && iEvent.type !== 'dragend') { return; }

  const { dropStatus } = interaction;

  if (scope.dynamicDrop) {
    dropStatus.activeDrops = getActiveDrops(scope, interaction.target, interaction.element);
  }

  const dragEvent = iEvent;
  const dropResult = getDrop(interaction, dragEvent, event);

  // update rejected status
  dropStatus.rejected = dropStatus.rejected &&
    !!dropResult &&
    dropResult.dropzone === dropStatus.cur.dropzone &&
    dropResult.element === dropStatus.cur.element;

  dropStatus.cur.dropzone  = dropResult && dropResult.dropzone;
  dropStatus.cur.element = dropResult && dropResult.element;

  dropStatus.events = getDropEvents(interaction, event, dragEvent);
}

/**
 * ```js
 * interact(target)
 * .dropChecker(function(dragEvent,         // related dragmove or dragend event
 *                       event,             // TouchEvent/PointerEvent/MouseEvent
 *                       dropped,           // bool result of the default checker
 *                       dropzone,          // dropzone Interactable
 *                       dropElement,       // dropzone elemnt
 *                       draggable,         // draggable Interactable
 *                       draggableElement) {// draggable element
 *
 *   return dropped && event.target.hasAttribute('allow-drop');
 * }
 * ```
 *
 * ```js
 * interact('.drop').dropzone({
 *   accept: '.can-drop' || document.getElementById('single-drop'),
 *   overlap: 'pointer' || 'center' || zeroToOne
 * }
 * ```
 *
 * Returns or sets whether draggables can be dropped onto this target to
 * trigger drop events
 *
 * Dropzones can receive the following events:
 *  - `dropactivate` and `dropdeactivate` when an acceptable drag starts and ends
 *  - `dragenter` and `dragleave` when a draggable enters and leaves the dropzone
 *  - `dragmove` when a draggable that has entered the dropzone is moved
 *  - `drop` when a draggable is dropped into this dropzone
 *
 * Use the `accept` option to allow only elements that match the given CSS
 * selector or element. The value can be:
 *
 *  - **an Element** - only that element can be dropped into this dropzone.
 *  - **a string**, - the element being dragged must match it as a CSS selector.
 *  - **`null`** - accept options is cleared - it accepts any element.
 *
 * Use the `overlap` option to set how drops are checked for. The allowed
 * values are:
 *
 *   - `'pointer'`, the pointer must be over the dropzone (default)
 *   - `'center'`, the draggable element's center must be over the dropzone
 *   - a number from 0-1 which is the `(intersection area) / (draggable area)`.
 *   e.g. `0.5` for drop to happen when half of the area of the draggable is
 *   over the dropzone
 *
 * Use the `checker` option to specify a function to check if a dragged element
 * is over this Interactable.
 *
 * @param {boolean | object | null} [options] The new options to be set.
 * @return {boolean | Interactable} The current setting or this Interactable
 */
function dropzoneMethod (interactable, options) {
  if (utils.is.object(options)) {
    interactable.options.drop.enabled = options.enabled === false? false: true;

    if (utils.is.func(options.ondrop)          ) { interactable.on('drop'          , options.ondrop          ); }
    if (utils.is.func(options.ondropactivate)  ) { interactable.on('dropactivate'  , options.ondropactivate  ); }
    if (utils.is.func(options.ondropdeactivate)) { interactable.on('dropdeactivate', options.ondropdeactivate); }
    if (utils.is.func(options.ondragenter)     ) { interactable.on('dragenter'     , options.ondragenter     ); }
    if (utils.is.func(options.ondragleave)     ) { interactable.on('dragleave'     , options.ondragleave     ); }
    if (utils.is.func(options.ondropmove)      ) { interactable.on('dropmove'      , options.ondropmove      ); }

    if (/^(pointer|center)$/.test(options.overlap)) {
      interactable.options.drop.overlap = options.overlap;
    }
    else if (utils.is.number(options.overlap)) {
      interactable.options.drop.overlap = Math.max(Math.min(1, options.overlap), 0);
    }
    if ('accept' in options) {
      interactable.options.drop.accept = options.accept;
    }
    if ('checker' in options) {
      interactable.options.drop.checker = options.checker;
    }

    return interactable;
  }

  if (utils.is.bool(options)) {
    interactable.options.drop.enabled = options;

    if (!options) {
      interactable.ondragenter = interactable.ondragleave = interactable.ondrop
        = interactable.ondropactivate = interactable.ondropdeactivate = null;
    }

    return interactable;
  }

  return interactable.options.drop;
}

function dropCheckMethod (interactable, dragEvent, event, draggable, draggableElement, dropElement, rect) {
  let dropped = false;

  // if the dropzone has no rect (eg. display: none)
  // call the custom dropChecker or just return false
  if (!(rect = rect || interactable.getRect(dropElement))) {
    return (interactable.options.drop.checker
      ? interactable.options.drop.checker(dragEvent, event, dropped, interactable, dropElement, draggable, draggableElement)
      : false);
  }

  const dropOverlap = interactable.options.drop.overlap;

  if (dropOverlap === 'pointer') {
    const origin = utils.getOriginXY(draggable, draggableElement, 'drag');
    const page = utils.pointer.getPageXY(dragEvent);

    page.x += origin.x;
    page.y += origin.y;

    const horizontal = (page.x > rect.left) && (page.x < rect.right);
    const vertical   = (page.y > rect.top ) && (page.y < rect.bottom);

    dropped = horizontal && vertical;
  }

  const dragRect = draggable.getRect(draggableElement);

  if (dragRect && dropOverlap === 'center') {
    const cx = dragRect.left + dragRect.width  / 2;
    const cy = dragRect.top  + dragRect.height / 2;

    dropped = cx >= rect.left && cx <= rect.right && cy >= rect.top && cy <= rect.bottom;
  }

  if (dragRect && utils.is.number(dropOverlap)) {
    const overlapArea  = (Math.max(0, Math.min(rect.right , dragRect.right ) - Math.max(rect.left, dragRect.left))
                          * Math.max(0, Math.min(rect.bottom, dragRect.bottom) - Math.max(rect.top , dragRect.top )));

    const overlapRatio = overlapArea / (dragRect.width * dragRect.height);

    dropped = overlapRatio >= dropOverlap;
  }

  if (interactable.options.drop.checker) {
    dropped = interactable.options.drop.checker(dragEvent, event, dropped, interactable, dropElement, draggable, draggableElement);
  }

  return dropped;
}

const drop = {
  init,
  getActiveDrops,
  getDrop,
  getDropEvents,
  fireDropEvents,
  defaults: {
    enabled: false,
    accept : null,
    overlap: 'pointer',
  },
};

export default drop;
<|endoftext|>