2016-09-09 17:20:59 +01:00
|
|
|
$(function() { sio = (function() {
|
|
|
|
|
|
|
|
var sio = {};
|
|
|
|
|
|
|
|
var counter = $('#counter');
|
|
|
|
|
|
|
|
var canvasPdf = $('#canvas-pdf').get(0);
|
|
|
|
var contextPdf = canvasPdf.getContext('2d');
|
|
|
|
|
|
|
|
var canvasPaint = $('#canvas-paint').get(0);
|
|
|
|
var contextPaint = canvasPaint.getContext('2d');
|
|
|
|
|
|
|
|
var pdf;
|
|
|
|
var currentPage = 1;
|
|
|
|
|
|
|
|
var startTime = 0;
|
|
|
|
var startSlide = 0;
|
|
|
|
var refreshIntervalId = 0;
|
|
|
|
|
|
|
|
var pointer = false;
|
|
|
|
var shouldUpdatePointer = false;
|
|
|
|
|
|
|
|
var canvasPdfBounding;
|
|
|
|
|
|
|
|
var lasers = {};
|
|
|
|
var drawAudienceLasers = false;
|
|
|
|
|
|
|
|
PDFJS.getDocument('/static/uploaded/' + filename + '.pdf').then(function getPdf(_pdf) {
|
|
|
|
pdf = _pdf;
|
|
|
|
updateUI();
|
|
|
|
});
|
|
|
|
|
|
|
|
var socket = io();
|
|
|
|
|
|
|
|
socket.on('welcome', function() {
|
|
|
|
socket.emit('speaker', filename, socket.id);
|
|
|
|
});
|
|
|
|
|
|
|
|
socket.on('pointer', canvasPointer);
|
|
|
|
|
|
|
|
function filterInt(value) {
|
|
|
|
if(/^(\-|\+)?([0-9]+|Infinity)$/.test(value))
|
|
|
|
return Number(value);
|
|
|
|
return NaN;
|
|
|
|
}
|
|
|
|
|
|
|
|
var updateUI = function() {
|
|
|
|
|
|
|
|
counter.val(currentPage + '/' + pdf.pdfInfo.numPages);
|
|
|
|
|
|
|
|
$('#previous,#first').prop('disabled', currentPage === 1);
|
|
|
|
$('#next,#last').prop('disabled', currentPage === pdf.pdfInfo.numPages);
|
|
|
|
|
|
|
|
pdf.getPage(currentPage).then(function(page) {
|
|
|
|
|
|
|
|
previousPage = currentPage;
|
|
|
|
|
|
|
|
var viewport = page.getViewport(2.0);
|
|
|
|
|
|
|
|
canvasPdf.width = viewport.width;
|
|
|
|
canvasPdf.height = viewport.height;
|
|
|
|
|
|
|
|
canvasPaint.width = viewport.width;
|
|
|
|
canvasPaint.height = viewport.height;
|
|
|
|
|
|
|
|
$('#canvases').width(canvasPdf.width + 'px');
|
|
|
|
$('#canvases').height(canvasPdf.height + 'px');
|
|
|
|
|
|
|
|
canvasPdfBounding = canvasPdf.getBoundingClientRect();
|
|
|
|
|
|
|
|
var renderContext = {
|
|
|
|
canvasContext: contextPdf,
|
|
|
|
viewport: viewport
|
|
|
|
};
|
|
|
|
|
|
|
|
page.render(renderContext);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
function updateAudience() { socket.emit('change-slide', filename, currentPage); }
|
|
|
|
|
|
|
|
function formatTime(ms) {
|
|
|
|
var sec = padToTwo(Math.floor((ms / 1000) % 60));
|
|
|
|
var min = padToTwo(Math.floor(((ms / 1000 - sec) % 3600) / 60));
|
|
|
|
|
|
|
|
return min + ':' + sec;
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateTimers() {
|
|
|
|
if (refreshIntervalId !== 0) {
|
|
|
|
$('#totalTime').html(formatTime(Date.now() - startTime));
|
|
|
|
$('#slideTime').html(formatTime(Date.now() - startSlide));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function padToTwo(number) {
|
|
|
|
if (number<=99) { number = ("0"+number).slice(-2); }
|
|
|
|
return number;
|
|
|
|
}
|
|
|
|
|
|
|
|
function resetTimeSlide() {
|
|
|
|
startSlide = Date.now();
|
|
|
|
updateTimers();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check if number is valid, and updates
|
|
|
|
// number undefined means sync all clients
|
|
|
|
function changeSlide(number) {
|
|
|
|
|
|
|
|
if (isNaN(number) || number < 1 || number > pdf.pdfInfo.numPages) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentPage === undefined || currentPage === number) {
|
|
|
|
updateAudience();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
currentPage = number;
|
|
|
|
|
|
|
|
updateUI();
|
|
|
|
updateAudience();
|
|
|
|
resetTimeSlide();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function canvasPointer(id,x,y) {
|
|
|
|
|
|
|
|
// Clear canvas
|
|
|
|
canvasPaint.width = canvasPaint.width;
|
|
|
|
|
|
|
|
if (id != undefined) {
|
|
|
|
if (x != undefined && y != undefined) {
|
|
|
|
lasers[id] = {x:x, y:y};
|
|
|
|
} else {
|
|
|
|
delete lasers[id];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var laserIndex in lasers) {
|
|
|
|
|
|
|
|
var laser = lasers[laserIndex];
|
|
|
|
|
|
|
|
if (drawAudienceLasers === true || laserIndex === socket.id) {
|
|
|
|
|
|
|
|
contextPaint.fillStyle = laserIndex === socket.id ? 'red' : 'green';
|
|
|
|
contextPaint.beginPath();
|
|
|
|
contextPaint.arc(laser.x * canvasPdf.width, laser.y * canvasPdf.height, 10, 0, Math.PI*2, true);
|
|
|
|
contextPaint.closePath();
|
|
|
|
contextPaint.fill();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
sio.onMouseDown = function(event) {
|
|
|
|
|
2016-09-09 17:25:16 +01:00
|
|
|
var x = event.offsetX / canvasPdf.width;
|
|
|
|
var y = event.offsetY / canvasPdf.height;
|
2016-09-09 17:20:59 +01:00
|
|
|
|
|
|
|
socket.emit('pointer', filename, socket.id, x, y);
|
|
|
|
|
|
|
|
pointer = true;
|
|
|
|
shouldUpdatePointer = true;
|
|
|
|
|
|
|
|
canvasPointer(socket.id, x, y);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
sio.onMouseMove = function(event) {
|
|
|
|
|
|
|
|
if (pointer) {
|
|
|
|
|
2016-09-09 17:25:16 +01:00
|
|
|
var x = event.offsetX / canvasPdf.width;
|
|
|
|
var y = event.offsetY / canvasPdf.height;
|
2016-09-09 17:20:59 +01:00
|
|
|
|
|
|
|
if (shouldUpdatePointer) {
|
|
|
|
// Update
|
|
|
|
socket.emit('pointer', filename, socket.id, x, y);
|
|
|
|
|
|
|
|
shouldUpdatePointer = false;
|
|
|
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
|
|
|
shouldUpdatePointer = true;
|
|
|
|
|
|
|
|
}, 20);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
canvasPointer(socket.id, x, y);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
sio.onMouseUp = function(event) {
|
|
|
|
|
|
|
|
socket.emit('pointer', filename, socket.id);
|
|
|
|
|
|
|
|
pointer = false;
|
|
|
|
shouldUpdatePointer = false;
|
|
|
|
|
|
|
|
canvasPointer(socket.id);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
sio.startPresentation = function() {
|
|
|
|
|
|
|
|
startTime = startSlide = Date.now();
|
|
|
|
|
|
|
|
refreshIntervalId = setInterval(updateTimers, 1000);
|
|
|
|
updateTimers();
|
|
|
|
|
|
|
|
$('#start').prop('disabled', true);
|
|
|
|
$('#stop').prop('disabled', false);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
sio.stopPresentation = function() {
|
|
|
|
|
|
|
|
clearInterval(refreshIntervalId);
|
|
|
|
refreshIntervalId = 0;
|
|
|
|
|
|
|
|
$('#start').prop('disabled', false);
|
|
|
|
$('#stop').prop('disabled', true);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
sio.changeSlideFromCounter = function() {
|
|
|
|
|
|
|
|
var slideNumber = filterInt($('#counter').val());
|
|
|
|
|
|
|
|
changeSlide(slideNumber);
|
|
|
|
|
|
|
|
// lose focus
|
|
|
|
$(':focus').blur();
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
sio.switchAudienceLaser = function() {
|
|
|
|
|
|
|
|
var laser = $('#viewer-laser');
|
|
|
|
|
|
|
|
if (drawAudienceLasers === false) {
|
|
|
|
|
|
|
|
// Laser is disabled, will be enabled
|
|
|
|
laser.text('Audience laser is enabled');
|
|
|
|
laser.removeClass('btn-default').addClass('btn-primary');
|
|
|
|
drawAudienceLasers = true;
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
laser.text('Audience laser is disabled');
|
|
|
|
laser.removeClass('btn-primary').addClass('btn-default');
|
|
|
|
drawAudienceLasers = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
socket.emit('viewer-laser', filename, drawAudienceLasers);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
sio.clearCounter = function() { $('#counter').val(''); };
|
|
|
|
sio.nextSlide = function() { changeSlide(currentPage + 1); };
|
|
|
|
sio.previousSlide = function() { changeSlide(currentPage - 1); };
|
|
|
|
sio.firstSlide = function() { changeSlide(1); };
|
|
|
|
sio.lastSlide = function() { changeSlide(pdf.pdfInfo.numPages); };
|
|
|
|
|
|
|
|
sio.syncAudience = updateAudience;
|
|
|
|
sio.update = updateUI;
|
|
|
|
|
|
|
|
$(window).resize(updateUI);
|
|
|
|
|
|
|
|
return sio;
|
|
|
|
|
|
|
|
})(); });
|