<commit_before>var async = require('async');
var _ = require('underscore');
var questions = require(__dirname + '/../../app/controllers/questions.js');
var answers = require(__dirname + '/../../app/controllers/answers.js');
var guestNames = [
    "Disco Potato",
    "Silver Blister",
    "Insulated Mustard",
    "Funeral Flapjack",
    "Toenail",
    "Urgent Drip",
    "Raging Bagel",
    "Aggressive Pie",
    "Loving Spoon",
    "Swollen Node",
    "The Spleen",
    "Dingle Dangle"
  ];

function Game(gameID, io) {
  this.io = io;
  this.gameID = gameID;
  this.players = []; // Contains array of player models
  this.table = []; // Contains array of {card: card, player: player.id}
  this.winningCard = -1; // Index in this.table
  this.gameWinner = -1; // Index in this.players
  this.winnerAutopicked = false;
  this.czar = -1; // Index in this.players
  this.playerMinLimit = 3;
  this.playerMaxLimit = 6;
  this.pointLimit = 5;
  this.state = "awaiting players";
  this.round = 0;
  this.questions = null;
  this.answers = null;
  this.curQuestion = null;
  this.timeLimits = {
    stateChoosing: 21,
    stateJudging: 16,
    stateResults: 6
  };
  // setTimeout ID that triggers the czar judging state
  // Used to automatically run czar judging if players don't pick before time limit
  // Gets cleared if players finish picking before time limit.
  this.choosingTimeout = 0;
  // setTimeout ID that triggers the result state
  // Used to automatically run result if czar doesn't decide before time limit
  // Gets cleared if czar finishes judging before time limit.
  this.judgingTimeout = 0;
  this.resultsTimeout = 0;
  this.guestNames = guestNames;
}

Game.prototype.payload = function() {
  var players = [];
  this.players.forEach(function(player,index) {
    players.push({
      hand: player.hand,
      points: player.points,
      username: player.username,
      avatar: player.avatar,
      premium: player.premium,
      socketID: player.socket.id,
      color: player.color
    });
  });
  return {
    gameID: this.gameID,
    players: players,
    czar: this.czar,
    state: this.state,
    round: this.round,
    gameWinner: this.gameWinner,
    winningCard: this.winningCard,
    winningCardPlayer: this.winningCardPlayer,
    winnerAutopicked: this.winnerAutopicked,
    table: this.table,
    pointLimit: this.pointLimit,
    curQuestion: this.curQuestion
  };
};

Game.prototype.sendNotification = function(msg) {
  this.io.sockets.in(this.gameID).emit('notification', {notification: msg});
};

// Currently called on each joinGame event from socket.js
// Also called on removePlayer IF game is in 'awaiting players' state
Game.prototype.assignPlayerColors = function() {
  this.players.forEach(function(player,index) {
    player.color = index;
  });
};

Game.prototype.assignGuestNames = function() {
  var self = this;
  this.players.forEach(function(player) {
    if (player.username === 'Guest' && self.guestNames.length > 0) {
      var randIndex = Math.floor(Math.random() * self.guestNames.length);
      player.username = self.guestNames.splice(randIndex, 1)[0];
      if (!self.guestNames.length) {
        self.guestNames = guestNames;
      }
    }
  });
};

Game.prototype.prepareGame = function() {
  this.state = "game in progress";

  this.io.sockets.in(this.gameID).emit('prepareGame',
    {
      playerMinLimit: this.playerMinLimit,
      playerMaxLimit: this.playerMaxLimit,
      pointLimit: this.pointLimit,
      timeLimits: this.timeLimits
    });

  var self = this;
  async.parallel([
    this.getQuestions,
    this.getAnswers
    ],
    function(err, results){
      if (err) {
        console.log(err);
      }
      self.questions = results[0];
      self.answers = results[1];

      self.startGame();
    });
};

Game.prototype.startGame = function() {
  console.log(this.gameID,this.state);
  this.shuffleCards(this.questions);
  this.shuffleCards(this.answers);
  this.stateChoosing(this);
};

Game.prototype.sendUpdate = function() {
  this.io.sockets.in(this.gameID).emit('gameUpdate', this.payload());
};

Game.prototype.stateChoosing = function(self) {
  self.state = "waiting for players to pick";
  console.log(self.gameID,self.state);
  self.table = [];
  self.winningCard = -1;
  self.winningCardPlayer = -1;
  self.winnerAutopicked = false;
  self.curQuestion = self.questions.pop();
  if (!self.questions.length) {
    self.getQuestions(function(err, data) {
      self.questions = data;
    });
  }
  self.round++;
  self.dealAnswers();
  // Rotate card czar
  if (self.czar >= self.players.length - 1) {
    self.czar = 0;
  } else {
    self.czar++;
  }
  self.sendUpdate();

  self.choosingTimeout = setTimeout(function() {
    self.stateJudging(self);
  }, self.timeLimits.stateChoosing*1000);
};

Game.prototype.selectFirst = function() {
  if (this.table.length) {
    this.winningCard = 0;
    var winnerIndex = this._findPlayerIndexBySocket(this.table[0].player);
    this.winningCardPlayer = winnerIndex;
    this.players[winnerIndex].points++;
    this.winnerAutopicked = true;
    this.stateResults(this);
  } else {
    console.log(this.gameID,'no cards were picked!');
    this.stateChoosing(this);
  }
};

Game.prototype.stateJudging = function(self) {
  self.state = "waiting for czar to decide";
  console.log(self.gameID,self.state);

  if (self.table.length <= 1) {
    // Automatically select a card if only one card was submitted
    self.selectFirst();
  } else {
    self.sendUpdate();
    self.judgingTimeout = setTimeout(function() {
      // Automatically select the first submitted card when time runs out.
      self.selectFirst();
    }, self.timeLimits.stateJudging*1000);
  }
};

Game.prototype.stateResults = function(self) {
  self.state = "winner has been chosen";
  console.log(self.state);
  // TODO: do stuff
  var winner = -1;
  for (var i = 0; i < self.players.length; i++) {
    if (self.players[i].points >= self.pointLimit) {
      winner = i;
    }
  }
  self.sendUpdate();
  self.resultsTimeout = setTimeout(function() {
    if (winner !== -1) {
      self.stateEndGame(winner);
    } else {
      self.stateChoosing(self);
    }
  }, self.timeLimits.stateResults*1000);
};

Game.prototype.stateEndGame = function(winner) {
  this.state = "game ended";
  this.gameWinner = winner;
  this.sendUpdate();
};

Game.prototype.stateDissolveGame = function() {
  this.state = "game dissolved";
  this.sendUpdate();
};

Game.prototype.getQuestions = function(cb) {
  questions.allQuestionsForGame(function(data){
    cb(null,data);
  });
};

Game.prototype.getAnswers = function(cb) {
  answers.allAnswersForGame(function(data){
    cb(null,data);
  });
};

Game.prototype.shuffleCards = function(cards) {
  var shuffleIndex = cards.length;
  var temp;
  var randNum;

  while(shuffleIndex) {
    randNum = Math.floor(Math.random() * shuffleIndex--);
    temp = cards[randNum];
    cards[randNum] = cards[shuffleIndex];
    cards[shuffleIndex] = temp;
  }

  return cards;
};

Game.prototype.dealAnswers = function(maxAnswers) {
  maxAnswers = maxAnswers || 10;
  var storeAnswers = function(err, data) {
    this.answers = data;
  };
  for (var i = 0; i < this.players.length; i++) {
    while (this.players[i].hand.length < maxAnswers) {
      this.players[i].hand.push(this.answers.pop());
      if (!this.answers.length) {
        this.getAnswers(storeAnswers);
      }
    }
  }
};

Game.prototype._findPlayerIndexBySocket = function(thisPlayer) {
  var playerIndex = -1;
  _.each(this.players, function(player, index) {
    if (player.socket.id === thisPlayer) {
      playerIndex = index;
    }
  });
  return playerIndex;
};

Game.prototype.pickCards = function(thisCardArray, thisPlayer) {
  // Only accept cards when we expect players to pick a card
  if (this.state === "waiting for players to pick") {
    // Find the player's position in the players array
    var playerIndex = this._findPlayerIndexBySocket(thisPlayer);
    console.log('player is at index',playerIndex);
    if (playerIndex !== -1) {
      // Verify that the player hasn't previously picked a card
      var previouslySubmitted = false;
      _.each(this.table, function(pickedSet, index) {
        if (pickedSet.player === thisPlayer) {
          previouslySubmitted = true;
        }
      });
      if (!previouslySubmitted) {
        // Find the indices of the cards in the player's hand (given the card ids)
        var tableCard = [];
        for (var i = 0; i < thisCardArray.length; i++ ) {
          var cardIndex = null;
          for (var j = 0; j < this.players[playerIndex].hand.length; j++) {
            if (this.players[playerIndex].hand[j].id === thisCardArray[i]) {
              cardIndex = j;
            }
          }
          console.log('card',i,'is at index',cardIndex);
          if (cardIndex !== null) {
            tableCard.push(this.players[playerIndex].hand.splice(cardIndex,1)[0]);
          }
          console.log('table object at',cardIndex,':',tableCard);
        }
        if (tableCard.length === this.curQuestion.numAnswers) {
          this.table.push({
            card: tableCard,
            player: this.players[playerIndex].socket.id
          });
        }
        console.log('final table object',this.table);
        if (this.table.length === this.players.length-1) {
          clearTimeout(this.choosingTimeout);
          this.stateJudging(this);
        } else {
          this.sendUpdate();
        }
      }
    }
  } else {
    console.log('NOTE:',thisPlayer,'picked a card during',this.state);
  }
};

Game.prototype.getPlayer = function(thisPlayer) {
  var playerIndex = this._findPlayerIndexBySocket(thisPlayer);
  if (playerIndex > -1) {
    return this.players[playerIndex];
  } else {
    return {};
  }
};

Game.prototype.removePlayer = function(thisPlayer) {
  var playerIndex = this._findPlayerIndexBySocket(thisPlayer);

  if (playerIndex !== -1) {
    // Just used to send the remaining players a notification
    var playerName = this.players[playerIndex].username;

    // Remove player from this.players
    this.players.splice(playerIndex,1);

    if (this.state === "awaiting players") {
      this.assignPlayerColors();
    }

    // Check if the player is the czar
    if (this.czar === playerIndex) {
      // If the player is the czar...
      // If players are currently picking a card, advance to a new round.
      if (this.state === "waiting for players to pick") {
        clearTimeout(this.choosingTimeout);
        this.sendNotification('The Czar left the game! Starting a new round.');
        return this.stateChoosing(this);
      } else if (this.state === "waiting for czar to decide") {
        // If players are waiting on a czar to pick, auto pick.
        this.sendNotification('The Czar left the game! First answer/s submitted wins!');
        this.pickWinning(this.table[0].card[0].id, thisPlayer, true);
      }
    } else {
      this.sendNotification(playerName+' has left the game.');
    }

    this.sendUpdate();
  }
};

Game.prototype.pickWinning = function(thisCard, thisPlayer, autopicked) {
  autopicked = autopicked || false;
  var playerIndex = this._findPlayerIndexBySocket(thisPlayer);
  if ((playerIndex === this.czar || autopicked) && this.state === "waiting for czar to decide") {
    var cardIndex = -1;
    _.each(this.table, function(winningSet, index) {
      if (winningSet.card[0].id === thisCard) {
        cardIndex = index;
      }
    });
    if (cardIndex !== -1) {
      this.winningCard = cardIndex;
      var winnerIndex = this._findPlayerIndexBySocket(this.table[cardIndex].player);
      this.sendNotification(this.players[winnerIndex].username+' has won the round!');
      this.winningCardPlayer = winnerIndex;
      this.players[winnerIndex].points++;
      clearTimeout(this.judgingTimeout);
      this.winnerAutopicked = autopicked;
      this.stateResults(this);
    } else {
      console.log('WARNING: czar',thisPlayer,'picked a card that was not on the table.');
    }
  } else {
    // TODO: Do something?
    this.sendUpdate();
  }
};

Game.prototype.killGame = function() {
  console.log('Killing game',this.gameID);
  clearTimeout(this.resultsTimeout);
  clearTimeout(this.choosingTimeout);
  clearTimeout(this.judgingTimeout);
};

module.exports = Game;

<commit_msg>Fixed issue with guestNames not cycling through names<commit_after>var async = require('async');
var _ = require('underscore');
var questions = require(__dirname + '/../../app/controllers/questions.js');
var answers = require(__dirname + '/../../app/controllers/answers.js');
var guestNames = [
    "Disco Potato",
    "Silver Blister",
    "Insulated Mustard",
    "Funeral Flapjack",
    "Toenail",
    "Urgent Drip",
    "Raging Bagel",
    "Aggressive Pie",
    "Loving Spoon",
    "Swollen Node",
    "The Spleen",
    "Dingle Dangle"
  ];

function Game(gameID, io) {
  this.io = io;
  this.gameID = gameID;
  this.players = []; // Contains array of player models
  this.table = []; // Contains array of {card: card, player: player.id}
  this.winningCard = -1; // Index in this.table
  this.gameWinner = -1; // Index in this.players
  this.winnerAutopicked = false;
  this.czar = -1; // Index in this.players
  this.playerMinLimit = 3;
  this.playerMaxLimit = 6;
  this.pointLimit = 5;
  this.state = "awaiting players";
  this.round = 0;
  this.questions = null;
  this.answers = null;
  this.curQuestion = null;
  this.timeLimits = {
    stateChoosing: 21,
    stateJudging: 16,
    stateResults: 6
  };
  // setTimeout ID that triggers the czar judging state
  // Used to automatically run czar judging if players don't pick before time limit
  // Gets cleared if players finish picking before time limit.
  this.choosingTimeout = 0;
  // setTimeout ID that triggers the result state
  // Used to automatically run result if czar doesn't decide before time limit
  // Gets cleared if czar finishes judging before time limit.
  this.judgingTimeout = 0;
  this.resultsTimeout = 0;
  this.guestNames = guestNames;
}

Game.prototype.payload = function() {
  var players = [];
  this.players.forEach(function(player,index) {
    players.push({
      hand: player.hand,
      points: player.points,
      username: player.username,
      avatar: player.avatar,
      premium: player.premium,
      socketID: player.socket.id,
      color: player.color
    });
  });
  return {
    gameID: this.gameID,
    players: players,
    czar: this.czar,
    state: this.state,
    round: this.round,
    gameWinner: this.gameWinner,
    winningCard: this.winningCard,
    winningCardPlayer: this.winningCardPlayer,
    winnerAutopicked: this.winnerAutopicked,
    table: this.table,
    pointLimit: this.pointLimit,
    curQuestion: this.curQuestion
  };
};

Game.prototype.sendNotification = function(msg) {
  this.io.sockets.in(this.gameID).emit('notification', {notification: msg});
};

// Currently called on each joinGame event from socket.js
// Also called on removePlayer IF game is in 'awaiting players' state
Game.prototype.assignPlayerColors = function() {
  this.players.forEach(function(player,index) {
    player.color = index;
  });
};

Game.prototype.assignGuestNames = function() {
  var self = this;
  this.players.forEach(function(player) {
    if (player.username === 'Guest') {
      var randIndex = Math.floor(Math.random() * self.guestNames.length);
      player.username = self.guestNames.splice(randIndex, 1)[0];
      if (!self.guestNames.length) {
        self.guestNames = guestNames;
      }
    }
  });
};

Game.prototype.prepareGame = function() {
  this.state = "game in progress";

  this.io.sockets.in(this.gameID).emit('prepareGame',
    {
      playerMinLimit: this.playerMinLimit,
      playerMaxLimit: this.playerMaxLimit,
      pointLimit: this.pointLimit,
      timeLimits: this.timeLimits
    });

  var self = this;
  async.parallel([
    this.getQuestions,
    this.getAnswers
    ],
    function(err, results){
      if (err) {
        console.log(err);
      }
      self.questions = results[0];
      self.answers = results[1];

      self.startGame();
    });
};

Game.prototype.startGame = function() {
  console.log(this.gameID,this.state);
  this.shuffleCards(this.questions);
  this.shuffleCards(this.answers);
  this.stateChoosing(this);
};

Game.prototype.sendUpdate = function() {
  this.io.sockets.in(this.gameID).emit('gameUpdate', this.payload());
};

Game.prototype.stateChoosing = function(self) {
  self.state = "waiting for players to pick";
  console.log(self.gameID,self.state);
  self.table = [];
  self.winningCard = -1;
  self.winningCardPlayer = -1;
  self.winnerAutopicked = false;
  self.curQuestion = self.questions.pop();
  if (!self.questions.length) {
    self.getQuestions(function(err, data) {
      self.questions = data;
    });
  }
  self.round++;
  self.dealAnswers();
  // Rotate card czar
  if (self.czar >= self.players.length - 1) {
    self.czar = 0;
  } else {
    self.czar++;
  }
  self.sendUpdate();

  self.choosingTimeout = setTimeout(function() {
    self.stateJudging(self);
  }, self.timeLimits.stateChoosing*1000);
};

Game.prototype.selectFirst = function() {
  if (this.table.length) {
    this.winningCard = 0;
    var winnerIndex = this._findPlayerIndexBySocket(this.table[0].player);
    this.winningCardPlayer = winnerIndex;
    this.players[winnerIndex].points++;
    this.winnerAutopicked = true;
    this.stateResults(this);
  } else {
    console.log(this.gameID,'no cards were picked!');
    this.stateChoosing(this);
  }
};

Game.prototype.stateJudging = function(self) {
  self.state = "waiting for czar to decide";
  console.log(self.gameID,self.state);

  if (self.table.length <= 1) {
    // Automatically select a card if only one card was submitted
    self.selectFirst();
  } else {
    self.sendUpdate();
    self.judgingTimeout = setTimeout(function() {
      // Automatically select the first submitted card when time runs out.
      self.selectFirst();
    }, self.timeLimits.stateJudging*1000);
  }
};

Game.prototype.stateResults = function(self) {
  self.state = "winner has been chosen";
  console.log(self.state);
  // TODO: do stuff
  var winner = -1;
  for (var i = 0; i < self.players.length; i++) {
    if (self.players[i].points >= self.pointLimit) {
      winner = i;
    }
  }
  self.sendUpdate();
  self.resultsTimeout = setTimeout(function() {
    if (winner !== -1) {
      self.stateEndGame(winner);
    } else {
      self.stateChoosing(self);
    }
  }, self.timeLimits.stateResults*1000);
};

Game.prototype.stateEndGame = function(winner) {
  this.state = "game ended";
  this.gameWinner = winner;
  this.sendUpdate();
};

Game.prototype.stateDissolveGame = function() {
  this.state = "game dissolved";
  this.sendUpdate();
};

Game.prototype.getQuestions = function(cb) {
  questions.allQuestionsForGame(function(data){
    cb(null,data);
  });
};

Game.prototype.getAnswers = function(cb) {
  answers.allAnswersForGame(function(data){
    cb(null,data);
  });
};

Game.prototype.shuffleCards = function(cards) {
  var shuffleIndex = cards.length;
  var temp;
  var randNum;

  while(shuffleIndex) {
    randNum = Math.floor(Math.random() * shuffleIndex--);
    temp = cards[randNum];
    cards[randNum] = cards[shuffleIndex];
    cards[shuffleIndex] = temp;
  }

  return cards;
};

Game.prototype.dealAnswers = function(maxAnswers) {
  maxAnswers = maxAnswers || 10;
  var storeAnswers = function(err, data) {
    this.answers = data;
  };
  for (var i = 0; i < this.players.length; i++) {
    while (this.players[i].hand.length < maxAnswers) {
      this.players[i].hand.push(this.answers.pop());
      if (!this.answers.length) {
        this.getAnswers(storeAnswers);
      }
    }
  }
};

Game.prototype._findPlayerIndexBySocket = function(thisPlayer) {
  var playerIndex = -1;
  _.each(this.players, function(player, index) {
    if (player.socket.id === thisPlayer) {
      playerIndex = index;
    }
  });
  return playerIndex;
};

Game.prototype.pickCards = function(thisCardArray, thisPlayer) {
  // Only accept cards when we expect players to pick a card
  if (this.state === "waiting for players to pick") {
    // Find the player's position in the players array
    var playerIndex = this._findPlayerIndexBySocket(thisPlayer);
    console.log('player is at index',playerIndex);
    if (playerIndex !== -1) {
      // Verify that the player hasn't previously picked a card
      var previouslySubmitted = false;
      _.each(this.table, function(pickedSet, index) {
        if (pickedSet.player === thisPlayer) {
          previouslySubmitted = true;
        }
      });
      if (!previouslySubmitted) {
        // Find the indices of the cards in the player's hand (given the card ids)
        var tableCard = [];
        for (var i = 0; i < thisCardArray.length; i++ ) {
          var cardIndex = null;
          for (var j = 0; j < this.players[playerIndex].hand.length; j++) {
            if (this.players[playerIndex].hand[j].id === thisCardArray[i]) {
              cardIndex = j;
            }
          }
          console.log('card',i,'is at index',cardIndex);
          if (cardIndex !== null) {
            tableCard.push(this.players[playerIndex].hand.splice(cardIndex,1)[0]);
          }
          console.log('table object at',cardIndex,':',tableCard);
        }
        if (tableCard.length === this.curQuestion.numAnswers) {
          this.table.push({
            card: tableCard,
            player: this.players[playerIndex].socket.id
          });
        }
        console.log('final table object',this.table);
        if (this.table.length === this.players.length-1) {
          clearTimeout(this.choosingTimeout);
          this.stateJudging(this);
        } else {
          this.sendUpdate();
        }
      }
    }
  } else {
    console.log('NOTE:',thisPlayer,'picked a card during',this.state);
  }
};

Game.prototype.getPlayer = function(thisPlayer) {
  var playerIndex = this._findPlayerIndexBySocket(thisPlayer);
  if (playerIndex > -1) {
    return this.players[playerIndex];
  } else {
    return {};
  }
};

Game.prototype.removePlayer = function(thisPlayer) {
  var playerIndex = this._findPlayerIndexBySocket(thisPlayer);

  if (playerIndex !== -1) {
    // Just used to send the remaining players a notification
    var playerName = this.players[playerIndex].username;

    // Remove player from this.players
    this.players.splice(playerIndex,1);

    if (this.state === "awaiting players") {
      this.assignPlayerColors();
    }

    // Check if the player is the czar
    if (this.czar === playerIndex) {
      // If the player is the czar...
      // If players are currently picking a card, advance to a new round.
      if (this.state === "waiting for players to pick") {
        clearTimeout(this.choosingTimeout);
        this.sendNotification('The Czar left the game! Starting a new round.');
        return this.stateChoosing(this);
      } else if (this.state === "waiting for czar to decide") {
        // If players are waiting on a czar to pick, auto pick.
        this.sendNotification('The Czar left the game! First answer/s submitted wins!');
        this.pickWinning(this.table[0].card[0].id, thisPlayer, true);
      }
    } else {
      this.sendNotification(playerName+' has left the game.');
    }

    this.sendUpdate();
  }
};

Game.prototype.pickWinning = function(thisCard, thisPlayer, autopicked) {
  autopicked = autopicked || false;
  var playerIndex = this._findPlayerIndexBySocket(thisPlayer);
  if ((playerIndex === this.czar || autopicked) && this.state === "waiting for czar to decide") {
    var cardIndex = -1;
    _.each(this.table, function(winningSet, index) {
      if (winningSet.card[0].id === thisCard) {
        cardIndex = index;
      }
    });
    if (cardIndex !== -1) {
      this.winningCard = cardIndex;
      var winnerIndex = this._findPlayerIndexBySocket(this.table[cardIndex].player);
      this.sendNotification(this.players[winnerIndex].username+' has won the round!');
      this.winningCardPlayer = winnerIndex;
      this.players[winnerIndex].points++;
      clearTimeout(this.judgingTimeout);
      this.winnerAutopicked = autopicked;
      this.stateResults(this);
    } else {
      console.log('WARNING: czar',thisPlayer,'picked a card that was not on the table.');
    }
  } else {
    // TODO: Do something?
    this.sendUpdate();
  }
};

Game.prototype.killGame = function() {
  console.log('Killing game',this.gameID);
  clearTimeout(this.resultsTimeout);
  clearTimeout(this.choosingTimeout);
  clearTimeout(this.judgingTimeout);
};

module.exports = Game;

<|endoftext|>


<commit_before>$('form').submit(function () {

  var originParts = decodeURIComponent(location.search.slice(1)).split('/'),
      origin = `${originParts[0]}//${originParts[2]}`,
      $submitIcon = $('.canvas-submit-icon'), // submit button in Promotions form
      checkSubmitIcon = function () {
        console.log(2);
        if ($submitIcon.css('display') === 'block') { // if submit loader is showing
          console.log(origin);
          clearInterval(interval); // stop checking
          top.postMessage('submitted', origin); // send success message to parent page
          console.log('message sent');
        }
      },
      interval = setInterval(checkSubmitIcon, 100); // check every 1/10th second

  console.log(1);
  console.log(location);
  console.log(origin);

  checkSubmitIcon(); // check initially
  setTimeout(function () { // check for up to 2 seconds
    clearInterval(interval);
  }, 2000);

});
<commit_msg>clean origin<commit_after>$('form').submit(function () {

  var origin = decodeURIComponent(location.search.slice(1)).split('&')[0],
      $submitIcon = $('.canvas-submit-icon'), // submit button in Promotions form
      checkSubmitIcon = function () {
        console.log(2);
        if ($submitIcon.css('display') === 'block') { // if submit loader is showing
          console.log(origin);
          clearInterval(interval); // stop checking
          top.postMessage('submitted', origin); // send success message to parent page
          console.log('message sent');
        }
      },
      interval = setInterval(checkSubmitIcon, 100); // check every 1/10th second

  console.log(1);
  console.log(location);
  console.log(origin);

  checkSubmitIcon(); // check initially
  setTimeout(function () { // check for up to 2 seconds
    clearInterval(interval);
  }, 2000);

});
<|endoftext|>


<commit_before>/**
 * Event storage method
 * Event send method
 */
// jsflight namespace
var jsflight = jsflight || {};

jsflight.checkTargetDetach = function(element){
    if(!element || !element.parentNode || !element.tagName){
        return false;
    }
    while(element.parentNode != null){
        element = element.parentNode;
    }
    if(!element.tagName){
        return false;
    }
    return !(element.tagName.toLowerCase === 'html')
}

jsflight.getDetachElement = function(event){
    var targetPath = event.path;
    for(var i=0; i< targetPath.length; i++){
        if(!targetPath[i].parentNode){
            return targetPath[i+1];
        }
    }
}

jsflight.getEventInfo = function(mouseEvent) {
    if (mouseEvent === undefined)
        mouseEvent = window.event;

    mouseEvent.target = 'target' in mouseEvent ? mouseEvent.target
        : mouseEvent.srcElement;

    var result = {};

    result.tabuuid = jsflight.tabUuid;
    result.type = mouseEvent.type;
    result.url = window.location.href;
    result.which = mouseEvent.which;
    result.key = mouseEvent.key;
    result.keyCode = mouseEvent.keyCode;
    result.charCode = mouseEvent.charCode;

    if (mouseEvent.type === 'keyup') {
        if (!event.shiftKey) {
            result.charCode = String.fromCharCode(result.charCode)
                    .toLowerCase().charCodeAt(0);
        }
    }
    result.altKey = mouseEvent.altKey;
    result.ctrlKey = mouseEvent.ctrlKey;
    result.shiftKey = mouseEvent.shiftKey;
    result.metaKey = mouseEvent.metaKey;
    result.button = mouseEvent.button;
    result.hash = window.location.hash;

    result.target = jsflight.getElementXPath(mouseEvent.target);
    result.target1 = jsflight.getTargetId(mouseEvent);
    result.target2 = jsflight.getElementXpathId(mouseEvent.target);

    if(!result.target2 && jsflight.checkTargetDetach(mouseEvent.target)){
        result.target2 = jsflight.getDetachedElementXpathId(mouseEvent.target, jsflight.getDetachElement(mouseEvent));
    }

    result.timestamp = Date.now();

    result.screenX = mouseEvent.screenX;
    result.screenY = mouseEvent.screenY;

    result.pageX = mouseEvent.pageX;
    result.pageY = mouseEvent.pageY;

    result.screen = {
    		width : screen.width,
    		height : screen.height
    		};

    result.window = {
	    	    width : window.outerWidth,
	    	    height : window.outerHeight
    		};

    result.page = {
    			width : window.innerWidth,
    			height : window.innerHeight
    		};

    result.agent = navigator.userAgent;
    result.image = mouseEvent.image;
    result.dom = mouseEvent.dom;
    result.eventId = mouseEvent.eventId;

    result.newUrl = mouseEvent.newURL;
    result.oldUrl = mouseEvent.oldURL;

    result.deltaX = mouseEvent.deltaX;
    result.deltaY = mouseEvent.deltaY;
    result.deltaZ = mouseEvent.deltaZ;

    if (jsflight.options.propertyProvider) {
        jsflight.options.propertyProvider(result);
    }

    return result;
};

/**
 * Store event to session storage
 *
 * @param eventid
 * @param eventdata
 */
jsflight.saveToStorage = function(eventid, eventdata) {
    if (typeof (window.sessionStorage) == "undefined") {
        console.log('No support of window.sessionStorage');
        return;
    }

    window.sessionStorage.setItem("recorder.max", eventid);
    window.sessionStorage.setItem('recorder.eventId.' + eventid, eventdata);
};

/**
 * Clear session storage
 */
jsflight.clearStorage = function() {
    jsflight.eventId = 0;
    sessionStorage.clear();
};

/**
 * send current batch of stored events and clear session storage
 */
jsflight.sendEventData = function(sendStop) {

    if (jsflight.started === false)
        return;

    if (typeof (window.sessionStorage) == "undefined") {
        console.log('No support of window.sessionStorage');
        return;
    }
    var storage = window.sessionStorage;

    var events = [];
    var keys = [];
    for ( var key in storage) {
        if (key.indexOf('recorder.eventId.') === 0) {
            events.push(storage.getItem(key));
            keys.push(key);
        }
    }

    // it is pity to send an empty array. No tracked data no xhr post
    if (events.length === 0 && sendStop === false)
        return;

    var data = JSON.stringify(events);
    var uri = jsflight.options.baseUrl + jsflight.options.downloadPath;
    if (sendStop) {
        uri += "?stop";
    }
    var xhr = new XMLHttpRequest();
    xhr.open('POST', uri, true);
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.onload = function() {
        if (xhr.status == 200) {
            for (var i = 0; i < keys.length; i++) {
                storage.removeItem(keys[i]);
            }
        } else {
            console.log("error storing data. status " + xhr.status);
        }
    };
    xhr.send('data=' + encodeURIComponent(data));
};
<commit_msg>Storing wheelDelta<commit_after>/**
 * Event storage method
 * Event send method
 */
// jsflight namespace
var jsflight = jsflight || {};

jsflight.checkTargetDetach = function(element){
    if(!element || !element.parentNode || !element.tagName){
        return false;
    }
    while(element.parentNode != null){
        element = element.parentNode;
    }
    if(!element.tagName){
        return false;
    }
    return !(element.tagName.toLowerCase === 'html')
}

jsflight.getDetachElement = function(event){
    var targetPath = event.path;
    for(var i=0; i< targetPath.length; i++){
        if(!targetPath[i].parentNode){
            return targetPath[i+1];
        }
    }
}

jsflight.getEventInfo = function(mouseEvent) {
    if (mouseEvent === undefined)
        mouseEvent = window.event;

    mouseEvent.target = 'target' in mouseEvent ? mouseEvent.target
        : mouseEvent.srcElement;

    var result = {};

    result.tabuuid = jsflight.tabUuid;
    result.type = mouseEvent.type;
    result.url = window.location.href;
    result.which = mouseEvent.which;
    result.key = mouseEvent.key;
    result.keyCode = mouseEvent.keyCode;
    result.charCode = mouseEvent.charCode;

    if (mouseEvent.type === 'keyup') {
        if (!event.shiftKey) {
            result.charCode = String.fromCharCode(result.charCode)
                    .toLowerCase().charCodeAt(0);
        }
    }
    result.altKey = mouseEvent.altKey;
    result.ctrlKey = mouseEvent.ctrlKey;
    result.shiftKey = mouseEvent.shiftKey;
    result.metaKey = mouseEvent.metaKey;
    result.button = mouseEvent.button;
    result.hash = window.location.hash;

    result.target = jsflight.getElementXPath(mouseEvent.target);
    result.target1 = jsflight.getTargetId(mouseEvent);
    result.target2 = jsflight.getElementXpathId(mouseEvent.target);

    if(!result.target2 && jsflight.checkTargetDetach(mouseEvent.target)){
        result.target2 = jsflight.getDetachedElementXpathId(mouseEvent.target, jsflight.getDetachElement(mouseEvent));
    }

    result.timestamp = Date.now();

    result.screenX = mouseEvent.screenX;
    result.screenY = mouseEvent.screenY;

    result.pageX = mouseEvent.pageX;
    result.pageY = mouseEvent.pageY;

    result.screen = {
    		width : screen.width,
    		height : screen.height
    		};

    result.window = {
	    	    width : window.outerWidth,
	    	    height : window.outerHeight
    		};

    result.page = {
    			width : window.innerWidth,
    			height : window.innerHeight
    		};

    result.agent = navigator.userAgent;
    result.image = mouseEvent.image;
    result.dom = mouseEvent.dom;
    result.eventId = mouseEvent.eventId;

    result.newUrl = mouseEvent.newURL;
    result.oldUrl = mouseEvent.oldURL;

    result.deltaX = mouseEvent.deltaX;
    result.deltaY = mouseEvent.deltaY;
    result.deltaZ = mouseEvent.deltaZ;

    result.wheelDelta = mouseEvent.wheelDelta;

    if (jsflight.options.propertyProvider) {
        jsflight.options.propertyProvider(result);
    }

    return result;
};

/**
 * Store event to session storage
 *
 * @param eventid
 * @param eventdata
 */
jsflight.saveToStorage = function(eventid, eventdata) {
    if (typeof (window.sessionStorage) == "undefined") {
        console.log('No support of window.sessionStorage');
        return;
    }

    window.sessionStorage.setItem("recorder.max", eventid);
    window.sessionStorage.setItem('recorder.eventId.' + eventid, eventdata);
};

/**
 * Clear session storage
 */
jsflight.clearStorage = function() {
    jsflight.eventId = 0;
    sessionStorage.clear();
};

/**
 * send current batch of stored events and clear session storage
 */
jsflight.sendEventData = function(sendStop) {

    if (jsflight.started === false)
        return;

    if (typeof (window.sessionStorage) == "undefined") {
        console.log('No support of window.sessionStorage');
        return;
    }
    var storage = window.sessionStorage;

    var events = [];
    var keys = [];
    for ( var key in storage) {
        if (key.indexOf('recorder.eventId.') === 0) {
            events.push(storage.getItem(key));
            keys.push(key);
        }
    }

    // it is pity to send an empty array. No tracked data no xhr post
    if (events.length === 0 && sendStop === false)
        return;

    var data = JSON.stringify(events);
    var uri = jsflight.options.baseUrl + jsflight.options.downloadPath;
    if (sendStop) {
        uri += "?stop";
    }
    var xhr = new XMLHttpRequest();
    xhr.open('POST', uri, true);
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.onload = function() {
        if (xhr.status == 200) {
            for (var i = 0; i < keys.length; i++) {
                storage.removeItem(keys[i]);
            }
        } else {
            console.log("error storing data. status " + xhr.status);
        }
    };
    xhr.send('data=' + encodeURIComponent(data));
};
<|endoftext|>


<commit_before>import Config from 'classes/Config';
import DefinitionClass from 'classes/Definition';
import Vue from 'vue';

/* global self, console, document */
/* eslint-disable no-console */

let winObj;

const vue = new Vue();

// window object exists
if(typeof self === 'object' && self.self === self) {
	winObj = self;
}
// fake our window object for testing/SSR
else {
	winObj = {};
	winObj.self = winObj;
	winObj.top = winObj;
}

export const win = winObj;

export const inIframeContext = () => {
	return win.self !== win.top;
};

export const isIframe = inIframeContext();

export const debug = (output, type = 'info') => {
	if(!Config.get('debug', false)) {
		return;
	}

	console[type](output);
};

export const uuid = (a) => {
	return a ?
		(a^Math.random() * 16 >> a / 4).toString(16) :
		([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, uuid);
};

export const Definition = (
	isIframe ? win.top.astroDefinition : (win.astroDefinition = DefinitionClass)
);

export const clamp = ({ val, min, max }) => {
	return Math.max(Math.min(val, max), min);
};

// Adapted from https://gist.github.com/desandro/4206095
export const smoothScrollTo = (options) => {
	const { element: el, y, x, duration, easing } = {
		element: document.body,
		x: 0,
		y: 0,
		duration: '0.3s',
		easing: 'ease-out',
		...options
	};

	// clamp values to min & max scroll
	// then remove the current scroll position
	let
		targetX = clamp({
			val: x,
			min: 0,
			max: el.scrollWidth - win.innerWidth
		}) - win.scrollX,

		targetY = clamp({
			val: y,
			min: 0,
			max: el.scrollHeight - win.innerHeight
		}) - win.scrollY;

	el.style.transition = `transform ${duration} ${easing}`;
	el.style.transform = `translate(${-targetX}px, ${-targetY}px)`;

	const onEnd = (e) => {
		if(e.target !== el) {
			return;
		}

		el.style.transition = null;
		el.style.transform = null;

		win.scrollTo(x, y);

		el.removeEventListener('transitionend', onEnd, false);
	};

	el.addEventListener('transitionend', onEnd, false);
};

export const readingSpeedFromString = (str = '', timeToNotice = 500) => {
	// average reading speed (CPM) + half a second to notice snackbar
	return Math.ceil((str.length * 60000) / 863) + timeToNotice;
};

/**
 * Get a rough estimate of time passed between a date and now.
 * @param {String} date - A date parsable by new Date(date)... although this should not include the timezone at the end or things will get "fun"
 * @param {boolean} about - True to include the word "about" before the result if the time is not exact
 * @param {integer|null} timezoneOffset - The timezone offset from UCT for the passed date string
 * @returns {string} - A nicely formatted string, e.g "about 5 minutes ago"
 */
export const prettyDate = (date, about = true, timezoneOffset = null) => {
    if(!Number.isInteger(timezoneOffset)) {
        timezoneOffset = new Date().getTimezoneOffset();
    }
    // get "now" in UCT seconds
    const now = Date.now() + (new Date().getTimezoneOffset() * 60000);
    const then = new Date(date).getTime() + (timezoneOffset * 60000);
    let diff = (now - then) / 1000,
		unit = ['second', 'minute', 'hour', 'day', 'week', 'month', 'year'],
		num = [60, 60, 24, 7, 4.35, 12],
		i = 0;

	while(i < num.length && diff >= num[i]) {
		diff /= num[i++];
	}

	diff = Math.round(diff);

	return `${(i > 0 && about) ? 'about ' : ''}${diff} ${unit[i]}${diff === 1 ? '' : 's'} ago`;
};

export const notify = ({ title, message, type }) => {
	// TODO:is notify is overkill for some scenarios?
	// Element UI's $message seems more suited to success messages
	vue.$notify({
		title,
		message,
		type,
		duration: readingSpeedFromString(message, 3000),
		onClick() {
			this.close();
		}
	});
};

// Does the given string start with a vowel? If so return "an", otherwise "a".
// Doesn't cover all cases, but is good enough for now.
export const aOrAn = (str) => str.match(/^[aeiou]/i) ? 'an' : 'a';

export const pageHasBeenPublished = (page) => {
	return page.status !== 'new';
};

/**
 * Get the URL at which the current page can be previewed in the editor.
 *
 * @param {string} domain - The domain name for the site.
 * @param {string} path - The full path of the page to generate the URL for.
 *
 * @returns {string} URL
 */
export const getDraftPreviewURL = (domain, path) => {
	let pattern = Config.get('draft_url_pattern') || '{domain}{path}';
	return pattern.replace(/{domain}/ig, domain).replace(/{path}/ig, path);
};

/**
 * Get the URL at which the published version of the current page can be previewed in the editor.
 *
 * @param {string} domain - The domain name for the site.
 * @param {string} path - The full path of the page to generate the URL for.
 *
 * @returns {string} URL
 */
export const getPublishedPreviewURL = (domain, path) => {
	let pattern = Config.get('published_url_pattern') || '{domain}{path}';
	return pattern.replace(/{domain}/ig, domain).replace(/{path}/ig, path);
};

/**
 * Get a url for an image or a default.
 * @param {String|Object|null} url - URL to the image OR object with url attribute OR null to use default.
 * @param {string|null} defaultUrl - Alternative placeholder image to use (relative to Config.get('assets_base_url') )
  * @param {object|null} options - Options to allow for for video or square images
 * @returns {string} - url, or Config.get('assets_base_url') + defaultUrl or Config.get('assets_base_url') + Config.get('default_placeholder_image')
 */
export const imageUrl = (src_or_url, defaultUrl, options) => {
	let result = (typeof src_or_url !== 'undefined') && src_or_url && src_or_url.url ? src_or_url.url: src_or_url;
	if(!result) {
		result = Config.get('assets_base_url');
		if(typeof defaultUrl !== 'undefined') {
			result += defaultUrl;
		}
		else {
			result += Config.get('placeholder_image_url');
		}
	}
	// if we have an image, make sure we choose the right version and not the original (a different version is needed for video placeholders)
	else {
		console.log(options);
		if (typeof options !== 'undefined' && options.video === true) {

			result = result.substring(0, result.length - 4) + Config.get('video_version_suffix') + ".jpg";
		}
		else if (typeof options !== 'undefined' && options.square === true) {
			result = result.substring(0, result.length - 4) + Config.get('square_version_suffix') + ".jpg";
		}
		else {
			result = result.substring(0, result.length - 4) + Config.get('image_version_suffix') + ".jpg";
		}
	}
	return result;
//	return url !== void 0 ? url :
//		Config.get('assets_base_url') + (defaultUrl !== void 0 ? defaultUrl : Config.get('default_placeholder_url'));
};

/**
	* Generates full url to an asset
	* @param {String} path - the relative path to the asset.
	* @returns {String} - the full URL to the asset, taking into account the configured assets base url.
	*/
export const assetsUrl = (path) => {
	return Config.get("assets_base_url") + path;
};

/**
	* Generates full url to the block images
	* @param {String} path - the relative path to the block images.
	* @returns {String} - the full URL to the block images, taking into account the configured block images base url.
	*/
export const blockImageUrl = (path) => {
	return Config.get("block_image_url") + '/' + path;
};
<commit_msg>got rid of console.log<commit_after>import Config from 'classes/Config';
import DefinitionClass from 'classes/Definition';
import Vue from 'vue';

/* global self, console, document */
/* eslint-disable no-console */

let winObj;

const vue = new Vue();

// window object exists
if(typeof self === 'object' && self.self === self) {
	winObj = self;
}
// fake our window object for testing/SSR
else {
	winObj = {};
	winObj.self = winObj;
	winObj.top = winObj;
}

export const win = winObj;

export const inIframeContext = () => {
	return win.self !== win.top;
};

export const isIframe = inIframeContext();

export const debug = (output, type = 'info') => {
	if(!Config.get('debug', false)) {
		return;
	}

	console[type](output);
};

export const uuid = (a) => {
	return a ?
		(a^Math.random() * 16 >> a / 4).toString(16) :
		([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, uuid);
};

export const Definition = (
	isIframe ? win.top.astroDefinition : (win.astroDefinition = DefinitionClass)
);

export const clamp = ({ val, min, max }) => {
	return Math.max(Math.min(val, max), min);
};

// Adapted from https://gist.github.com/desandro/4206095
export const smoothScrollTo = (options) => {
	const { element: el, y, x, duration, easing } = {
		element: document.body,
		x: 0,
		y: 0,
		duration: '0.3s',
		easing: 'ease-out',
		...options
	};

	// clamp values to min & max scroll
	// then remove the current scroll position
	let
		targetX = clamp({
			val: x,
			min: 0,
			max: el.scrollWidth - win.innerWidth
		}) - win.scrollX,

		targetY = clamp({
			val: y,
			min: 0,
			max: el.scrollHeight - win.innerHeight
		}) - win.scrollY;

	el.style.transition = `transform ${duration} ${easing}`;
	el.style.transform = `translate(${-targetX}px, ${-targetY}px)`;

	const onEnd = (e) => {
		if(e.target !== el) {
			return;
		}

		el.style.transition = null;
		el.style.transform = null;

		win.scrollTo(x, y);

		el.removeEventListener('transitionend', onEnd, false);
	};

	el.addEventListener('transitionend', onEnd, false);
};

export const readingSpeedFromString = (str = '', timeToNotice = 500) => {
	// average reading speed (CPM) + half a second to notice snackbar
	return Math.ceil((str.length * 60000) / 863) + timeToNotice;
};

/**
 * Get a rough estimate of time passed between a date and now.
 * @param {String} date - A date parsable by new Date(date)... although this should not include the timezone at the end or things will get "fun"
 * @param {boolean} about - True to include the word "about" before the result if the time is not exact
 * @param {integer|null} timezoneOffset - The timezone offset from UCT for the passed date string
 * @returns {string} - A nicely formatted string, e.g "about 5 minutes ago"
 */
export const prettyDate = (date, about = true, timezoneOffset = null) => {
    if(!Number.isInteger(timezoneOffset)) {
        timezoneOffset = new Date().getTimezoneOffset();
    }
    // get "now" in UCT seconds
    const now = Date.now() + (new Date().getTimezoneOffset() * 60000);
    const then = new Date(date).getTime() + (timezoneOffset * 60000);
    let diff = (now - then) / 1000,
		unit = ['second', 'minute', 'hour', 'day', 'week', 'month', 'year'],
		num = [60, 60, 24, 7, 4.35, 12],
		i = 0;

	while(i < num.length && diff >= num[i]) {
		diff /= num[i++];
	}

	diff = Math.round(diff);

	return `${(i > 0 && about) ? 'about ' : ''}${diff} ${unit[i]}${diff === 1 ? '' : 's'} ago`;
};

export const notify = ({ title, message, type }) => {
	// TODO:is notify is overkill for some scenarios?
	// Element UI's $message seems more suited to success messages
	vue.$notify({
		title,
		message,
		type,
		duration: readingSpeedFromString(message, 3000),
		onClick() {
			this.close();
		}
	});
};

// Does the given string start with a vowel? If so return "an", otherwise "a".
// Doesn't cover all cases, but is good enough for now.
export const aOrAn = (str) => str.match(/^[aeiou]/i) ? 'an' : 'a';

export const pageHasBeenPublished = (page) => {
	return page.status !== 'new';
};

/**
 * Get the URL at which the current page can be previewed in the editor.
 *
 * @param {string} domain - The domain name for the site.
 * @param {string} path - The full path of the page to generate the URL for.
 *
 * @returns {string} URL
 */
export const getDraftPreviewURL = (domain, path) => {
	let pattern = Config.get('draft_url_pattern') || '{domain}{path}';
	return pattern.replace(/{domain}/ig, domain).replace(/{path}/ig, path);
};

/**
 * Get the URL at which the published version of the current page can be previewed in the editor.
 *
 * @param {string} domain - The domain name for the site.
 * @param {string} path - The full path of the page to generate the URL for.
 *
 * @returns {string} URL
 */
export const getPublishedPreviewURL = (domain, path) => {
	let pattern = Config.get('published_url_pattern') || '{domain}{path}';
	return pattern.replace(/{domain}/ig, domain).replace(/{path}/ig, path);
};

/**
 * Get a url for an image or a default.
 * @param {String|Object|null} url - URL to the image OR object with url attribute OR null to use default.
 * @param {string|null} defaultUrl - Alternative placeholder image to use (relative to Config.get('assets_base_url') )
  * @param {object|null} options - Options to allow for for video or square images
 * @returns {string} - url, or Config.get('assets_base_url') + defaultUrl or Config.get('assets_base_url') + Config.get('default_placeholder_image')
 */
export const imageUrl = (src_or_url, defaultUrl, options) => {
	let result = (typeof src_or_url !== 'undefined') && src_or_url && src_or_url.url ? src_or_url.url: src_or_url;
	if(!result) {
		result = Config.get('assets_base_url');
		if(typeof defaultUrl !== 'undefined') {
			result += defaultUrl;
		}
		else {
			result += Config.get('placeholder_image_url');
		}
	}
	// if we have an image, make sure we choose the right version and not the original (a different version is needed for video placeholders)
	else {
		if (typeof options !== 'undefined' && options.video === true) {
			result = result.substring(0, result.length - 4) + Config.get('video_version_suffix') + ".jpg";
		}
		else if (typeof options !== 'undefined' && options.square === true) {
			result = result.substring(0, result.length - 4) + Config.get('square_version_suffix') + ".jpg";
		}
		else {
			result = result.substring(0, result.length - 4) + Config.get('image_version_suffix') + ".jpg";
		}
	}
	return result;
//	return url !== void 0 ? url :
//		Config.get('assets_base_url') + (defaultUrl !== void 0 ? defaultUrl : Config.get('default_placeholder_url'));
};

/**
	* Generates full url to an asset
	* @param {String} path - the relative path to the asset.
	* @returns {String} - the full URL to the asset, taking into account the configured assets base url.
	*/
export const assetsUrl = (path) => {
	return Config.get("assets_base_url") + path;
};

/**
	* Generates full url to the block images
	* @param {String} path - the relative path to the block images.
	* @returns {String} - the full URL to the block images, taking into account the configured block images base url.
	*/
export const blockImageUrl = (path) => {
	return Config.get("block_image_url") + '/' + path;
};
<|endoftext|>


<commit_before>/****************************************************************************
 * Copyright (C) 2015-2016 EPAM Systems
 *
 * This file is part of Indigo-Node binding.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 3 as published by the Free Software
 * Foundation and appearing in the file LICENSE.md  included in the
 * packaging of this file.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

/* declaration of modules  */
var assert = require('assert');
var path = require('path');
var fs = require('fs');
var local = path.join.bind(path, __dirname);

var Indigo = require("../indigo-node/indigo");
var indigo = new Indigo();
var IndigoInchi = require("../indigo-node/indigo_inchi");
var indigo_inchi = new IndigoInchi(indigo);

console.log(indigo_inchi.version());

console.log("*** Basic *** ");
var m = indigo_inchi.loadMolecule("InChI=1S/C10H20N2O2/c11-7-1-5-2-8(12)10(14)4-6(5)3-9(7)13/h5-10,13-14H,1-4,11-12H2");
console.log(m.canonicalSmiles());<commit_msg>add UT: indigo_inchi.getInchi indigo_inchi.getWarning<commit_after>/****************************************************************************
 * Copyright (C) 2015-2016 EPAM Systems
 *
 * This file is part of Indigo-Node binding.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 3 as published by the Free Software
 * Foundation and appearing in the file LICENSE.md  included in the
 * packaging of this file.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

/* declaration of modules  */
var assert = require('assert');
var path = require('path');
var fs = require('fs');
var local = path.join.bind(path, __dirname);

var Indigo = require("../indigo-node/indigo");
var indigo = new Indigo();
var IndigoInchi = require("../indigo-node/indigo_inchi");
var indigo_inchi = new IndigoInchi(indigo);

console.log(indigo_inchi.version());

console.log("*** Basic *** ");
var m = indigo_inchi.loadMolecule("InChI=1S/C10H20N2O2/c11-7-1-5-2-8(12)10(14)4-6(5)3-9(7)13/h5-10,13-14H,1-4,11-12H2");
console.log(m.canonicalSmiles());
console.log(indigo_inchi.getInchi(m));
console.log(indigo_inchi.getWarning());
<|endoftext|>


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

/**
 * WordPress dependencies
 */
import { createRegistry } from '@wordpress/data';

/**
 * Internal dependencies
 */
import {
	addInitializeAction,
	addInitializeReducer,
	collectActions,
	collectControls,
	collectReducers,
	collectResolvers,
	collectSelectors,
	collectState,
	collectName,
	commonActions,
	commonControls,
} from 'assets/js/googlesitekit/data/utils';

const Data = createRegistry();

// Attach some of our utility functions to the registry so third-party
// developers can use them.
Data.addInitializeAction = addInitializeAction;
Data.addInitializeReducer = addInitializeReducer;
Data.collectActions = collectActions;
Data.collectControls = collectControls;
Data.collectReducers = collectReducers;
Data.collectResolvers = collectResolvers;
Data.collectSelectors = collectSelectors;
Data.collectState = collectState;
Data.collectName = collectName;
Data.commonActions = commonActions;
Data.commonControls = commonControls;

export default Data;
<commit_msg>Export registry control and selector creators.<commit_after>/**
 * Site Kit @wordpress/data (eg Redux-style) data store.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * WordPress dependencies
 */
import { createRegistry } from '@wordpress/data';
export {
	createRegistryControl,
	createRegistrySelector,
} from '@wordpress/data';

/**
 * Internal dependencies
 */
import {
	addInitializeAction,
	addInitializeReducer,
	collectActions,
	collectControls,
	collectReducers,
	collectResolvers,
	collectSelectors,
	collectState,
	collectName,
	commonActions,
	commonControls,
} from 'assets/js/googlesitekit/data/utils';

const Data = createRegistry();

// Attach some of our utility functions to the registry so third-party
// developers can use them.
Data.addInitializeAction = addInitializeAction;
Data.addInitializeReducer = addInitializeReducer;
Data.collectActions = collectActions;
Data.collectControls = collectControls;
Data.collectReducers = collectReducers;
Data.collectResolvers = collectResolvers;
Data.collectSelectors = collectSelectors;
Data.collectState = collectState;
Data.collectName = collectName;
Data.commonActions = commonActions;
Data.commonControls = commonControls;

export default Data;
<|endoftext|>


<commit_before> ( function( mw, $ ) {"use strict";

    mw.KMenu = function( $element, options ) {

    	// Set some defaults
    	var defaults = {
            cssClass: "dropdown-menu",
            tabIndex: 1,
            closeOnFocusOut: true,
            attributes: {
				'role': 'menu',
				'aria-labelledby': 'dLabel'
			},
			dividerClass: 'divider'
        };

        this.bindPostfix = '.kMenu';
        this.$el = $element;
        this.options = $.extend( {}, defaults, options) ;

        this.itemIdx = 0;
	    this.selectedIndex = -1; // holds the currently active item index
        this.init();
        return this;
    }

    mw.KMenu.prototype = {
        init: function(){
            var _this = this;
            // Add CSS class
            if( this.options.cssClass ){
            	this.$el.addClass(this.options.cssClass);
            }
            // Add attributes
            if( $.isPlainObject(this.options.attributes) ){
            	this.$el.attr(this.options.attributes);
            }
            this.$el.attr({
                'role':'menu'
            });
            // Add unique id
            this.$el.uniqueId();
        },
        getTabIndex: function(idx){
            var tabIndex = parseFloat(this.options.tabIndex + '.00');
            idx = (idx < 10) ? '0' + idx : idx;
            return tabIndex += parseFloat('.' + idx);
        },
        addItem: function( item ){
        	var _this = this;
        	item.idx = this.itemIdx;
            var attrs = item.attributes || {};
            var $item = $('<li />')
						.addClass(item.cssClass)
                        .attr(attrs)
						.append(
							$('<a />')
							.attr({
								'href': '#',
                                'title': item.label,
                                'role': 'menuitemcheckbox',
                                'aria-checked': 'false',
								'tabindex': this.getTabIndex(this.itemIdx + 1)
							})
							.text( item.label )
							.click(function(e){
								e.preventDefault();
								_this.setActive( item.idx );
								_this.selectedIndex = item.idx;
								if( $.isFunction( item.callback ) ){
									item.callback();
								}
								_this.close();
							})
						);

            // If not the first item
            if( this.itemIdx > 0 ){
                this.addDivider();
            }

			this.$el.append( $item );

            if( item.active ){
                $item.addClass('active').attr('aria-checked', 'true');
	            this.selectedIndex = this.itemIdx;
            }
			// Incrase out counter ( for tab index )
			this.itemIdx++;
        },
        addDivider: function(){
        	this.$el.append( $( '<li />').addClass( this.options.dividerClass ) );
        },
        isOpen: function(){
        	return this.$el.hasClass('open');
        },
        open: function(){
        	var _this = this;
        	this.$el.addClass('open');
        	// Bind to click event and close the menu
            if( this.options.closeOnFocusOut ) {
                setTimeout(function(){
            	$(document).on('click' + _this.bindPostfix + _this.$el.attr('id'), function(){
            		_this.close();
            	});
                },0);
            }
        },
        close: function(){
        	this.$el.removeClass('open');
			if( this.options.closeOnFocusOut ){
        		$(document).off('click' + this.bindPostfix + this.$el.attr('id'));
        	}
        },
        toggle: function(){
        	if( this.isOpen() ){
        		this.close();
        	} else {
        		this.open();
        	}
        },
	    previousItem: function(){
		    this.selectedIndex--;
		    if (this.selectedIndex < 0){
			    this.selectedIndex = this.itemIdx-1;
		    }
		    this.setActive( this.selectedIndex );

	    },
	    nextItem: function(){
		    this.selectedIndex++;
		    if (this.selectedIndex == this.itemIdx){
			    this.selectedIndex = 0;
		    }
		    this.setActive( this.selectedIndex );

	    },
        disable: function(){
            this.$el.addClass('disabled');
        },
        setActive: function( idx ){
            // Clear all other items
            this.clearActive();
            // Set active
            var selector = null;
            if( typeof idx == 'number' ){
                selector = 'li:not(.' + this.options.dividerClass + ',.label):eq(' + idx + ')';
            } else {
                selector = 'li[' + idx.key + '=' + idx.val + ']';
            }
	        this.$el.find( selector ).addClass( 'active' ).attr('aria-checked', 'true');
	        this.$el.find( selector +" a").focus();
	        // for IE8, force screen refresh
	        if (mw.isIE8()){
		        this.$el.addClass('dummy').removeClass('dummy');
	        }
        },
        clearActive: function(){
        	this.$el.find('li').removeClass('active').attr('aria-checked', 'false');
        },
        destroy: function(){
            this.$el.empty();
            this.itemIdx = 0;
        },
		numOfChildren: function() {
			return this.itemIdx;
		}
    };

} )( window.mw, window.jQuery );<commit_msg>Revert "Ignore li with "label" class"<commit_after> ( function( mw, $ ) {"use strict";

    mw.KMenu = function( $element, options ) {

    	// Set some defaults
    	var defaults = {
            cssClass: "dropdown-menu",
            tabIndex: 1,
            closeOnFocusOut: true,
            attributes: {
				'role': 'menu',
				'aria-labelledby': 'dLabel'
			},
			dividerClass: 'divider'
        };

        this.bindPostfix = '.kMenu';
        this.$el = $element;
        this.options = $.extend( {}, defaults, options) ;

        this.itemIdx = 0;
	    this.selectedIndex = -1; // holds the currently active item index
        this.init();
        return this;
    }

    mw.KMenu.prototype = {
        init: function(){
            var _this = this;
            // Add CSS class
            if( this.options.cssClass ){
            	this.$el.addClass(this.options.cssClass);
            }
            // Add attributes
            if( $.isPlainObject(this.options.attributes) ){
            	this.$el.attr(this.options.attributes);
            }
            this.$el.attr({
                'role':'menu'
            });
            // Add unique id
            this.$el.uniqueId();
        },
        getTabIndex: function(idx){
            var tabIndex = parseFloat(this.options.tabIndex + '.00');
            idx = (idx < 10) ? '0' + idx : idx;
            return tabIndex += parseFloat('.' + idx);
        },
        addItem: function( item ){
        	var _this = this;
        	item.idx = this.itemIdx;
            var attrs = item.attributes || {};
            var $item = $('<li />')
						.addClass(item.cssClass)
                        .attr(attrs)
						.append(
							$('<a />')
							.attr({
								'href': '#',
                                'title': item.label,
                                'role': 'menuitemcheckbox',
                                'aria-checked': 'false',
								'tabindex': this.getTabIndex(this.itemIdx + 1)
							})
							.text( item.label )
							.click(function(e){
								e.preventDefault();
								_this.setActive( item.idx );
								_this.selectedIndex = item.idx;
								if( $.isFunction( item.callback ) ){
									item.callback();
								}
								_this.close();
							})
						);

            // If not the first item
            if( this.itemIdx > 0 ){
                this.addDivider();
            }

			this.$el.append( $item );

            if( item.active ){
                $item.addClass('active').attr('aria-checked', 'true');
	            this.selectedIndex = this.itemIdx;
            }
			// Incrase out counter ( for tab index )
			this.itemIdx++;
        },
        addDivider: function(){
        	this.$el.append( $( '<li />').addClass( this.options.dividerClass ) );
        },
        isOpen: function(){
        	return this.$el.hasClass('open');
        },
        open: function(){
        	var _this = this;
        	this.$el.addClass('open');
        	// Bind to click event and close the menu
            if( this.options.closeOnFocusOut ) {
                setTimeout(function(){
            	$(document).on('click' + _this.bindPostfix + _this.$el.attr('id'), function(){
            		_this.close();
            	});
                },0);
            }
        },
        close: function(){
        	this.$el.removeClass('open');
			if( this.options.closeOnFocusOut ){
        		$(document).off('click' + this.bindPostfix + this.$el.attr('id'));
        	}
        },
        toggle: function(){
        	if( this.isOpen() ){
        		this.close();
        	} else {
        		this.open();
        	}
        },
	    previousItem: function(){
		    this.selectedIndex--;
		    if (this.selectedIndex < 0){
			    this.selectedIndex = this.itemIdx-1;
		    }
		    this.setActive( this.selectedIndex );

	    },
	    nextItem: function(){
		    this.selectedIndex++;
		    if (this.selectedIndex == this.itemIdx){
			    this.selectedIndex = 0;
		    }
		    this.setActive( this.selectedIndex );

	    },
        disable: function(){
            this.$el.addClass('disabled');
        },
        setActive: function( idx ){
            // Clear all other items
            this.clearActive();
            // Set active
            var selector = null;
            if( typeof idx == 'number' ){
                selector = 'li:not(.' + this.options.dividerClass + '):eq(' + idx + ')';
            } else {
                selector = 'li[' + idx.key + '=' + idx.val + ']';
            }
	        this.$el.find( selector ).addClass( 'active' ).attr('aria-checked', 'true');
	        this.$el.find( selector +" a").focus();
	        // for IE8, force screen refresh
	        if (mw.isIE8()){
		        this.$el.addClass('dummy').removeClass('dummy');
	        }
        },
        clearActive: function(){
        	this.$el.find('li').removeClass('active').attr('aria-checked', 'false');
        },
        destroy: function(){
            this.$el.empty();
            this.itemIdx = 0;
        },
		numOfChildren: function() {
			return this.itemIdx;
		}
    };

} )( window.mw, window.jQuery );<|endoftext|>


<commit_before>$(document).ready(function() {

  configureDataTables();
  configureCodeBox();
  configureGolf();

  $("form#run-code button#approve-button").live("click", function(e) {
    e.preventDefault();
    if(confirm("Are you sure you want to mark this problem as approved?"))
      $(this).parents("form").attr("action", "/problem/approve").submit();
  });

  $("form#run-code button#reject-button").live("click", function(e) {
    e.preventDefault();
    if(confirm("Are you sure you want to reject this problem? It will be permanently deleted.")) {
      $(this).parents("form").attr("action", "/problem/reject").submit();
    }
  });

  $("form#run-code button#edit-button").live("click", function(e) {
    e.preventDefault();
    $(this).parents("form").attr("action", "/problem/edit").submit();
  });

  $("button.user-follow-button").live("click", function(e) {
      e.preventDefault();
      var $form = $(this).parents("form");
      var $button = $(this);
      $.ajax({type: "POST",
              url: "/rest" + $form.attr("action"),
              dataType: "json",
              success: function(data) {
                if (data) {
                  $button.text(data["next-label"]);
                  $form.attr("action", data["next-action"]);
                }
              },
             });
      return false;
  });

  $("#user-table").addClass("js-enabled");

  $("#user-table input.following").live("click", function(e) {
    e.preventDefault();
    var $checkbox = $(this)
    var $form = $checkbox.parents("form")
    $.ajax({type: "POST",
            url: "/rest" + $form.attr("action"),
            dataType: "json",
            success: function(data) {
              if (data) {
                $checkbox.attr("checked", data["following"]);
                $form.attr("action", data["next-action"]);
              }
             },
           });
    return false;
  });
});

var difficulty = new Array();
difficulty["Elementary"] = 0;
difficulty["Easy"]       = 1;
difficulty["Medium"]     = 2;
difficulty["Hard"]       = 3;
difficulty[""]           = 4;

jQuery.fn.dataTableExt.oSort['difficulty-asc'] = function(a, b) {
    return difficulty[a] - difficulty[b];
};

jQuery.fn.dataTableExt.oSort['difficulty-desc'] = function(a, b) {
    return difficulty[b] - difficulty[a];
};

function configureDataTables(){

    $('#problem-table').dataTable( {
        "iDisplayLength": 100,
        "aaSorting": [[5, "desc"], [1, "asc"], [4, "desc"]],
        "aoColumns": [
            {"sType": "string"},
            {"sType": "difficulty"},
            {"sType": "string"},
            {"sType": "string"},
            {"sType": "numeric"},
            {"sType": "string"}
        ]
    } );

    $('#unapproved-problems').dataTable( {
        "iDisplayLength": 25,
        "aaSorting": [[3, "desc"]],
        "aoColumns": [
            {"sType": "string"},
            {"sType": "string"},
            {"sType": "string"},
            {"sType": "string"}
        ]
    } );

    $('#user-table').dataTable( {
        "iDisplayLength":100,
        "aaSorting": [[0, "asc"]],
        "aoColumns": [
            {"sType": "numeric"},
            {"sType": "string"},
            {"sType": "numeric"},
            {"sType": "string"}
        ]
    } );
}

function setIconColor(element, color, timeOut) {
  timeOut = (typeof timeOut == "undefined") ? 0 : timeOut
  setTimeout (function() {
      element.src = "/images/"+color+"light.png";
  }, timeOut);
}

function changeToCodeView() {
  $('#code-div').show('fast');
  $('#golfgraph').hide('fast');
  $('#graph-link').html("View Chart");
}

function configureCodeBox(){
    //For no javascript version we have the code-box text area
    //If we have javascript on then we remove it and replace it with
    //the proper div
    var oldBox = $('#code-box');
    var disableJavaScriptCodeBox = $('#disable-javascript-codebox');
    if (disableJavaScriptCodeBox.length){
      return;
    }
    var hiddenCodeInput = "<input type=\"hidden\" value=\"blank\" name=\"code\" id=\"code\">";
    oldBox.replaceWith("

" + oldBox.val() + "

"+hiddenCodeInput);

    if ($("#run-button").length || $("#submission-button").length){
       var editor = ace.edit("editor");
       editor.setTheme("ace/theme/textmate");

       var ClojureMode = require("ace/mode/clojure").Mode;
       var session = editor.getSession();

       var clickHandler = function() {
         var text = session.getValue(),
           id = $('#id').attr("value"),
           images = $(".testcases").find("img"),
           cont = true,
           high = false,
           animationTime = 800,
           waitTimePerItem = 500,
           waitTime = waitTimePerItem,

           beforeSendCallback = function(data) {
             var anim = function() {
               if(cont) {
                 images.animate({
                   opacity: high ? 1.0 : 0.1,
                 }, animationTime);
                 high = !high;
                 setTimeout(anim,animationTime);
               }
             };

             $("#message-text").text("Executing unit tests...");
             $("#error-message-text").text("");
             images.each( function(index, element) {
               setIconColor(element, "blue");
             });
             setTimeout(changeToCodeView,0);
             setTimeout(anim,0);
           },
           successCallback = function(data) {
             var failingTest = data.failingTest,
                 getColorFor = function(index) {
                     return index === failingTest ? "red" : "green";
                 },
                 testWasExecuted = function(index) {
                     return index <= failingTest;
                 },
                 setColor = function(index,element) {
                     var color = getColorFor(index);
                     waitTime = waitTimePerItem * (index+1);
                     setIconColor(element, color, waitTime);
                 },
                 setMessages = function() {
                     $("#message-text").html(data.message);
                     $("#error-message-text").html(data.error);
                     $("#golfgraph").html(data.golfChart);
                     $("#golfscore").html(data.golfScore);
                     configureGolf();
                 },
                 stopAnimation = function() {
                     cont = false;
                     images.stop(true);
                     images.css({ opacity: 1.0, });
                 };

             setTimeout(stopAnimation, waitTime);
             images.filter( testWasExecuted ).
                 each(setColor);
             setTimeout (setMessages, waitTime);
           };

         $.ajax({type: "POST",
           url: "/rest/problem/"+id,
           dataType: "json",
           data: { id: id, code: text, },
           timout: 20000, // default clojail timeout is 10000
           beforeSend: beforeSendCallback,
           success: successCallback,
           error: function(data, str, error) {
             $("#message-text").text("An Error occured: "+error);
           },
         });
         return false;
       };

       $("#run-button").click(clickHandler);

       session.setMode(new ClojureMode());
       session.setUseSoftTabs(true);
       session.setTabSize(2);

       document.getElementById('editor').style.fontSize='13px';
       $("#run-button").click(function(){
         var text = editor.getSession().getValue();
         $('#code').val(text);
       });

       $("#submission-button").click(function(){
         var text = editor.getSession().getValue();
         $('#code').val(text);
       });
    }
}

function configureGolf(){
  $('#graph-link').show();
  $('#golfgraph').hide();
  $('#graph-link').click(function() {
    $('#code-div').toggle('fast', function() {
      // Animation complete.
    });
    $('#golfgraph').toggle('fast', function() {
      // Animation complete.
    });
    var text = $('#graph-link').html();
    if (text && text == 'View Chart'){
       $('#graph-link').html("View Code");
    } else {
       $('#graph-link').html("View Chart");
    }
  });

}
<commit_msg>Make sure the javascript sets img URLs that are in the static domain<commit_after>$(document).ready(function() {

  configureDataTables();
  configureCodeBox();
  configureGolf();

  $("form#run-code button#approve-button").live("click", function(e) {
    e.preventDefault();
    if(confirm("Are you sure you want to mark this problem as approved?"))
      $(this).parents("form").attr("action", "/problem/approve").submit();
  });

  $("form#run-code button#reject-button").live("click", function(e) {
    e.preventDefault();
    if(confirm("Are you sure you want to reject this problem? It will be permanently deleted.")) {
      $(this).parents("form").attr("action", "/problem/reject").submit();
    }
  });

  $("form#run-code button#edit-button").live("click", function(e) {
    e.preventDefault();
    $(this).parents("form").attr("action", "/problem/edit").submit();
  });

  $("button.user-follow-button").live("click", function(e) {
      e.preventDefault();
      var $form = $(this).parents("form");
      var $button = $(this);
      $.ajax({type: "POST",
              url: "/rest" + $form.attr("action"),
              dataType: "json",
              success: function(data) {
                if (data) {
                  $button.text(data["next-label"]);
                  $form.attr("action", data["next-action"]);
                }
              },
             });
      return false;
  });

  $("#user-table").addClass("js-enabled");

  $("#user-table input.following").live("click", function(e) {
    e.preventDefault();
    var $checkbox = $(this)
    var $form = $checkbox.parents("form")
    $.ajax({type: "POST",
            url: "/rest" + $form.attr("action"),
            dataType: "json",
            success: function(data) {
              if (data) {
                $checkbox.attr("checked", data["following"]);
                $form.attr("action", data["next-action"]);
              }
             },
           });
    return false;
  });
});

var difficulty = new Array();
difficulty["Elementary"] = 0;
difficulty["Easy"]       = 1;
difficulty["Medium"]     = 2;
difficulty["Hard"]       = 3;
difficulty[""]           = 4;

jQuery.fn.dataTableExt.oSort['difficulty-asc'] = function(a, b) {
    return difficulty[a] - difficulty[b];
};

jQuery.fn.dataTableExt.oSort['difficulty-desc'] = function(a, b) {
    return difficulty[b] - difficulty[a];
};

function configureDataTables(){

    $('#problem-table').dataTable( {
        "iDisplayLength": 100,
        "aaSorting": [[5, "desc"], [1, "asc"], [4, "desc"]],
        "aoColumns": [
            {"sType": "string"},
            {"sType": "difficulty"},
            {"sType": "string"},
            {"sType": "string"},
            {"sType": "numeric"},
            {"sType": "string"}
        ]
    } );

    $('#unapproved-problems').dataTable( {
        "iDisplayLength": 25,
        "aaSorting": [[3, "desc"]],
        "aoColumns": [
            {"sType": "string"},
            {"sType": "string"},
            {"sType": "string"},
            {"sType": "string"}
        ]
    } );

    $('#user-table').dataTable( {
        "iDisplayLength":100,
        "aaSorting": [[0, "asc"]],
        "aoColumns": [
            {"sType": "numeric"},
            {"sType": "string"},
            {"sType": "numeric"},
            {"sType": "string"}
        ]
    } );
}

function setIconColor(element, color, timeOut) {
  timeOut = (typeof timeOut == "undefined") ? 0 : timeOut
  setTimeout (function() {
      element.src = element.src.replace(new RegExp("(.*/images/).*(light.png)"), "$1" + color + "$2");
  }, timeOut);
}

function changeToCodeView() {
  $('#code-div').show('fast');
  $('#golfgraph').hide('fast');
  $('#graph-link').html("View Chart");
}

function configureCodeBox(){
    //For no javascript version we have the code-box text area
    //If we have javascript on then we remove it and replace it with
    //the proper div
    var oldBox = $('#code-box');
    var disableJavaScriptCodeBox = $('#disable-javascript-codebox');
    if (disableJavaScriptCodeBox.length){
      return;
    }
    var hiddenCodeInput = "<input type=\"hidden\" value=\"blank\" name=\"code\" id=\"code\">";
    oldBox.replaceWith("

" + oldBox.val() + "

"+hiddenCodeInput);

    if ($("#run-button").length || $("#submission-button").length){
       var editor = ace.edit("editor");
       editor.setTheme("ace/theme/textmate");

       var ClojureMode = require("ace/mode/clojure").Mode;
       var session = editor.getSession();

       var clickHandler = function() {
         var text = session.getValue(),
           id = $('#id').attr("value"),
           images = $(".testcases").find("img"),
           cont = true,
           high = false,
           animationTime = 800,
           waitTimePerItem = 500,
           waitTime = waitTimePerItem,

           beforeSendCallback = function(data) {
             var anim = function() {
               if(cont) {
                 images.animate({
                   opacity: high ? 1.0 : 0.1,
                 }, animationTime);
                 high = !high;
                 setTimeout(anim,animationTime);
               }
             };

             $("#message-text").text("Executing unit tests...");
             $("#error-message-text").text("");
             images.each( function(index, element) {
               setIconColor(element, "blue");
             });
             setTimeout(changeToCodeView,0);
             setTimeout(anim,0);
           },
           successCallback = function(data) {
             var failingTest = data.failingTest,
                 getColorFor = function(index) {
                     return index === failingTest ? "red" : "green";
                 },
                 testWasExecuted = function(index) {
                     return index <= failingTest;
                 },
                 setColor = function(index,element) {
                     var color = getColorFor(index);
                     waitTime = waitTimePerItem * (index+1);
                     setIconColor(element, color, waitTime);
                 },
                 setMessages = function() {
                     $("#message-text").html(data.message);
                     $("#error-message-text").html(data.error);
                     $("#golfgraph").html(data.golfChart);
                     $("#golfscore").html(data.golfScore);
                     configureGolf();
                 },
                 stopAnimation = function() {
                     cont = false;
                     images.stop(true);
                     images.css({ opacity: 1.0, });
                 };

             setTimeout(stopAnimation, waitTime);
             images.filter( testWasExecuted ).
                 each(setColor);
             setTimeout (setMessages, waitTime);
           };

         $.ajax({type: "POST",
           url: "/rest/problem/"+id,
           dataType: "json",
           data: { id: id, code: text, },
           timout: 20000, // default clojail timeout is 10000
           beforeSend: beforeSendCallback,
           success: successCallback,
           error: function(data, str, error) {
             $("#message-text").text("An Error occured: "+error);
           },
         });
         return false;
       };

       $("#run-button").click(clickHandler);

       session.setMode(new ClojureMode());
       session.setUseSoftTabs(true);
       session.setTabSize(2);

       document.getElementById('editor').style.fontSize='13px';
       $("#run-button").click(function(){
         var text = editor.getSession().getValue();
         $('#code').val(text);
       });

       $("#submission-button").click(function(){
         var text = editor.getSession().getValue();
         $('#code').val(text);
       });
    }
}

function configureGolf(){
  $('#graph-link').show();
  $('#golfgraph').hide();
  $('#graph-link').click(function() {
    $('#code-div').toggle('fast', function() {
      // Animation complete.
    });
    $('#golfgraph').toggle('fast', function() {
      // Animation complete.
    });
    var text = $('#graph-link').html();
    if (text && text == 'View Chart'){
       $('#graph-link').html("View Code");
    } else {
       $('#graph-link').html("View Chart");
    }
  });

}
<|endoftext|>


<commit_before>(function (d) {
  var passwordVisibility = false
  var passwordInput = d.getElementById('password')
  var passwordVisibilityButton = d.getElementById('password-visibility-button')
  passwordVisibilityButton.addEventListener('click', function (event) {
    event.preventDefault()
    passwordVisibility = !passwordVisibility
    passwordInput.type = passwordVisibility ? 'text' : 'password'
    passwordVisibilityButton.setAttribute('aria-pressed', passwordVisibility)
  })
})(window.document)
<commit_msg>fix: avoid autocomplete on clear password login field :bug:<commit_after>(function (d) {
  var passwordVisibility = false
  var passwordInput = d.getElementById('password')
  var passwordVisibilityButton = d.getElementById('password-visibility-button')
  passwordVisibilityButton.addEventListener('click', function (event) {
    event.preventDefault()
    passwordVisibility = !passwordVisibility
    passwordInput.type = passwordVisibility ? 'text' : 'password'
    passwordInput.setAttribute('autocomplete', passwordVisibility ? 'off' : 'current-password')
    passwordVisibilityButton.setAttribute('aria-pressed', passwordVisibility)
  })
})(window.document)
<|endoftext|>


<commit_before>import Vue from 'vue'

Vue.component('typeahead', {
  props: {
    data: {
      type: Object
    },
    limit: {
      type: Number,
      default: 0
    },
    onHit: {
      type: Function,
      required: true
    },
    prepareData: {
      type: Function
    },
    src: {
      type: String,
      required: true
    }
  },

  data () {
    return {
      items: [],
      query: '',
      current: 0,
      loading: false
    }
  },

  components: {
    typeaheadInput: {
      inherit: true,
      template: "<input type=\"text\" autocomplete=\"off\" v-model=\"query\" v-on=\"keydown: down|key 'down', keydown: up|key 'up', keydown: hit|key 'enter', keydown: reset|key 'esc', blur: reset, input: update\"/>"
    }
  },

  computed: {
    hasItems () {
      return this.items.length > 0
    },

    isEmpty () {
      return !this.query && !this.loading
    },

    isDirty () {
      return !!this.query && !this.loading
    }
  },

  methods: {
    update () {
      if (!this.query) {
        this.reset()
        return
      }

      this.loading = true

      this.$http.get(this.src, Object.assign({q:this.query}, this.data))
        .success(function (data) {
          if (this.query) {
            data = this.prepareData ? this.prepareData(data) : data
            this.items = !!this.limit ? data.slice(0, this.limit) : data
            this.current = 0
            this.loading = false
          }
        }.bind(this))
    },

    reset () {
      this.items = []
      this.query = ''
      this.loading = false
    },

    setActive (index) {
      this.current = index
    },

    isActive (index) {
      return this.current == index
    },

    hit () {
      this.onHit(this.items[this.current])
    },

    up () {
      if (this.current > 0) this.current--
    },

    down () {
      if (this.current < this.items.length-1) this.current++
    }
  }
})
<commit_msg>Export object instead of setting the component<commit_after>export default {
  props: {
    data: {
      type: Object
    },
    limit: {
      type: Number,
      default: 0
    },
    onHit: {
      type: Function,
      required: true
    },
    prepareData: {
      type: Function
    },
    src: {
      type: String,
      required: true
    }
  },

  data () {
    return {
      items: [],
      query: '',
      current: 0,
      loading: false
    }
  },

  components: {
    typeaheadInput: {
      inherit: true,
      template: "<input type=\"text\" autocomplete=\"off\" v-model=\"query\" v-on=\"keydown: down|key 'down', keydown: up|key 'up', keydown: hit|key 'enter', keydown: reset|key 'esc', blur: reset, input: update\"/>"
    }
  },

  computed: {
    hasItems () {
      return this.items.length > 0
    },

    isEmpty () {
      return !this.query && !this.loading
    },

    isDirty () {
      return !!this.query && !this.loading
    }
  },

  methods: {
    update () {
      if (!this.query) {
        this.reset()
        return
      }

      this.loading = true

      this.$http.get(this.src, Object.assign({q:this.query}, this.data))
        .success(function (data) {
          if (this.query) {
            data = this.prepareData ? this.prepareData(data) : data
            this.items = !!this.limit ? data.slice(0, this.limit) : data
            this.current = 0
            this.loading = false
          }
        }.bind(this))
    },

    reset () {
      this.items = []
      this.query = ''
      this.loading = false
    },

    setActive (index) {
      this.current = index
    },

    isActive (index) {
      return this.current == index
    },

    hit () {
      this.onHit(this.items[this.current])
    },

    up () {
      if (this.current > 0) this.current--
    },

    down () {
      if (this.current < this.items.length-1) this.current++
    }
  }
}
<|endoftext|>