<commit_before>(function(Factlink, $, _, easyXDM, undefined) {
  // var timeout;
  var popupTimeout;

  function getTextRange() {
    var d;

    if (document.getSelection) {
      d = document.getSelection();
    } else if (document.getSelection) {
      d = document.getSelection();
    } else if (document.selection) {
      d = document.selection.createRange().text;
    } else {
      d = '';
    }
    return d;
  }

  Factlink.createEvidenceFromSelection = function(opinion, callback){
    var selInfo = Factlink.getSelectionInfo();
    if (Factlink.prepare.getFactId()) {
        Factlink.remote.createEvidence(Factlink.prepare.getFactId(), Factlink.siteUrl(), opinion, selInfo.title);
    } else {
        Factlink.remote.createNewEvidence(selInfo.text, selInfo.passage, Factlink.siteUrl(), opinion, selInfo.title);
    }
  };

  Factlink.createFactFromSelection = function(opinion,callback,errorCallback){
    var selInfo = Factlink.getSelectionInfo();
    Factlink.create(selInfo.text, selInfo.passage, Factlink.siteUrl(), selInfo.title, opinion,callback,errorCallback);
  };

  Factlink.create = function(fact, passage, url, title, opinion, successFn, errorFn) {
    Factlink.post("/facts.json", {
      data: {
        fact: fact,
        passage: passage,
        opinion: opinion,
        title: title,
        url: url
      },
      success: function(data) {
        var factObjs = Factlink.modal.highlightNewFactlink.method(data.displaystring, data.id, data.score_dict_as_percentage);

        if ($.isFunction(successFn)) {
          successFn(data.id, factObjs);
        }
      },
      error: errorFn
    });
  };

  // We make this a global function so it can be used for direct adding of facts
  // (Right click with chrome-extension)
  Factlink.getSelectionInfo = function() {
    // Get the selection object
    var selection = getTextRange();

    //TODO: Add passage detection here
    return {
      text: selection.toString(),
      passage: "",
      title: document.title
    };
  };

  // This method will position a frame at the coordinates, either the left-top or
  // the right-top will be placed at x,y (preferably left-top)
  Factlink.positionFrameToCoord = function($frame, x, y, centered) {

    // First, set `absolute` so width can be determined
    $frame.css({
      position: 'absolute'
    });

    if ($(window).width() < (x + $frame.outerWidth(true) - $(window).scrollLeft())) {
      x -= $frame.outerWidth(true);
    }

    if ($(window).height() < (y + $frame.outerHeight(true) - $(window).scrollTop())) {
      y -= $frame.outerHeight(true);
    }

    // Position the middle of the frame at the mouse pointer\
    // in stead of the top left corner
    if (centered === true) {
      x = x - ($frame.outerWidth(true) / 2);
      y = y - ($frame.outerHeight(true) / 2);
    }

    // Position the frame
    $frame.css({
      top: y + 'px',
      left: x + 'px'
    });
  };

})(window.Factlink, Factlink.$, Factlink._, Factlink.easyXDM);

<commit_msg>yeah..<commit_after>(function(Factlink, $, _, easyXDM, undefined) {
  // var timeout;
  var popupTimeout;

  function getTextRange() {
    var d;

    if (document.getSelection) {
      d = document.getSelection();
    } else if (document.selection) {
      d = document.selection.createRange().text;
    } else {
      d = '';
    }
    return d;
  }

  Factlink.createEvidenceFromSelection = function(opinion, callback){
    var selInfo = Factlink.getSelectionInfo();
    if (Factlink.prepare.getFactId()) {
        Factlink.remote.createEvidence(Factlink.prepare.getFactId(), Factlink.siteUrl(), opinion, selInfo.title);
    } else {
        Factlink.remote.createNewEvidence(selInfo.text, selInfo.passage, Factlink.siteUrl(), opinion, selInfo.title);
    }
  };

  Factlink.createFactFromSelection = function(opinion,callback,errorCallback){
    var selInfo = Factlink.getSelectionInfo();
    Factlink.create(selInfo.text, selInfo.passage, Factlink.siteUrl(), selInfo.title, opinion,callback,errorCallback);
  };

  Factlink.create = function(fact, passage, url, title, opinion, successFn, errorFn) {
    Factlink.post("/facts.json", {
      data: {
        fact: fact,
        passage: passage,
        opinion: opinion,
        title: title,
        url: url
      },
      success: function(data) {
        var factObjs = Factlink.modal.highlightNewFactlink.method(data.displaystring, data.id, data.score_dict_as_percentage);

        if ($.isFunction(successFn)) {
          successFn(data.id, factObjs);
        }
      },
      error: errorFn
    });
  };

  // We make this a global function so it can be used for direct adding of facts
  // (Right click with chrome-extension)
  Factlink.getSelectionInfo = function() {
    // Get the selection object
    var selection = getTextRange();

    //TODO: Add passage detection here
    return {
      text: selection.toString(),
      passage: "",
      title: document.title
    };
  };

  // This method will position a frame at the coordinates, either the left-top or
  // the right-top will be placed at x,y (preferably left-top)
  Factlink.positionFrameToCoord = function($frame, x, y, centered) {

    // First, set `absolute` so width can be determined
    $frame.css({
      position: 'absolute'
    });

    if ($(window).width() < (x + $frame.outerWidth(true) - $(window).scrollLeft())) {
      x -= $frame.outerWidth(true);
    }

    if ($(window).height() < (y + $frame.outerHeight(true) - $(window).scrollTop())) {
      y -= $frame.outerHeight(true);
    }

    // Position the middle of the frame at the mouse pointer\
    // in stead of the top left corner
    if (centered === true) {
      x = x - ($frame.outerWidth(true) / 2);
      y = y - ($frame.outerHeight(true) / 2);
    }

    // Position the frame
    $frame.css({
      top: y + 'px',
      left: x + 'px'
    });
  };

})(window.Factlink, Factlink.$, Factlink._, Factlink.easyXDM);

<|endoftext|>


<commit_before>var express    = require('express');
var bodyParser = require('body-parser');
var gpio       = require('gpio');
var Slack      = require('slack-node');
var fs         = require('fs');
var jsonfile   = require('jsonfile');

var app = express();
slack = new Slack();
var port = 3000; // same port as ngrok
var highScoresFile = 'HighScores.json';
var defaultChannel = '#door-channel';

// number of milliseconds elapsed since 1 January 1970
var startTime = 0; // when the user is notified
var endTime   = 0; // when the user returns from opening the door

var messageLink = process.env.LINK;
var token       = process.env.TOKEN;

slack.setWebhook(messageLink);

app.use(bodyParser.urlencoded({extended: true}));

app.get('/', function(req, res) {
  res.status(200).send('Hello World!\n');
});

app.listen(port, function(){
  console.log('Listening on port ' + port);
  console.log(messageLink);
});

//===========================================================

app.post('/', function(req, res, next) {

  var requesterName = req.body.user_name;
  var trigger = req.body.trigger_word;
  var tok = req.body.token;
  // make sure there are no message loops, and only one user is being timed
  if(requesterName === 'slackbot' || requesterName === 'Door' || startTime != 0 || tok !== token){
    console.log('YOU SHALL NOT PASS!\n');
    return res.status(200).end();
  } else {
    if (trigger === 'highscore'){
      showHighScore();
      return res.status(200).end();
    }

    var channel = trigger;
    // Turn on red LED (TODO: sound buzzer)
    var chosenName = OnDoorCall(channel, requesterName);

    // checks if button was pressed in 10ms intervals
    firstButtonPressCheck = setInterval(function() {
      if (gpio27.value == 1) {
        clearInterval(firstButtonPressCheck);

        console.log('\nBUTTON -> press (1)');
        OnFirstButtonPress(requesterName,chosenName);

        // checks if button was released in 60ms intervals
        firstButtonReleaseCheck = setInterval(function() {
          if (gpio27.value == 0) {
            clearInterval(firstButtonReleaseCheck);

            console.log('BUTTON -> release (1)');

            // checks if button was pressed in 10ms intervals
            secondButtonPressCheck = setInterval(function() {
              if (gpio27.value == 1) {
                clearInterval(secondButtonPressCheck);

                console.log('\nBUTTON -> press (2)');
                var score = OnSecondButtonPress(requesterName,chosenName);

                // checks if button was released in 60ms intervals
                secondButtonReleaseCheck = setInterval(function() {
                  if (gpio27.value == 0) {
                    clearInterval(secondButtonReleaseCheck);

                    console.log('BUTTON -> release (2)');
                    updateScore(chosenName, score);
                    startTime = 0;
                    endTime = 0;
                    return res.status(200).end();
                  }
                },60);
              }
            },10);
          }
        },60);
      }
    },10);
  }
});

function showHighScore(){
  var highScore = getHighScore();
  var timeString = getTimeString(highScore.score);
  var message = '@' + highScore.name + ' tem o melhor tempo (' + timeString + ')!';
  sendMessage(defaultChannel, message);
}

function getHighScore(){
  var obj = JSON.parse(fs.readFileSync(highScoresFile, 'utf8'));
  var highScore = obj[0].score;
  var highScoreIndex = 0;
  for(var i = 0; i < obj.length; i++) {
    if (obj[i].score < highScore) {
      highScore = obj[i].score;
      highScoreIndex = i;
    }
  }
  return obj[highScoreIndex];
}

function updateScore(playerName, playerScore){
  var obj = JSON.parse(fs.readFileSync(highScoresFile, 'utf8'));
  for(var i = 0; i < obj.length; i++) {
      if (obj[i].name === playerName) {
        if (obj[i].score > playerScore) {
          obj[i].score = playerScore;
          jsonfile.writeFile(highScoresFile, obj, function(err){
            if (err)
              console.error(err);
          })
        }
        return;
      }
  }
  obj.push({name:playerName, score:playerScore});

  jsonfile.writeFile(highScoresFile, obj, function(err){
    if (err)
      console.error(err);
  })
}

function sendMessage(msgChannel, msgText) {
  slack.webhook({
    channel:msgChannel,
    username:'HODOR',
    text:msgText
  }, function(err, response) {
    if(err === null)
      console.log('[MESSAGE]\n' + msgChannel + ' -> ' + msgText);
  });
}

function pickRandom(department) {
  var members = JSON.parse(fs.readFileSync('members/' + department + '.json', 'utf8'));
  var chosenOne = members[Math.floor(Math.random() * members.length)];
  console.log('pickRandom -> ' + chosenOne);

  return chosenOne;
};

// flashing lights if led is on GPIO4
//green led
var gpio4 = gpio.export(4, {
  direction: 'out',
  interval: 200,
  ready: function(){
    intervalTimer = setInterval(function() {
      gpio4.set();
      setTimeout(function() {
        gpio4.reset();
      },500);
    },500);
  }
});

// red led
var gpio17 = gpio.export(17, {
  direction: 'out',
  interval: 200,
  ready: function() {
    gpio17.reset();
  }
});

// button
var gpio27 = gpio.export(27, {
  direction: 'in',
  interval: 200
});

function OnDoorCall(callerChannel, callerName){
  // Green ON
  gpio17.set(1);
  console.log('Gren LED -> ON');

  // get a random user
  var chosenName = pickRandom(callerChannel);
  var channel = '@' + chosenName;
  var privateMessage = '@' + callerName + ' pede que abras a porta, por favor!';
  var publicMessage = '@' + chosenName + ' é a tua vez de abrir a porta :heart:';
  sendMessage(channel, privateMessage);
  sendMessage(defaultChannel, publicMessage);

  return chosenName;
}

function OnFirstButtonPress(requester, buttonPresser) {

  // Green OFF
  gpio17.set(0);
  console.log('Gren LED -> OFF');

  // start the timer
  startTime = getTime();
  console.log('Start time -> ' + startTime);

  // at this time, the user should be on his way to get the door
  var msgChannel = '@' + requester;
  var msgText = '@' + buttonPresser + ' está a caminho!';
  sendMessage(msgChannel,msgText);
}

function OnSecondButtonPress(requesterName, chosenName) {

  // stop the timer
  endTime = getTime();
  console.log('End time -> ' + endTime);

  var deltaTime = getDeltaTime();
  var timeString = getTimeString(deltaTime);
  var publicMessage = '@' + chosenName + ' abriu a porta em ' + timeString + '!';
  sendMessage(defaultChannel, publicMessage);

  return deltaTime;
}

function getDeltaTime() {
  // get diff time inseconds
  var deltaTime = Math.round((endTime - startTime)/1000);
  console.log('Delta time -> ' + deltaTime);

  return deltaTime;
}

function getTime() {
  var date = Date.now();

  return (date);
}

var getTimeString = function(deltaT) {
  var hours = 0;
  var minutes = 0;
  var seconds = 0;
  var string = '';
  while (deltaT >= (3600)) {
    hours++;
    deltaT -= 3600;
  }

  while (deltaT >= 60) {
    minutes++;
    deltaT -= 60;
  }

  while (deltaT >= 1) {
    seconds++;
    deltaT-= 1;
  }

  if (hours > 0) {
    string = hours + ' hora';
    if (hours > 1)
      string = string + 's';

    string = string + ', ';
  }

  if (minutes > 0) {
    string = string + minutes + ' minuto';
    if (minutes > 1)
      string = string + 's';

    string = string + ' e ';
  }

  string = string + seconds + ' segundo';
    if (seconds > 1)
      string = string + 's';

  return string;
}
<commit_msg>Add check personal high score and lowercased trigger word<commit_after>var express    = require('express');
var bodyParser = require('body-parser');
var gpio       = require('gpio');
var Slack      = require('slack-node');
var fs         = require('fs');
var jsonfile   = require('jsonfile');

var app = express();
slack = new Slack();
var port = 3000; // same port as ngrok
var highScoresFile = 'HighScores.json';
var defaultChannel = '#door-channel';

// number of milliseconds elapsed since 1 January 1970
var startTime = 0; // when the user is notified
var endTime   = 0; // when the user returns from opening the door

var messageLink = process.env.LINK;
var token       = process.env.TOKEN;

slack.setWebhook(messageLink);

app.use(bodyParser.urlencoded({extended: true}));

app.get('/', function(req, res) {
  res.status(200).send('Hello World!\n');
});

app.listen(port, function(){
  console.log('Listening on port ' + port);
  console.log(messageLink);
});

//===========================================================

app.post('/', function(req, res, next) {

  var requesterName = req.body.user_name;
  var trigger = req.body.trigger_word;
  trigger = trigger.toLowerCase();
  var tok = req.body.token;
  // make sure there are no message loops, and only one user is being timed
  if(requesterName === 'slackbot' || requesterName === 'Door' || startTime != 0 || tok !== token){
    console.log('YOU SHALL NOT PASS!\n');
    return res.status(200).end();
  } else {
    if (trigger === 'highscore'){
      showHighScore();
      return res.status(200).end();
    }

    var channel = trigger;
    // Turn on red LED (TODO: sound buzzer)
    var chosenName = OnDoorCall(channel, requesterName);

    // checks if button was pressed in 10ms intervals
    firstButtonPressCheck = setInterval(function() {
      if (gpio27.value == 1) {
        clearInterval(firstButtonPressCheck);

        console.log('\nBUTTON -> press (1)');
        OnFirstButtonPress(requesterName,chosenName);

        // checks if button was released in 60ms intervals
        firstButtonReleaseCheck = setInterval(function() {
          if (gpio27.value == 0) {
            clearInterval(firstButtonReleaseCheck);

            console.log('BUTTON -> release (1)');

            // checks if button was pressed in 10ms intervals
            secondButtonPressCheck = setInterval(function() {
              if (gpio27.value == 1) {
                clearInterval(secondButtonPressCheck);

                console.log('\nBUTTON -> press (2)');
                var score = OnSecondButtonPress(requesterName,chosenName);

                // checks if button was released in 60ms intervals
                secondButtonReleaseCheck = setInterval(function() {
                  if (gpio27.value == 0) {
                    clearInterval(secondButtonReleaseCheck);

                    console.log('BUTTON -> release (2)');
                    updateScore(chosenName, score);
                    startTime = 0;
                    endTime = 0;
                    return res.status(200).end();
                  }
                },60);
              }
            },10);
          }
        },60);
      }
    },10);
  }
});

function showPersonalScore(name){
  var message = '@' + name + ', não tens nenhum tempo guardado!';
  var obj = JSON.parse(fs.readFileSync(highScoresFile, 'utf8'));
  for (var i = 0; i < obj.length; i++;) {
    if (obj[i].name === name) {
      var timeString = getTimeString(obj[i].score);
      message = '@' + name + ', o teu melhor tempo é ' + timeString + '!';
      break;
    }
  }

  sendMessage(defaultChannel, message);
}

function showHighScore(){
  var highScore = getHighScore();
  var timeString = getTimeString(highScore.score);
  var message = '@' + highScore.name + ' tem o melhor tempo (' + timeString + ')!';
  sendMessage(defaultChannel, message);
}

function getHighScore(){
  var obj = JSON.parse(fs.readFileSync(highScoresFile, 'utf8'));
  var highScore = obj[0].score;
  var highScoreIndex = 0;
  for (var i = 0; i < obj.length; i++) {
    if (obj[i].score < highScore) {
      highScore = obj[i].score;
      highScoreIndex = i;
    }
  }
  return obj[highScoreIndex];
}

function updateScore(playerName, playerScore){
  var obj = JSON.parse(fs.readFileSync(highScoresFile, 'utf8'));
  for (var i = 0; i < obj.length; i++) {
      if (obj[i].name === playerName) {
        if (obj[i].score > playerScore) {
          obj[i].score = playerScore;
          jsonfile.writeFile(highScoresFile, obj, function(err){
            if (err)
              console.error(err);
          })
        }
        return;
      }
  }
  obj.push({name:playerName, score:playerScore});

  jsonfile.writeFile(highScoresFile, obj, function(err){
    if (err)
      console.error(err);
  })
}

function sendMessage(msgChannel, msgText) {
  slack.webhook({
    channel:msgChannel,
    username:'HODOR',
    text:msgText
  }, function(err, response) {
    if (err === null)
      console.log('[MESSAGE]\n' + msgChannel + ' -> ' + msgText);
  });
}

function pickRandom(department) {
  var members = JSON.parse(fs.readFileSync('members/' + department + '.json', 'utf8'));
  var chosenOne = members[Math.floor(Math.random() * members.length)];
  console.log('pickRandom -> ' + chosenOne);

  return chosenOne;
};

// flashing lights if led is on GPIO4
//green led
var gpio4 = gpio.export(4, {
  direction: 'out',
  interval: 200,
  ready: function(){
    intervalTimer = setInterval(function() {
      gpio4.set();
      setTimeout(function() {
        gpio4.reset();
      },500);
    },500);
  }
});

// red led
var gpio17 = gpio.export(17, {
  direction: 'out',
  interval: 200,
  ready: function() {
    gpio17.reset();
  }
});

// button
var gpio27 = gpio.export(27, {
  direction: 'in',
  interval: 200
});

function OnDoorCall(callerChannel, callerName){
  // Green ON
  gpio17.set(1);
  console.log('Gren LED -> ON');

  // get a random user
  var chosenName = pickRandom(callerChannel);
  var channel = '@' + chosenName;
  var privateMessage = '@' + callerName + ' pede que abras a porta, por favor!';
  var publicMessage = '@' + chosenName + ' é a tua vez de abrir a porta :heart:';
  sendMessage(channel, privateMessage);
  sendMessage(defaultChannel, publicMessage);

  return chosenName;
}

function OnFirstButtonPress(requester, buttonPresser) {

  // Green OFF
  gpio17.set(0);
  console.log('Gren LED -> OFF');

  // start the timer
  startTime = getTime();
  console.log('Start time -> ' + startTime);

  // at this time, the user should be on his way to get the door
  var msgChannel = '@' + requester;
  var msgText = '@' + buttonPresser + ' está a caminho!';
  sendMessage(msgChannel,msgText);
}

function OnSecondButtonPress(requesterName, chosenName) {

  // stop the timer
  endTime = getTime();
  console.log('End time -> ' + endTime);

  var deltaTime = getDeltaTime();
  var timeString = getTimeString(deltaTime);
  var publicMessage = '@' + chosenName + ' abriu a porta em ' + timeString + '!';
  sendMessage(defaultChannel, publicMessage);

  return deltaTime;
}

function getDeltaTime() {
  // get diff time inseconds
  var deltaTime = Math.round((endTime - startTime)/1000);
  console.log('Delta time -> ' + deltaTime);

  return deltaTime;
}

function getTime() {
  var date = Date.now();

  return (date);
}

var getTimeString = function(deltaT) {
  var hours = 0;
  var minutes = 0;
  var seconds = 0;
  var string = '';
  while (deltaT >= (3600)) {
    hours++;
    deltaT -= 3600;
  }

  while (deltaT >= 60) {
    minutes++;
    deltaT -= 60;
  }

  while (deltaT >= 1) {
    seconds++;
    deltaT-= 1;
  }

  if (hours > 0) {
    string = hours + ' hora';
    if (hours > 1)
      string = string + 's';

    string = string + ', ';
  }

  if (minutes > 0) {
    string = string + minutes + ' minuto';
    if (minutes > 1)
      string = string + 's';

    string = string + ' e ';
  }

  string = string + seconds + ' segundo';
    if (seconds > 1)
      string = string + 's';

  return string;
}
<|endoftext|>


<commit_before>var areasToDefine = 10;
var dotMax = 0;
var dotMin = 0;
var dotAreas = [];

var showActualValue = function() {
  var matrixDotElem = $(this);
  var val = matrixDotElem.attr('value') || '0';
  $('.display-count .count-value').text(val);
};

var hideActualValue = function() {
  $('.display-count .count-value').text('-');
};

var addHoverListeners = function() {
  $('.matrixdot').hover(showActualValue);
  $('.quadrant').mouseout(hideActualValue);
};

var addMatrixClasses = function() {
  $('.matrixdot').each(function() {
    var arrIsIterated = false;
    var className;
    var dotElem = $(this);
    var dotElemValue = parseInt(dotElem.attr('value'), 10);
    var elemIsBelow = false;
    var i = 0;

    while(i < dotAreas.length) {
      elemIsBelow = dotElemValue < dotAreas[i];
      arrIsIterated = i + 1 >= dotAreas.length;

      if (elemIsBelow || arrIsIterated) {
        className = i > 0 ?
          'op-' + i + '0' :
          'op-0';

        dotElem.addClass(className);
        break;
      }
      i++;
    }
  });
};

var setDotsValues = function() {
  var area = 0;
  var i = 0;
  var dotsValues = [];
  var dotsValuesAvg = 0;
  var dotsValuesSum = 0;

  $('.matrixdot').each(function() {
    var val = parseInt($(this).attr('value'), 10)
    dotsValues.push(val);
    dotsValuesSum += val;
  });

  dotsValuesAvg = Math.floor(dotsValuesSum / dotsValues.length * 10) / 10;
  $('.display-count .avg-value').text(dotsValuesAvg);

  dotMax = Math.max.apply(Math, dotsValues);

  while (i++ < areasToDefine) {
    area = Math.floor(dotMax / areasToDefine * i);
    dotAreas.push(area);
  }
};

var displayMaxEntry = function() {
  $('.display-count .max-value').text(dotMax);
};

$(document).ready(setDotsValues);
$(document).ready(addHoverListeners);
$(document).ready(addMatrixClasses);
$(document).ready(displayMaxEntry);
<commit_msg>Use mouseleave instead of mouseout<commit_after>var areasToDefine = 10;
var dotMax = 0;
var dotMin = 0;
var dotAreas = [];

var showActualValue = function() {
  var matrixDotElem = $(this);
  var val = matrixDotElem.attr('value') || '0';
  $('.display-count .count-value').text(val);
};

var hideActualValue = function() {
  $('.display-count .count-value').text('-');
};

var addHoverListeners = function() {
  $('.matrixdot').hover(showActualValue);
  $('.quadrant').mouseleave(hideActualValue);
};

var addMatrixClasses = function() {
  $('.matrixdot').each(function() {
    var arrIsIterated = false;
    var className;
    var dotElem = $(this);
    var dotElemValue = parseInt(dotElem.attr('value'), 10);
    var elemIsBelow = false;
    var i = 0;

    while(i < dotAreas.length) {
      elemIsBelow = dotElemValue < dotAreas[i];
      arrIsIterated = i + 1 >= dotAreas.length;

      if (elemIsBelow || arrIsIterated) {
        className = i > 0 ?
          'op-' + i + '0' :
          'op-0';

        dotElem.addClass(className);
        break;
      }
      i++;
    }
  });
};

var setDotsValues = function() {
  var area = 0;
  var i = 0;
  var dotsValues = [];
  var dotsValuesAvg = 0;
  var dotsValuesSum = 0;

  $('.matrixdot').each(function() {
    var val = parseInt($(this).attr('value'), 10)
    dotsValues.push(val);
    dotsValuesSum += val;
  });

  dotsValuesAvg = Math.floor(dotsValuesSum / dotsValues.length * 10) / 10;
  $('.display-count .avg-value').text(dotsValuesAvg);

  dotMax = Math.max.apply(Math, dotsValues);

  while (i++ < areasToDefine) {
    area = Math.floor(dotMax / areasToDefine * i);
    dotAreas.push(area);
  }
};

var displayMaxEntry = function() {
  $('.display-count .max-value').text(dotMax);
};

$(document).ready(setDotsValues);
$(document).ready(addHoverListeners);
$(document).ready(addMatrixClasses);
$(document).ready(displayMaxEntry);
<|endoftext|>


<commit_before>/*
	{
		"user": {
			"name": "BOT"
		},
		"message": "Hello World!",
		"eventType":"new message"
	}
 */

var config,
	server,
	secureServer,
	io,
	logger,
	route,
	db,
	active,
	limit = 20;

var redis = require('socket.io-redis'),
	MongoClient = require('mongodb').MongoClient,
	url = require('url'),
	Result = require('./Objects/Result.js');

var usernames = {},
	numUsers = 0;

var configure = function(_config, _server, _secureServer, _logger, _route) {
	config = _config;
	server = _server;
	secureServer = _secureServer;
	logger = _logger;
	route = _route;
	io = require('socket.io').listen(server);
	secureServer && (io.listen(secureServer));

	db = dbconn(config.get('mongo'));
};

var dbconn = function(option) {
	var rs,
		dbURL = url.parse(option.uri);;

	!option && (option = {});
	option.protocol = 'mongodb:';
	option.pathname = '/pushServer';
	option.slashes = true;
	!option.host && (option.host = dbURL.host);
	!option.port && (option.port = dbURL.port);

	MongoClient.connect(url.format(option), function(err, _db) {
		if(err) {
			console.log(err);
			rs = false;
		}

		rs = _db;
	});

	while(rs === undefined) {
		require('deasync').runLoopOnce();
	}
	return rs;
};

var start = function() {
	var self = this;
	io.on('connection', function (socket) {
		var addedUser = false;
		socket.channel = [];
		// when the client emits 'new message', this listens and executes
		socket.on('new message', function (data) {
			var msg = {
				user: {
					uid: socket.id,
					ip: socket.handshake.address.address,
					name: socket.username
				},
				channel: data.channel,
				message: data,
				timestamp: new Date()
			};

			// we tell the client to execute 'new message'
			socket.broadcast.emit('new message', msg);

			log(msg);
			//self.send();
		});

		// get channel history
		socket.on('load message', function(data) {
			var channel = data.channel || 'default';
			var timestamp = new Date(data.timestamp);
			var cond = {};

			if(data.channel) { cond.channel = data.channel; }
			if(data.timestamp) { cond.timestamp = { $lt: new Date(data.timestamp) }; }

			db.collection('messages').find(cond).sort({'timestamp': -1}).limit(limit).toArray(function(_err, _data) {
				socket.emit('load message', {
					channel: channel,
					messages: _data
				});
			});
		});

		// get channel list
		socket.on('get channel', function(data) {

		});

		// when the client emits 'add user', this listens and executes
		socket.on('add user', function (username) {
			// we store the username in the socket session for this client
			socket.username = username;
			// add the client's username to the global list
			usernames[username] = username;
			++numUsers;
			addedUser = true;
			socket.emit('login', {
				numUsers: numUsers,
				timestamp: new Date()
			});
			// echo globally (all clients) that a person has connected
			socket.broadcast.emit('user joined', {
					user: {
					name: socket.username
				},
				numUsers: numUsers,
				timestamp: new Date()
			});
		});

		// when the client emits 'typing', we broadcast it to others
		socket.on('typing', function () {
			socket.broadcast.emit('typing', {
				user: {
					name: socket.username
				},
				timestamp: new Date()
			});
		});

		// when the client emits 'stop typing', we broadcast it to others
		socket.on('stop typing', function () {
			socket.broadcast.emit('stop typing', {
				user: {
					name: socket.username
				},
				timestamp: new Date()
			});
		});

		// when the user disconnects.. perform this
		socket.on('disconnect', function () {
			// remove the username from global usernames list
			if (addedUser) {
				delete usernames[socket.username];
				--numUsers;

				// echo globally that this client has left
				socket.broadcast.emit('user left', {
					user: {
						name: socket.username
					},
					numUsers: numUsers,
					timestamp: new Date()
				});
			}
		});

		// when the user join some channel
		socket.on('join', function (room) {
			socket.join(room);
			socket.channel.indexOf(room) == -1 && socket.channel.push(room);
		});

		// where the user leave some channel
		socket.on('leave', function (room) {
			socket.leave(room);
			socket.channel.splice(socket.channel.indexOf(room), 1);
		});
	});

	//push service
	route('all', '/push/', module.exports.pushMessage);
	route('all', '/push/:channel', module.exports.pushMessage);

	console.log("Socket start");
	active = true;
};
var log = function(message) {
	!message.channel && (message.channel = 'default');
	db.collection('messages').insert(message, function(_err, _data) { console.log(_err); console.log(_data); });
	return true;
};
var send = function(data, channel) {
	if(!data) { return false;}
	if(!active) { return true;}

	var sender = channel? io.to(channel): io,
		eventType = data.eventType;

	data.timestamp = new Date();
	data.channel = channel;

	sender.emit(eventType, data);
	log(data);

	return true;
};
var pushMessage = function(req, res, next) {
	res.result = new Result();

	var channel = req.params.channel,
		dist = channel || 'default',
		data = req.body;

	send(data, channel);
	res.result.response(next, 1, 'send message to channel: ' + dist);
};

module.exports = {
    configure: configure,
    start: start,
    send: send,
    pushMessage: pushMessage
}<commit_msg>Debug<commit_after>/*
	{
		"user": {
			"name": "BOT"
		},
		"message": "Hello World!",
		"eventType":"new message"
	}
 */

var config,
	server,
	secureServer,
	io,
	logger,
	route,
	db,
	active,
	limit = 20;

var redis = require('socket.io-redis'),
	MongoClient = require('mongodb').MongoClient,
	url = require('url'),
	Result = require('./Objects/Result.js');

var usernames = {},
	numUsers = 0;

var configure = function(_config, _server, _secureServer, _logger, _route) {
	config = _config;
	server = _server;
	secureServer = _secureServer;
	logger = _logger;
	route = _route;
	io = require('socket.io').listen(server);
	io.adapter(redis(config.get('redis')));
	secureServer && (io.listen(secureServer));

	db = dbconn(config.get('mongo'));
};

var dbconn = function(option) {
	var rs,
		dbURL = url.parse(option.uri);;

	!option && (option = {});
	option.protocol = 'mongodb:';
	option.pathname = '/pushServer';
	option.slashes = true;
	!option.host && (option.host = dbURL.host);
	!option.port && (option.port = dbURL.port);

	MongoClient.connect(url.format(option), function(err, _db) {
		if(err) {
			console.log(err);
			rs = false;
		}

		rs = _db;
	});

	while(rs === undefined) {
		require('deasync').runLoopOnce();
	}
	return rs;
};

var start = function() {
	var self = this;
	io.on('connection', function (socket) {
		var addedUser = false;
		socket.channel = [];
		// when the client emits 'new message', this listens and executes
		socket.on('new message', function (data) {
			var msg = {
				user: {
					uid: socket.id,
					ip: socket.handshake.address.address,
					name: socket.username
				},
				channel: data.channel,
				message: data,
				timestamp: new Date()
			};

			// we tell the client to execute 'new message'
			socket.broadcast.emit('new message', msg);

			log(msg);
			//self.send();
		});

		// get channel history
		socket.on('load message', function(data) {
			var channel = data.channel || 'default';
			var timestamp = new Date(data.timestamp);
			var cond = {};

			if(data.limit) { limit = data.limit; }
			if(data.channel) { cond.channel = data.channel; }
			if(data.timestamp) { cond.timestamp = { $lt: new Date(data.timestamp) }; }

			db.collection('messages').find(cond).sort({'timestamp': -1}).limit(limit).toArray(function(_err, _data) {
				socket.emit('load message', {
					channel: channel,
					messages: _data
				});
			});
		});

		// get channel list
		socket.on('get channel', function(data) {

		});

		// when the client emits 'add user', this listens and executes
		socket.on('add user', function (username) {
			// we store the username in the socket session for this client
			socket.username = username;
			// add the client's username to the global list
			usernames[username] = username;
			++numUsers;
			addedUser = true;
			socket.emit('login', {
				numUsers: numUsers,
				timestamp: new Date()
			});
			// echo globally (all clients) that a person has connected
			socket.broadcast.emit('user joined', {
					user: {
					name: socket.username
				},
				numUsers: numUsers,
				timestamp: new Date()
			});
		});

		// when the client emits 'typing', we broadcast it to others
		socket.on('typing', function () {
			socket.broadcast.emit('typing', {
				user: {
					name: socket.username
				},
				timestamp: new Date()
			});
		});

		// when the client emits 'stop typing', we broadcast it to others
		socket.on('stop typing', function () {
			socket.broadcast.emit('stop typing', {
				user: {
					name: socket.username
				},
				timestamp: new Date()
			});
		});

		// when the user disconnects.. perform this
		socket.on('disconnect', function () {
			// remove the username from global usernames list
			if (addedUser) {
				delete usernames[socket.username];
				--numUsers;

				// echo globally that this client has left
				socket.broadcast.emit('user left', {
					user: {
						name: socket.username
					},
					numUsers: numUsers,
					timestamp: new Date()
				});
			}
		});

		// when the user join some channel
		socket.on('join', function (room) {
			socket.join(room);
			socket.channel.indexOf(room) == -1 && socket.channel.push(room);
		});

		// where the user leave some channel
		socket.on('leave', function (room) {
			socket.leave(room);
			socket.channel.splice(socket.channel.indexOf(room), 1);
		});
	});

	//push service
	route('all', '/push/', module.exports.pushMessage);
	route('all', '/push/:channel', module.exports.pushMessage);

	console.log("Socket start");
	active = true;
};
var log = function(message) {
	!message.channel && (message.channel = 'default');
	db.collection('messages').insert(message, function(_err, _data) { console.log(_err); console.log(_data); });
	return true;
};
var send = function(data, channel) {
	if(!data) { return false;}
	if(!active) { return true;}

	var sender = channel? io.to(channel): io,
		eventType = data.eventType;

	data.timestamp = new Date();
	data.channel = channel;

	sender.emit(eventType, data);
	log(data);

	return true;
};
var pushMessage = function(req, res, next) {
	res.result = new Result();

	var channel = req.params.channel,
		dist = channel || 'default',
		data = req.body;

	send(data, channel);
	res.result.response(next, 1, 'send message to channel: ' + dist);
};

module.exports = {
    configure: configure,
    start: start,
    send: send,
    pushMessage: pushMessage
}<|endoftext|>


<commit_before>(function ($) {

    if (!$) { throw new Error('OpenSeadragon Annotations requires OpenSeadragon'); }

    $.Viewer.prototype.initializeAnnotations = function (options) {
        var options = $.extend({ viewer: this }, options);
        this.addHandler('open', annotations.onOpen.bind(annotations));
        this.annotations = this.annotations || annotations.initialize(options);
        return this;
    };

    var annotations = {

        initialize: function (options) {
            $.extend(this, {
                state: move.initialize(),
                controls: controls.initialize({
                    imagePath: options.imagePath || ''
                })
            }, options);
            this.controls.addHandler('add', function (button) {
                this.viewer.addControl(button.element, {
                    anchor: $.ControlAnchor.BOTTOM_LEFT
                });
            }.bind(this));
            return this;
        },

        onOpen: function () {
            this.overlay = overlay.initialize({
                viewer: this.viewer
            });

            this.viewer.addHandler('animation', function () {
                var width = this.overlay.el.clientWidth;
                var height = this.overlay.el.clientHeight;
                var viewPort = '0 0 ' + width + ' ' + height;
                var svg = this.overlay.el.querySelector('svg');
                svg.setAttribute('viewPort', viewPort);
            }.bind(this));

            this.controls.add('move', true).addHandler('click', function () {
                this.viewer.setMouseNavEnabled(true);
                this.state = move.initialize();
            }.bind(this));

            this.controls.add('draw').addHandler('click', function () {
                this.viewer.setMouseNavEnabled(false);
                this.state = draw.initialize();
            }.bind(this));

            this.overlay.el.addEventListener('mousedown', function (e) {
                this.state.handleMouseDown(e, this.overlay);
            }.bind(this), false);

            this.overlay.el.addEventListener('mouseup', function (e) {
                this.state.handleMouseUp(e, this.overlay);
            }.bind(this), false);

            return this;
        }

    };

    var state = {

        initialize: function (options) {
            $.extend(this, options);
            return this;
        },

        handleMouseDown: function () {
            return this;
        },

        handleMouseUp: function () {
            return this;
        }

    }

    var move = Object.create(state);

    var draw = $.extend(Object.create(state), {

        initialize: function (options) {
            $.extend(this, options);
            this._mouseTracker = function (e) {
                this.x = e.offsetX;
                this.y = e.offsetY;
            }.bind(this);
            return this;
        },

        handleMouseDown: function (e, overlay) {
            if (!this._interval) {
                this.x = e.offsetX;
                this.y = e.offsetY;
                var svg = overlay.el.querySelector('svg');
                var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
                path.setAttribute('fill', 'none');
                path.setAttribute('stroke', 'red');
                path.setAttribute('stroke-width', '0.5');
                path.setAttribute('stroke-linejoin', 'round');
                path.setAttribute('stroke-linecap', 'round');
                path.setAttribute('d', 'M' + this.x / overlay.el.clientWidth * 100 +
                    ' ' + this.y / overlay.el.clientHeight * 100);
                svg.appendChild(path);

                overlay.el.addEventListener('mousemove', this._mouseTracker, false);

                this._interval = window.setInterval(function () {
                    path.setAttribute('d', path.getAttribute('d') +
                        ' L' + this.x / overlay.el.clientWidth * 100 +
                        ' ' + this.y / overlay.el.clientHeight * 100);
                }.bind(this), 25);
            }
            e.stopPropagation();
            return this;
        },

        handleMouseUp: function (e, overlay) {
            overlay.el.removeEventListener('mousemove', this._mouseTracker);
            this._interval = clearInterval(this._interval);
            return this;
        }

    });

    var controls = $.extend(new $.EventSource(), {

        initialize: function (options) {
            $.extend(this, options);
            this.list = {};
            this.addHandler('click', this.onClick.bind(this));
            return this;
        },

        onClick: function (name) {
            for (var button in this.list) {
                if (this.list.hasOwnProperty(button)) {
                    if (button === name) {
                        this.list[button].imgDown.style.visibility = 'visible';
                    } else {
                        this.list[button].imgDown.style.visibility = 'hidden';
                    }
                }
            }
            return this;
        },

        add: function (name, active) {
            this.list[name] = new $.Button({
                tooltip: name[0].toUpperCase() + name.substr(1),
                srcRest: this.imagePath + name + '_rest.png',
                srcGroup: this.imagePath + name + '_grouphover.png',
                srcHover: this.imagePath + name + '_hover.png',
                srcDown: this.imagePath + name + '_pressed.png',
                onClick: this.raiseEvent.bind(this, 'click', name)
            });
            if (active) {
                this.list[name].imgDown.style.visibility = 'visible';
            }
            this.raiseEvent('add', this.list[name]);
            return this.list[name];
        },

        get: function (name) {
            return this.list[name];
        }

    });

    var overlay = {

        initialize: function (options) {
            $.extend(this, options);
            this.el = document.createElement('div');
            this.el.className = 'overlay';
            var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            svg.setAttribute('version', '1.1');
            svg.setAttribute('width', '100%');
            svg.setAttribute('height', '100%');
            svg.setAttribute('preserveAspectRatio', 'none');
            svg.setAttribute('viewBox', '0 0 100 100')
            svg.style.cursor = 'default';
            this.el.appendChild(svg);
            var width = this.viewer.viewport.homeBounds.width;
            var height = this.viewer.viewport.homeBounds.height;
            this.viewer.addOverlay(this.el, new $.Rect(0, 0, width, height));
            return this;
        }

    };

})(OpenSeadragon);
<commit_msg>Use strict<commit_after>'use strict';

(function ($) {

    if (!$) { throw new Error('OpenSeadragon Annotations requires OpenSeadragon'); }

    $.Viewer.prototype.initializeAnnotations = function (options) {
        var options = $.extend({ viewer: this }, options);
        this.addHandler('open', annotations.onOpen.bind(annotations));
        this.annotations = this.annotations || annotations.initialize(options);
        return this;
    };

    var annotations = {

        initialize: function (options) {
            $.extend(this, {
                state: move.initialize(),
                controls: controls.initialize({
                    imagePath: options.imagePath || ''
                })
            }, options);
            this.controls.addHandler('add', function (button) {
                this.viewer.addControl(button.element, {
                    anchor: $.ControlAnchor.BOTTOM_LEFT
                });
            }.bind(this));
            return this;
        },

        onOpen: function () {
            this.overlay = overlay.initialize({
                viewer: this.viewer
            });

            this.viewer.addHandler('animation', function () {
                var width = this.overlay.el.clientWidth;
                var height = this.overlay.el.clientHeight;
                var viewPort = '0 0 ' + width + ' ' + height;
                var svg = this.overlay.el.querySelector('svg');
                svg.setAttribute('viewPort', viewPort);
            }.bind(this));

            this.controls.add('move', true).addHandler('click', function () {
                this.viewer.setMouseNavEnabled(true);
                this.state = move.initialize();
            }.bind(this));

            this.controls.add('draw').addHandler('click', function () {
                this.viewer.setMouseNavEnabled(false);
                this.state = draw.initialize();
            }.bind(this));

            this.overlay.el.addEventListener('mousedown', function (e) {
                this.state.handleMouseDown(e, this.overlay);
            }.bind(this), false);

            this.overlay.el.addEventListener('mouseup', function (e) {
                this.state.handleMouseUp(e, this.overlay);
            }.bind(this), false);

            return this;
        }

    };

    var state = {

        initialize: function (options) {
            $.extend(this, options);
            return this;
        },

        handleMouseDown: function () {
            return this;
        },

        handleMouseUp: function () {
            return this;
        }

    }

    var move = Object.create(state);

    var draw = $.extend(Object.create(state), {

        initialize: function (options) {
            $.extend(this, options);
            this._mouseTracker = function (e) {
                this.x = e.offsetX;
                this.y = e.offsetY;
            }.bind(this);
            return this;
        },

        handleMouseDown: function (e, overlay) {
            if (!this._interval) {
                this.x = e.offsetX;
                this.y = e.offsetY;
                var svg = overlay.el.querySelector('svg');
                var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
                path.setAttribute('fill', 'none');
                path.setAttribute('stroke', 'red');
                path.setAttribute('stroke-width', '0.5');
                path.setAttribute('stroke-linejoin', 'round');
                path.setAttribute('stroke-linecap', 'round');
                path.setAttribute('d', 'M' + this.x / overlay.el.clientWidth * 100 +
                    ' ' + this.y / overlay.el.clientHeight * 100);
                svg.appendChild(path);

                overlay.el.addEventListener('mousemove', this._mouseTracker, false);

                this._interval = window.setInterval(function () {
                    path.setAttribute('d', path.getAttribute('d') +
                        ' L' + this.x / overlay.el.clientWidth * 100 +
                        ' ' + this.y / overlay.el.clientHeight * 100);
                }.bind(this), 25);
            }
            e.stopPropagation();
            return this;
        },

        handleMouseUp: function (e, overlay) {
            overlay.el.removeEventListener('mousemove', this._mouseTracker);
            this._interval = clearInterval(this._interval);
            return this;
        }

    });

    var controls = $.extend(new $.EventSource(), {

        initialize: function (options) {
            $.extend(this, options);
            this.list = {};
            this.addHandler('click', this.onClick.bind(this));
            return this;
        },

        onClick: function (name) {
            for (var button in this.list) {
                if (this.list.hasOwnProperty(button)) {
                    if (button === name) {
                        this.list[button].imgDown.style.visibility = 'visible';
                    } else {
                        this.list[button].imgDown.style.visibility = 'hidden';
                    }
                }
            }
            return this;
        },

        add: function (name, active) {
            this.list[name] = new $.Button({
                tooltip: name[0].toUpperCase() + name.substr(1),
                srcRest: this.imagePath + name + '_rest.png',
                srcGroup: this.imagePath + name + '_grouphover.png',
                srcHover: this.imagePath + name + '_hover.png',
                srcDown: this.imagePath + name + '_pressed.png',
                onClick: this.raiseEvent.bind(this, 'click', name)
            });
            if (active) {
                this.list[name].imgDown.style.visibility = 'visible';
            }
            this.raiseEvent('add', this.list[name]);
            return this.list[name];
        },

        get: function (name) {
            return this.list[name];
        }

    });

    var overlay = {

        initialize: function (options) {
            $.extend(this, options);
            this.el = document.createElement('div');
            this.el.className = 'overlay';
            var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            svg.setAttribute('version', '1.1');
            svg.setAttribute('width', '100%');
            svg.setAttribute('height', '100%');
            svg.setAttribute('preserveAspectRatio', 'none');
            svg.setAttribute('viewBox', '0 0 100 100')
            svg.style.cursor = 'default';
            this.el.appendChild(svg);
            var width = this.viewer.viewport.homeBounds.width;
            var height = this.viewer.viewport.homeBounds.height;
            this.viewer.addOverlay(this.el, new $.Rect(0, 0, width, height));
            return this;
        }

    };

})(OpenSeadragon);
<|endoftext|>


<commit_before>/*
 * Jakefile for Rimu Markup (http://github.com/srackham/rimu).
 */
'use strict';

var pkg = require('./package.json');
var shelljs = require('shelljs');
var child_process = require('child_process');

/* Inputs and outputs */

var RIMU_VAR_LIB = 'bin/rimu-var.js';  // Script tag library format.
var RIMU_VAR_LIB_MIN = 'bin/rimu-var.min.js';
var RIMU_COMMONJS2_LIB = 'bin/rimu-commonjs2.js';  // Npm library format.
var MAIN_TS = 'src/main.ts';
var MAIN_JS = 'out/main.js';
var SOURCE = shelljs.ls('src/*.ts');
var TESTS = shelljs.ls('test/*.js');
var GH_PAGES_DIR = './gh-pages/';
var RIMUC = './bin/rimuc.js';

var DOCS = [
  {src: 'README.md', dst: 'doc/index.html', title: 'Rimu Markup', hasToc: true},
  {src: 'CHANGELOG.md', dst: 'doc/CHANGELOG.html', title: 'Rimu Change Log', hasToc: true},
  {src: 'doc/reference.rmu', dst: 'doc/reference.html', title: 'Rimu Reference', hasToc: true},
  {src: 'doc/tips.rmu', dst: 'doc/tips.html', title: 'Rimu Tips', hasToc: true},
  {src: 'doc/rimuplayground.rmu', dst: 'doc/rimuplayground.html', title: 'Rimu Playground', hasToc: true}
];

var HTML = [];
DOCS.forEach(function(doc) {
  HTML.push(doc.dst);
});

/* Utility functions. */

/*
 Execute shell commands in parallel then run the callback when they have all finished.
 `callback` defaults to the Jake async `complete` function.
 Abort if an error occurs.
 Write command output to the inherited stdout (unless the Jake --quiet option is set).
 Print a status message when each command starts and finishes (unless the Jake --quiet option is set).

 NOTE: This function is similar to the built-in jake.exec function but is twice as fast.
 */
function exec(commands, callback) {
  if (typeof commands === 'string') {
    commands = [commands];
  }
  callback = callback || complete;
  var remaining = commands.length;
  if (remaining === 0) {
    callback();
  } else {
    commands.forEach(function(command) {
      jake.logger.log('Starting: ' + command);
      child_process.exec(command, function(error, stdout, stderr) {
        if (!jake.program.opts.quiet) {
          process.stdout.write(stdout);
        }
        if (error !== null) {
          fail(error, error.code);
        }
        jake.logger.log('Finished: ' + command);
        remaining--;
        if (remaining === 0) {
          callback();
        }
      });
    });
  }
}

/*
 Tasks

 All tasks are synchronous (another task will not run until the current task has completed).
 Consequently all task dependencies are executed asynchronously in declaration order.
 The `exec` function ensures shell commands within each task run in parallel.
 */

desc('Run test task.');
task('default', ['test']);

desc('compile, jslint, test, tslint, build-gh-pages, validate-html.');
task('build', ['test', 'tslint', 'build-gh-pages', 'validate-html']);

desc('Update version number, tag and push to Github and npm. Use vers=x.y.z argument to set a new version number. Finally, rebuild and publish docs website.');
task('release', ['build', 'version', 'tag', 'publish', 'release-gh-pages']);

desc('Lint Javascript and JSON files.');
task('jslint', {async: true}, function() {
  var commands = TESTS.concat([RIMUC]).map(function(file) {
    return 'jshint ' + file;
  });
  commands.push('jsonlint --quiet package.json');
  exec(commands);
});

desc('Lint TypeScript source files.');
task('tslint', {async: true}, function() {
  complete(); return  // TODO: Uncomment when tslint is compatible with TypeScript 1.5.
  var commands = SOURCE.map(function(file) {
    return 'tslint -f ' + file;
  });
  exec(commands);
});

desc('Run tests (recompile if necessary).');
task('test', ['compile', 'jslint'], {async: true}, function() {
  var commands = TESTS.map(function(file) {
    return 'nodeunit ' + file;
  });
  exec(commands);
});

// TODO: Fix me.
desc('Compile Typescript to JavaScript then bundle CommonJS and scriptable libraries.');
task('compile', [MAIN_JS, RIMU_VAR_LIB, RIMU_COMMONJS2_LIB, RIMU_VAR_LIB_MIN]);

file(MAIN_JS, SOURCE, {async: true}, function() {
  shelljs.rm('./out/*');
  exec('tsc --project .');
});

file(RIMU_COMMONJS2_LIB, [MAIN_JS], {async: true}, function() {
  exec('webpack');
});

file(RIMU_VAR_LIB, [MAIN_JS], {async: true}, function() {
  exec('webpack --output-library-target var --output-file ' + RIMU_VAR_LIB);
});

function minify(src, dst) {
  var preamble = '/* ' + pkg.name + ' ' + pkg.version + ' (' + pkg.repository.url + ') */';
  var command = 'uglifyjs  --preamble "' + preamble + '" --output ' + dst + ' ' + src;
  exec(command);
};

file(RIMU_VAR_LIB_MIN, [RIMU_VAR_LIB], {async: true}, function() {
  minify(RIMU_VAR_LIB, RIMU_VAR_LIB_MIN)
});

desc('Generate HTML documentation');
task('html-docs', {async: true}, function() {
  var commands = DOCS.map(function(doc) {
    return 'node ./bin/rimuc.js' +
      ' --styled --no-rimurc' +
      ' --output "' + doc.dst + '"' +
      ' --title "' + doc.title + '"' +
      (doc.hasToc ? ' --toc' : '' ) +
      ' ./examples/.rimurc ./doc/doc-header.rmu ' + doc.src;
  });
  exec(commands);
});

desc('Validate HTML documents with W3C Validator.');
task('validate-html', {async: true}, function() {
  var commands = HTML.map(function(file) {
    return 'nu-html-checker ' + file;
  });
  exec(commands);
});

desc('Display or update the project version number. Use vers=x.y.z argument to set a new version number.');
task('version', {async: true}, function() {
  var version = process.env.vers;
  if (!version) {
    console.log('\nversion: ' + pkg.version);
    complete();
  }
  else {
    if (!version.match(/^\d+\.\d+\.\d+$/)) {
      fail('Invalid version number: ' + version + '\n');
    }
    shelljs.sed('-i', /(\n\s*"version"\s*:\s*)"\d+\.\d+\.\d+"/, '$1' + '"' + version + '"', 'package.json');
    pkg.version = version;
    exec('git commit -m "Bump version number." package.json');
  }
});

desc('Create tag ' + pkg.version);
task('tag', ['test'], {async: true}, function() {
  exec('git tag -a -m "Tag ' + pkg.version + '" ' + pkg.version);
});

desc('Commit changes to local Git repo.');
task('commit', ['test'], {async: true}, function() {
  jake.exec('git commit -a', {interactive: true}, complete);
});

desc('push, publish-npm.');
task('publish', ['push', 'publish-npm']);

desc('Push local commits to Github.');
task('push', ['test'], {async: true}, function() {
  exec('git push -u --tags origin master');
});

desc('Publish to npm.');
task('publish-npm', {async: true}, ['test'], function() {
  exec('npm publish');
});

desc('Rebuild and validate documentation then commit and publish to GitHub Pages');
task('release-gh-pages', ['build-gh-pages', 'commit-gh-pages', 'push-gh-pages']);

desc('Generate documentation and copy to local gh-pages repo');
task('build-gh-pages', ['html-docs', 'validate-html'], function() {
  shelljs.cp('-f', HTML.concat(RIMU_VAR_LIB), GH_PAGES_DIR)
});

desc('Commit changes to local gh-pages repo. Use msg=\'commit message\' to set a custom commit message.');
task('commit-gh-pages', ['test'], {async: true}, function() {
  var msg = process.env.msg;
  if (!msg) {
    msg = 'rebuilt project website';
  }
  shelljs.cd(GH_PAGES_DIR);
  exec('git commit -a -m "' + msg + '"', function () {
    shelljs.cd('..');
    complete();
  });
});

desc('Push gh-pages commits to Github.');
task('push-gh-pages', ['test'], {async: true}, function() {
  shelljs.cd(GH_PAGES_DIR);
  exec('git push origin gh-pages', function () {
    shelljs.cd('..');
    complete();
  });
});
<commit_msg>chore: Generalize rimuc documentation build options.<commit_after>/*
 * Jakefile for Rimu Markup (http://github.com/srackham/rimu).
 */
'use strict';

var pkg = require('./package.json');
var shelljs = require('shelljs');
var child_process = require('child_process');

/* Inputs and outputs */

var RIMU_VAR_LIB = 'bin/rimu-var.js';  // Script tag library format.
var RIMU_VAR_LIB_MIN = 'bin/rimu-var.min.js';
var RIMU_COMMONJS2_LIB = 'bin/rimu-commonjs2.js';  // Npm library format.
var MAIN_TS = 'src/main.ts';
var MAIN_JS = 'out/main.js';
var SOURCE = shelljs.ls('src/*.ts');
var TESTS = shelljs.ls('test/*.js');
var GH_PAGES_DIR = './gh-pages/';
var RIMUC = './bin/rimuc.js';

var DOCS = [
  {src: 'README.md', dst: 'doc/index.html', title: 'Rimu Markup', rimucOptions: '--toc'},
  {src: 'CHANGELOG.md', dst: 'doc/CHANGELOG.html', title: 'Rimu Change Log', rimucOptions: '--toc'},
  {src: 'doc/reference.rmu', dst: 'doc/reference.html', title: 'Rimu Reference', rimucOptions: '--toc'},
  {src: 'doc/tips.rmu', dst: 'doc/tips.html', title: 'Rimu Tips', rimucOptions: '--toc'},
  {src: 'doc/rimuplayground.rmu', dst: 'doc/rimuplayground.html', title: 'Rimu Playground', rimucOptions: '--toc'}
];

var HTML = [];
DOCS.forEach(function(doc) {
  HTML.push(doc.dst);
});

/* Utility functions. */

/*
 Execute shell commands in parallel then run the callback when they have all finished.
 `callback` defaults to the Jake async `complete` function.
 Abort if an error occurs.
 Write command output to the inherited stdout (unless the Jake --quiet option is set).
 Print a status message when each command starts and finishes (unless the Jake --quiet option is set).

 NOTE: This function is similar to the built-in jake.exec function but is twice as fast.
 */
function exec(commands, callback) {
  if (typeof commands === 'string') {
    commands = [commands];
  }
  callback = callback || complete;
  var remaining = commands.length;
  if (remaining === 0) {
    callback();
  } else {
    commands.forEach(function(command) {
      jake.logger.log('Starting: ' + command);
      child_process.exec(command, function(error, stdout, stderr) {
        if (!jake.program.opts.quiet) {
          process.stdout.write(stdout);
        }
        if (error !== null) {
          fail(error, error.code);
        }
        jake.logger.log('Finished: ' + command);
        remaining--;
        if (remaining === 0) {
          callback();
        }
      });
    });
  }
}

/*
 Tasks

 All tasks are synchronous (another task will not run until the current task has completed).
 Consequently all task dependencies are executed asynchronously in declaration order.
 The `exec` function ensures shell commands within each task run in parallel.
 */

desc('Run test task.');
task('default', ['test']);

desc('compile, jslint, test, tslint, build-gh-pages, validate-html.');
task('build', ['test', 'tslint', 'build-gh-pages', 'validate-html']);

desc('Update version number, tag and push to Github and npm. Use vers=x.y.z argument to set a new version number. Finally, rebuild and publish docs website.');
task('release', ['build', 'version', 'tag', 'publish', 'release-gh-pages']);

desc('Lint Javascript and JSON files.');
task('jslint', {async: true}, function() {
  var commands = TESTS.concat([RIMUC]).map(function(file) {
    return 'jshint ' + file;
  });
  commands.push('jsonlint --quiet package.json');
  exec(commands);
});

desc('Lint TypeScript source files.');
task('tslint', {async: true}, function() {
  complete(); return  // TODO: Uncomment when tslint is compatible with TypeScript 1.5.
  var commands = SOURCE.map(function(file) {
    return 'tslint -f ' + file;
  });
  exec(commands);
});

desc('Run tests (recompile if necessary).');
task('test', ['compile', 'jslint'], {async: true}, function() {
  var commands = TESTS.map(function(file) {
    return 'nodeunit ' + file;
  });
  exec(commands);
});

// TODO: Fix me.
desc('Compile Typescript to JavaScript then bundle CommonJS and scriptable libraries.');
task('compile', [MAIN_JS, RIMU_VAR_LIB, RIMU_COMMONJS2_LIB, RIMU_VAR_LIB_MIN]);

file(MAIN_JS, SOURCE, {async: true}, function() {
  shelljs.rm('./out/*');
  exec('tsc --project .');
});

file(RIMU_COMMONJS2_LIB, [MAIN_JS], {async: true}, function() {
  exec('webpack');
});

file(RIMU_VAR_LIB, [MAIN_JS], {async: true}, function() {
  exec('webpack --output-library-target var --output-file ' + RIMU_VAR_LIB);
});

function minify(src, dst) {
  var preamble = '/* ' + pkg.name + ' ' + pkg.version + ' (' + pkg.repository.url + ') */';
  var command = 'uglifyjs  --preamble "' + preamble + '" --output ' + dst + ' ' + src;
  exec(command);
};

file(RIMU_VAR_LIB_MIN, [RIMU_VAR_LIB], {async: true}, function() {
  minify(RIMU_VAR_LIB, RIMU_VAR_LIB_MIN)
});

desc('Generate HTML documentation');
task('html-docs', {async: true}, function() {
  var commands = DOCS.map(function(doc) {
    return 'node ./bin/rimuc.js' +
      ' --styled --no-rimurc' +
      ' --output "' + doc.dst + '"' +
      ' --title "' + doc.title + '"' +
      ' ' + doc.rimucOptions + ' ' +
      ' ./examples/.rimurc ./doc/doc-header.rmu ' + doc.src;
  });
  exec(commands);
});

desc('Validate HTML documents with W3C Validator.');
task('validate-html', {async: true}, function() {
  var commands = HTML.map(function(file) {
    return 'nu-html-checker ' + file;
  });
  exec(commands);
});

desc('Display or update the project version number. Use vers=x.y.z argument to set a new version number.');
task('version', {async: true}, function() {
  var version = process.env.vers;
  if (!version) {
    console.log('\nversion: ' + pkg.version);
    complete();
  }
  else {
    if (!version.match(/^\d+\.\d+\.\d+$/)) {
      fail('Invalid version number: ' + version + '\n');
    }
    shelljs.sed('-i', /(\n\s*"version"\s*:\s*)"\d+\.\d+\.\d+"/, '$1' + '"' + version + '"', 'package.json');
    pkg.version = version;
    exec('git commit -m "Bump version number." package.json');
  }
});

desc('Create tag ' + pkg.version);
task('tag', ['test'], {async: true}, function() {
  exec('git tag -a -m "Tag ' + pkg.version + '" ' + pkg.version);
});

desc('Commit changes to local Git repo.');
task('commit', ['test'], {async: true}, function() {
  jake.exec('git commit -a', {interactive: true}, complete);
});

desc('push, publish-npm.');
task('publish', ['push', 'publish-npm']);

desc('Push local commits to Github.');
task('push', ['test'], {async: true}, function() {
  exec('git push -u --tags origin master');
});

desc('Publish to npm.');
task('publish-npm', {async: true}, ['test'], function() {
  exec('npm publish');
});

desc('Rebuild and validate documentation then commit and publish to GitHub Pages');
task('release-gh-pages', ['build-gh-pages', 'commit-gh-pages', 'push-gh-pages']);

desc('Generate documentation and copy to local gh-pages repo');
task('build-gh-pages', ['html-docs', 'validate-html'], function() {
  shelljs.cp('-f', HTML.concat(RIMU_VAR_LIB), GH_PAGES_DIR)
});

desc('Commit changes to local gh-pages repo. Use msg=\'commit message\' to set a custom commit message.');
task('commit-gh-pages', ['test'], {async: true}, function() {
  var msg = process.env.msg;
  if (!msg) {
    msg = 'rebuilt project website';
  }
  shelljs.cd(GH_PAGES_DIR);
  exec('git commit -a -m "' + msg + '"', function () {
    shelljs.cd('..');
    complete();
  });
});

desc('Push gh-pages commits to Github.');
task('push-gh-pages', ['test'], {async: true}, function() {
  shelljs.cd(GH_PAGES_DIR);
  exec('git push origin gh-pages', function () {
    shelljs.cd('..');
    complete();
  });
});
<|endoftext|>


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

var Util = require('./util.js');
var WakeLock = require('./wakelock.js');

// Start at a higher number to reduce chance of conflict.
var nextDisplayId = 1000;
var hasShowDeprecationWarning = false;

/**
 * The base class for all VR displays.
 */
function VRDisplay() {
  this.isPolyfilled = true;
  this.displayId = nextDisplayId++;
  this.displayName = 'webvr-polyfill displayName';

  this.isConnected = true;
  this.isPresenting = false;
  this.capabilities = {
    hasPosition: false,
    hasOrientation: false,
    hasExternalDisplay: false,
    canPresent: false,
    maxLayers: 1
  };
  this.stageParameters = null;

  // "Private" members.
  this.waitingForPresent_ = false;
  this.layer_ = null;

  this.fullscreenElement_ = null;
  this.fullscreenWrapper_ = null;
  this.fullscreenElementCachedStyle_ = null;

  this.fullscreenEventTarget_ = null;
  this.fullscreenChangeHandler_ = null;
  this.fullscreenErrorHandler_ = null;

  this.wakelock_ = new WakeLock();
}

VRDisplay.prototype.getPose = function() {
  // TODO: Technically this should retain it's value for the duration of a frame
  // but I doubt that's practical to do in javascript.
  return this.getImmediatePose();
};

VRDisplay.prototype.requestAnimationFrame = function(callback) {
  return window.requestAnimationFrame(callback);
};

VRDisplay.prototype.cancelAnimationFrame = function(id) {
  return window.cancelAnimationFrame(id);
};

VRDisplay.prototype.wrapForFullscreen = function(element) {
  if (!this.fullscreenWrapper_) {
    this.fullscreenWrapper_ = document.createElement('div');
    var cssProperties = [
      'height: ' + Math.min(screen.height, screen.width) + 'px !important',
      'top: 0 !important',
      'left: 0 !important',
      'right: 0 !important',
      'border: 0',
      'margin: 0',
      'padding: 0',
      'z-index: 999999 !important',
      'position: fixed',
    ];
    this.fullscreenWrapper_.setAttribute('style', cssProperties.join('; ') + ';');
    this.fullscreenWrapper_.classList.add('webvr-polyfill-fullscreen-wrapper');
  }

  if (this.fullscreenElement_ == element)
    return this.fullscreenWrapper_;

  // Remove any previously applied wrappers
  this.removeFullscreenWrapper();

  this.fullscreenElement_ = element;
  var parent = this.fullscreenElement_.parentElement;
  parent.insertBefore(this.fullscreenWrapper_, this.fullscreenElement_);
  parent.removeChild(this.fullscreenElement_);
  this.fullscreenWrapper_.insertBefore(this.fullscreenElement_, this.fullscreenWrapper_.firstChild);
  this.fullscreenElementCachedStyle_ = this.fullscreenElement_.getAttribute('style');

  var self = this;
  function applyFullscreenElementStyle() {
    if (!self.fullscreenElement_)
      return;

    var cssProperties = [
      'position: absolute',
      'top: 0',
      'left: 0',
      'width: ' + Math.max(screen.width, screen.height) + 'px',
      'height: ' + Math.min(screen.height, screen.width) + 'px',
      'border: 0',
      'margin: 0',
      'padding: 0',
    ];
    self.fullscreenElement_.setAttribute('style', cssProperties.join('; ') + ';');
  }

  if (Util.isIOS()) {
    // "To the last I grapple with thee;
    //  from hell's heart I stab at thee;
    //  for hate's sake I spit my last breath at thee."
    // -- Moby Dick, by Herman Melville
    this.fullscreenElement_.setAttribute('style', 'width: ' + (Math.max(screen.width, screen.height) - 1) + 'px;');
    setTimeout(applyFullscreenElementStyle, 1000);
  } else {
    applyFullscreenElementStyle();
  }

  return this.fullscreenWrapper_;
};

VRDisplay.prototype.removeFullscreenWrapper = function() {
  if (!this.fullscreenElement_) {
    return;
  }

  var element = this.fullscreenElement_;
  if (this.fullscreenElementCachedStyle_) {
    element.setAttribute('style', this.fullscreenElementCachedStyle_);
  } else {
    element.removeAttribute('style');
  }
  this.fullscreenElement_ = null;
  this.fullscreenElementCachedStyle_ = null;

  var parent = this.fullscreenWrapper_.parentElement;
  this.fullscreenWrapper_.removeChild(element);
  parent.insertBefore(element, this.fullscreenWrapper_);
  parent.removeChild(this.fullscreenWrapper_);

  return element;
};

VRDisplay.prototype.requestPresent = function(layers) {
  var self = this;

  if (!(layers instanceof Array)) {
    if (!hasShowDeprecationWarning) {
      console.warn("Using a deprecated form of requestPresent. Should pass in an array of VRLayers.");
      hasShowDeprecationWarning = true;
    }
    layers = [layers];
  }

  return new Promise(function(resolve, reject) {
    if (!self.capabilities.canPresent) {
      reject(new Error('VRDisplay is not capable of presenting.'));
      return;
    }

    if (layers.length == 0 || layers.length > self.capabilities.maxLayers) {
      reject(new Error('Invalid number of layers.'));
      return;
    }

    self.layer_ = layers[0];

    self.waitingForPresent_ = false;
    if (self.layer_ && self.layer_.source) {
      var fullscreenElement = self.wrapForFullscreen(self.layer_.source);

      function onFullscreenChange() {
        var actualFullscreenElement = Util.getFullscreenElement();

        self.isPresenting = (fullscreenElement === actualFullscreenElement);
        if (self.isPresenting) {
          if (screen.orientation && screen.orientation.lock) {
            screen.orientation.lock('landscape-primary');
          }
          self.waitingForPresent_ = false;
          self.beginPresent_();
          resolve();
        } else {
          if (screen.orientation && screen.orientation.unlock) {
            screen.orientation.unlock();
          }
          self.removeFullscreenWrapper();
          self.wakelock_.release();
          self.endPresent_();
          self.removeFullscreenListeners_();
        }
        self.fireVRDisplayPresentChange_();
      }
      function onFullscreenError() {
        if (!self.waitingForPresent_) {
          return;
        }

        self.removeFullscreenWrapper();
        self.removeFullscreenListeners_();

        self.wakelock_.release();
        self.waitingForPresent_ = false;
        self.isPresenting = false;

        reject(new Error('Unable to present.'));
      }

      self.addFullscreenListeners_(fullscreenElement,
          onFullscreenChange, onFullscreenError);

      if (Util.requestFullscreen(fullscreenElement)) {
        self.wakelock_.request();
        self.waitingForPresent_ = true;
      } else if (Util.isIOS()) {
        // *sigh* Just fake it.
        self.wakelock_.request();
        self.isPresenting = true;
        self.beginPresent_();
        self.fireVRDisplayPresentChange_();
        resolve();
      }
    }

    if (!self.waitingForPresent_ && !Util.isIOS()) {
      Util.exitFullscreen();
      reject(new Error('Unable to present.'));
    }
  });
};

VRDisplay.prototype.exitPresent = function() {
  var wasPresenting = this.isPresenting;
  var self = this;
  this.isPresenting = false;
  this.layer_ = null;
  this.wakelock_.release();

  return new Promise(function(resolve, reject) {
    if (wasPresenting) {
      if (!Util.exitFullscreen() && Util.isIOS()) {
        self.endPresent_();
        self.fireVRDisplayPresentChange_();
      }

      resolve();
    } else {
      reject(new Error('Was not presenting to VRDisplay.'));
    }
  });
};

VRDisplay.prototype.getLayers = function() {
  if (this.layer_) {
    return [this.layer_];
  }
  return [];
};

VRDisplay.prototype.fireVRDisplayPresentChange_ = function() {
  var event = new CustomEvent('vrdisplaypresentchange', {detail: {vrdisplay: this}});
  window.dispatchEvent(event);
};

VRDisplay.prototype.addFullscreenListeners_ = function(element, changeHandler, errorHandler) {
  this.removeFullscreenListeners_();

  this.fullscreenEventTarget_ = element;
  this.fullscreenChangeHandler_ = changeHandler;
  this.fullscreenErrorHandler_ = errorHandler;

  if (changeHandler) {
    element.addEventListener('fullscreenchange', changeHandler, false);
    element.addEventListener('webkitfullscreenchange', changeHandler, false);
    document.addEventListener('mozfullscreenchange', changeHandler, false);
    element.addEventListener('msfullscreenchange', changeHandler, false);
  }

  if (errorHandler) {
    element.addEventListener('fullscreenerror', errorHandler, false);
    element.addEventListener('webkitfullscreenerror', errorHandler, false);
    document.addEventListener('mozfullscreenerror', errorHandler, false);
    element.addEventListener('msfullscreenerror', errorHandler, false);
  }
};

VRDisplay.prototype.removeFullscreenListeners_ = function() {
  if (!this.fullscreenEventTarget_)
    return;

  var element = this.fullscreenEventTarget_;

  if (this.fullscreenChangeHandler_) {
    var changeHandler = this.fullscreenChangeHandler_;
    element.removeEventListener('fullscreenchange', changeHandler, false);
    element.removeEventListener('webkitfullscreenchange', changeHandler, false);
    document.removeEventListener('mozfullscreenchange', changeHandler, false);
    element.removeEventListener('msfullscreenchange', changeHandler, false);
  }

  if (this.fullscreenErrorHandler_) {
    var errorHandler = this.fullscreenErrorHandler_;
    element.removeEventListener('fullscreenerror', errorHandler, false);
    element.removeEventListener('webkitfullscreenerror', errorHandler, false);
    document.removeEventListener('mozfullscreenerror', errorHandler, false);
    element.removeEventListener('msfullscreenerror', errorHandler, false);
  }

  this.fullscreenEventTarget_ = null;
  this.fullscreenChangeHandler_ = null;
  this.fullscreenErrorHandler_ = null;
};

VRDisplay.prototype.beginPresent_ = function() {
  // Override to add custom behavior when presentation begins.
};

VRDisplay.prototype.endPresent_ = function() {
  // Override to add custom behavior when presentation ends.
};

VRDisplay.prototype.submitFrame = function(pose) {
  // Override to add custom behavior for frame submission.
};

VRDisplay.prototype.getEyeParameters = function(whichEye) {
  // Override to return accurate eye parameters if canPresent is true.
  return null;
};

/*
 * Deprecated classes
 */

/**
 * The base class for all VR devices. (Deprecated)
 */
function VRDevice() {
  this.isPolyfilled = true;
  this.hardwareUnitId = 'webvr-polyfill hardwareUnitId';
  this.deviceId = 'webvr-polyfill deviceId';
  this.deviceName = 'webvr-polyfill deviceName';
}

/**
 * The base class for all VR HMD devices. (Deprecated)
 */
function HMDVRDevice() {
}
HMDVRDevice.prototype = new VRDevice();

/**
 * The base class for all VR position sensor devices. (Deprecated)
 */
function PositionSensorVRDevice() {
}
PositionSensorVRDevice.prototype = new VRDevice();

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

var Util = require('./util.js');
var WakeLock = require('./wakelock.js');

// Start at a higher number to reduce chance of conflict.
var nextDisplayId = 1000;
var hasShowDeprecationWarning = false;

/**
 * The base class for all VR displays.
 */
function VRDisplay() {
  this.isPolyfilled = true;
  this.displayId = nextDisplayId++;
  this.displayName = 'webvr-polyfill displayName';

  this.isConnected = true;
  this.isPresenting = false;
  this.capabilities = {
    hasPosition: false,
    hasOrientation: false,
    hasExternalDisplay: false,
    canPresent: false,
    maxLayers: 1
  };
  this.stageParameters = null;

  // "Private" members.
  this.waitingForPresent_ = false;
  this.layer_ = null;

  this.fullscreenElement_ = null;
  this.fullscreenWrapper_ = null;
  this.fullscreenElementCachedStyle_ = null;

  this.fullscreenEventTarget_ = null;
  this.fullscreenChangeHandler_ = null;
  this.fullscreenErrorHandler_ = null;

  this.wakelock_ = new WakeLock();
}

VRDisplay.prototype.getPose = function() {
  // TODO: Technically this should retain it's value for the duration of a frame
  // but I doubt that's practical to do in javascript.
  return this.getImmediatePose();
};

VRDisplay.prototype.requestAnimationFrame = function(callback) {
  return window.requestAnimationFrame(callback);
};

VRDisplay.prototype.cancelAnimationFrame = function(id) {
  return window.cancelAnimationFrame(id);
};

VRDisplay.prototype.wrapForFullscreen = function(element) {
  if (!this.fullscreenWrapper_) {
    this.fullscreenWrapper_ = document.createElement('div');
    var cssProperties = [
      'height: ' + Math.min(screen.height, screen.width) + 'px !important',
      'top: 0 !important',
      'left: 0 !important',
      'right: 0 !important',
      'border: 0',
      'margin: 0',
      'padding: 0',
      'z-index: 999999 !important',
      'position: fixed',
    ];
    this.fullscreenWrapper_.setAttribute('style', '');
    this.fullscreenWrapper_.setAttribute('style', cssProperties.join('; ') + ';');
    this.fullscreenWrapper_.classList.add('webvr-polyfill-fullscreen-wrapper');
  }

  if (this.fullscreenElement_ == element)
    return this.fullscreenWrapper_;

  // Remove any previously applied wrappers
  this.removeFullscreenWrapper();

  this.fullscreenElement_ = element;
  var parent = this.fullscreenElement_.parentElement;
  parent.insertBefore(this.fullscreenWrapper_, this.fullscreenElement_);
  parent.removeChild(this.fullscreenElement_);
  this.fullscreenWrapper_.insertBefore(this.fullscreenElement_, this.fullscreenWrapper_.firstChild);
  this.fullscreenElementCachedStyle_ = this.fullscreenElement_.getAttribute('style');

  var self = this;
  function applyFullscreenElementStyle() {
    if (!self.fullscreenElement_)
      return;

    var cssProperties = [
      'position: absolute',
      'top: 0',
      'left: 0',
      'width: ' + Math.max(screen.width, screen.height) + 'px',
      'height: ' + Math.min(screen.height, screen.width) + 'px',
      'border: 0',
      'margin: 0',
      'padding: 0',
    ];
    self.fullscreenElement_.setAttribute('style', cssProperties.join('; ') + ';');
  }

  if (Util.isIOS()) {
    // "To the last I grapple with thee;
    //  from hell's heart I stab at thee;
    //  for hate's sake I spit my last breath at thee."
    // -- Moby Dick, by Herman Melville
    this.fullscreenElement_.setAttribute('style', 'width: ' + (Math.max(screen.width, screen.height) - 1) + 'px;');
    setTimeout(applyFullscreenElementStyle, 1000);
  } else {
    applyFullscreenElementStyle();
  }

  return this.fullscreenWrapper_;
};

VRDisplay.prototype.removeFullscreenWrapper = function() {
  if (!this.fullscreenElement_) {
    return;
  }

  var element = this.fullscreenElement_;
  if (this.fullscreenElementCachedStyle_) {
    element.setAttribute('style', this.fullscreenElementCachedStyle_);
  } else {
    element.removeAttribute('style');
  }
  this.fullscreenElement_ = null;
  this.fullscreenElementCachedStyle_ = null;

  var parent = this.fullscreenWrapper_.parentElement;
  this.fullscreenWrapper_.removeChild(element);
  parent.insertBefore(element, this.fullscreenWrapper_);
  parent.removeChild(this.fullscreenWrapper_);

  return element;
};

VRDisplay.prototype.requestPresent = function(layers) {
  var self = this;

  if (!(layers instanceof Array)) {
    if (!hasShowDeprecationWarning) {
      console.warn("Using a deprecated form of requestPresent. Should pass in an array of VRLayers.");
      hasShowDeprecationWarning = true;
    }
    layers = [layers];
  }

  return new Promise(function(resolve, reject) {
    if (!self.capabilities.canPresent) {
      reject(new Error('VRDisplay is not capable of presenting.'));
      return;
    }

    if (layers.length == 0 || layers.length > self.capabilities.maxLayers) {
      reject(new Error('Invalid number of layers.'));
      return;
    }

    self.layer_ = layers[0];

    self.waitingForPresent_ = false;
    if (self.layer_ && self.layer_.source) {
      var fullscreenElement = self.wrapForFullscreen(self.layer_.source);

      function onFullscreenChange() {
        var actualFullscreenElement = Util.getFullscreenElement();

        self.isPresenting = (fullscreenElement === actualFullscreenElement);
        if (self.isPresenting) {
          if (screen.orientation && screen.orientation.lock) {
            screen.orientation.lock('landscape-primary');
          }
          self.waitingForPresent_ = false;
          self.beginPresent_();
          resolve();
        } else {
          if (screen.orientation && screen.orientation.unlock) {
            screen.orientation.unlock();
          }
          self.removeFullscreenWrapper();
          self.wakelock_.release();
          self.endPresent_();
          self.removeFullscreenListeners_();
        }
        self.fireVRDisplayPresentChange_();
      }
      function onFullscreenError() {
        if (!self.waitingForPresent_) {
          return;
        }

        self.removeFullscreenWrapper();
        self.removeFullscreenListeners_();

        self.wakelock_.release();
        self.waitingForPresent_ = false;
        self.isPresenting = false;

        reject(new Error('Unable to present.'));
      }

      self.addFullscreenListeners_(fullscreenElement,
          onFullscreenChange, onFullscreenError);

      if (Util.requestFullscreen(fullscreenElement)) {
        self.wakelock_.request();
        self.waitingForPresent_ = true;
      } else if (Util.isIOS()) {
        // *sigh* Just fake it.
        self.wakelock_.request();
        self.isPresenting = true;
        self.beginPresent_();
        self.fireVRDisplayPresentChange_();
        resolve();
      }
    }

    if (!self.waitingForPresent_ && !Util.isIOS()) {
      Util.exitFullscreen();
      reject(new Error('Unable to present.'));
    }
  });
};

VRDisplay.prototype.exitPresent = function() {
  var wasPresenting = this.isPresenting;
  var self = this;
  this.isPresenting = false;
  this.layer_ = null;
  this.wakelock_.release();

  return new Promise(function(resolve, reject) {
    if (wasPresenting) {
      if (!Util.exitFullscreen() && Util.isIOS()) {
        self.endPresent_();
        self.fireVRDisplayPresentChange_();
      }

      resolve();
    } else {
      reject(new Error('Was not presenting to VRDisplay.'));
    }
  });
};

VRDisplay.prototype.getLayers = function() {
  if (this.layer_) {
    return [this.layer_];
  }
  return [];
};

VRDisplay.prototype.fireVRDisplayPresentChange_ = function() {
  var event = new CustomEvent('vrdisplaypresentchange', {detail: {vrdisplay: this}});
  window.dispatchEvent(event);
};

VRDisplay.prototype.addFullscreenListeners_ = function(element, changeHandler, errorHandler) {
  this.removeFullscreenListeners_();

  this.fullscreenEventTarget_ = element;
  this.fullscreenChangeHandler_ = changeHandler;
  this.fullscreenErrorHandler_ = errorHandler;

  if (changeHandler) {
    element.addEventListener('fullscreenchange', changeHandler, false);
    element.addEventListener('webkitfullscreenchange', changeHandler, false);
    document.addEventListener('mozfullscreenchange', changeHandler, false);
    element.addEventListener('msfullscreenchange', changeHandler, false);
  }

  if (errorHandler) {
    element.addEventListener('fullscreenerror', errorHandler, false);
    element.addEventListener('webkitfullscreenerror', errorHandler, false);
    document.addEventListener('mozfullscreenerror', errorHandler, false);
    element.addEventListener('msfullscreenerror', errorHandler, false);
  }
};

VRDisplay.prototype.removeFullscreenListeners_ = function() {
  if (!this.fullscreenEventTarget_)
    return;

  var element = this.fullscreenEventTarget_;

  if (this.fullscreenChangeHandler_) {
    var changeHandler = this.fullscreenChangeHandler_;
    element.removeEventListener('fullscreenchange', changeHandler, false);
    element.removeEventListener('webkitfullscreenchange', changeHandler, false);
    document.removeEventListener('mozfullscreenchange', changeHandler, false);
    element.removeEventListener('msfullscreenchange', changeHandler, false);
  }

  if (this.fullscreenErrorHandler_) {
    var errorHandler = this.fullscreenErrorHandler_;
    element.removeEventListener('fullscreenerror', errorHandler, false);
    element.removeEventListener('webkitfullscreenerror', errorHandler, false);
    document.removeEventListener('mozfullscreenerror', errorHandler, false);
    element.removeEventListener('msfullscreenerror', errorHandler, false);
  }

  this.fullscreenEventTarget_ = null;
  this.fullscreenChangeHandler_ = null;
  this.fullscreenErrorHandler_ = null;
};

VRDisplay.prototype.beginPresent_ = function() {
  // Override to add custom behavior when presentation begins.
};

VRDisplay.prototype.endPresent_ = function() {
  // Override to add custom behavior when presentation ends.
};

VRDisplay.prototype.submitFrame = function(pose) {
  // Override to add custom behavior for frame submission.
};

VRDisplay.prototype.getEyeParameters = function(whichEye) {
  // Override to return accurate eye parameters if canPresent is true.
  return null;
};

/*
 * Deprecated classes
 */

/**
 * The base class for all VR devices. (Deprecated)
 */
function VRDevice() {
  this.isPolyfilled = true;
  this.hardwareUnitId = 'webvr-polyfill hardwareUnitId';
  this.deviceId = 'webvr-polyfill deviceId';
  this.deviceName = 'webvr-polyfill deviceName';
}

/**
 * The base class for all VR HMD devices. (Deprecated)
 */
function HMDVRDevice() {
}
HMDVRDevice.prototype = new VRDevice();

/**
 * The base class for all VR position sensor devices. (Deprecated)
 */
function PositionSensorVRDevice() {
}
PositionSensorVRDevice.prototype = new VRDevice();

module.exports.VRDisplay = VRDisplay;
module.exports.VRDevice = VRDevice;
module.exports.HMDVRDevice = HMDVRDevice;
module.exports.PositionSensorVRDevice = PositionSensorVRDevice;
<|endoftext|>


<commit_before>
window.addEventListener("mousedown", function(e) {

  if (!e) var e = window.event;
  if (e.which) rightclick = (e.which == 3);
  else if (e.button) rightclick = (e.button == 2);
  //console.log(rightclick);
  if(rightclick) {
    direction = "";
    url = "";
    window.addEventListener("contextmenu", stopContextMenu);
    oldX = e.screenX;
    oldY = e.screenY;
    url = e.target.href;
    window.addEventListener("mousemove", getMouseDirection, false);
    textChainNode.style.display = "";
  }
});

window.addEventListener("mouseup", function(e) {
if(rightclick) {

  window.removeEventListener("mousemove", getMouseDirection, false);
  if(direction === "") {
    window.removeEventListener("contextmenu", stopContextMenu);
  }
  if(direction !== "") {
    console.log(direction);
    console.log(url);
    browser.runtime.sendMessage({
      gesture: direction,
      targeturl: url
    });
  }

  }
  textChainNode.style.display = "none";

});
var url = "";
var rightclick;
var direction = "";

var textChainNode = document.createElement("span");
textChainNode.id = "directionChain";
//textChainNode.style.all = "initial";
textChainNode.style.position = "fixed";
textChainNode.style.bottom = "2px";
textChainNode.style.right = "5px";
textChainNode.style.font = "1rem arial,sans-serif";
document.body.appendChild(textChainNode);
textChainNode.style.display = "none";

var oldX = 0;
var oldY = 0;

function stopContextMenu(e) {
  e.preventDefault();
  return false;
}

function getMouseDirection(e) {

  var x = e.screenX;
  var y = e.screenY;
  var lastX = oldX;
  var lastY = oldY;
  var subX = x - lastX;
  var subY = y - lastY;
  var distX = (subX > 0 ? subX : (-subX));
  var distY= (subY > 0 ? subY : (-subY));
  var currentDirection;

  if(distX < 10 && distY < 10) {
    return;
  }
  if(distX > distY) {
    currentDirection = subX < 0 ? "L" : "R";
  } else {
    currentDirection = subY < 0 ? "U" : "D";
  }
  if(currentDirection !== direction.charAt(direction.length - 1)) {
    direction += currentDirection;
  }
  oldX = x;
  oldY = y;

  textChainNode.textContent = direction;
  //textChainNode.appendChild(document.createTextNode(direction));
}

<commit_msg>Resolves #3<commit_after>
window.addEventListener("mousedown", function(e) {

  if (!e) var e = window.event;
  if (e.which) rightclick = (e.which == 3);
  else if (e.button) rightclick = (e.button == 2);
  //console.log(rightclick);
  if(rightclick) {
    direction = "";
    url = "";
    window.addEventListener("contextmenu", stopContextMenu);
    oldX = e.screenX;
    oldY = e.screenY;

    let node = e.target;
    console.log(e.nodeName);
    while(!node.hasAttribute("href")) {

      //console.log(node.nodeName);
      node = node.parentElement;
      if(node.nodeName === "BODY") {
        break;
      }
    }
    url = node.href;
    window.addEventListener("mousemove", getMouseDirection, false);
    textChainNode.style.display = "";
  }
});

window.addEventListener("mouseup", function(e) {
if(rightclick) {

  window.removeEventListener("mousemove", getMouseDirection, false);
  if(direction === "") {
    window.removeEventListener("contextmenu", stopContextMenu);
  }
  if(direction !== "") {
    console.log(direction);
    console.log(url);
    browser.runtime.sendMessage({
      gesture: direction,
      targeturl: url
    });
  }

  }
  textChainNode.style.display = "none";

});
var url = "";
var rightclick;
var direction = "";

var textChainNode = document.createElement("span");
textChainNode.id = "directionChain";
//textChainNode.style.all = "initial";
textChainNode.style.position = "fixed";
textChainNode.style.bottom = "2px";
textChainNode.style.right = "5px";
textChainNode.style.font = "1rem arial,sans-serif";
document.body.appendChild(textChainNode);
textChainNode.style.display = "none";

var oldX = 0;
var oldY = 0;

function stopContextMenu(e) {
  e.preventDefault();
  return false;
}

function getMouseDirection(e) {

  var x = e.screenX;
  var y = e.screenY;
  var lastX = oldX;
  var lastY = oldY;
  var subX = x - lastX;
  var subY = y - lastY;
  var distX = (subX > 0 ? subX : (-subX));
  var distY= (subY > 0 ? subY : (-subY));
  var currentDirection;

  if(distX < 10 && distY < 10) {
    return;
  }
  if(distX > distY) {
    currentDirection = subX < 0 ? "L" : "R";
  } else {
    currentDirection = subY < 0 ? "U" : "D";
  }
  if(currentDirection !== direction.charAt(direction.length - 1)) {
    direction += currentDirection;
  }
  oldX = x;
  oldY = y;

  textChainNode.textContent = direction;
  //textChainNode.appendChild(document.createTextNode(direction));
}

<|endoftext|>