123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- /**
- * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
- *
- * Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
- *
- * This program is free software; you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation; either version 3.0 of the License, or (at your option) any later
- * version.
- *
- * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License along
- * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-
- // - - - START OF GLOBAL VARIABLES - - - //
- "use strict";
-
- function getUrlParameters() {
- var map = {};
- window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) { map[key] = value; });
- return map;
- }
-
- // - - - END OF GLOBAL VARIABLES - - - //
-
- // - - - START OF JAVASCRIPT FUNCTIONS - - - //
-
- // Draw the cursor at a specific point
- function draw(x, y) {
- cursorStyle = document.getElementById("cursor").style;
- var slide = document.getElementById("slide");
- var obj = $("#slide > object");
- var scaledX = parseInt(x, 10) * (parseInt(obj.attr("width"), 10) / 800);
- var scaledY = parseInt(y, 10) * (parseInt(obj.attr("height"), 10) / 600);
-
- //move to the next place
- var leftValue = parseInt(slide.offsetLeft, 10) + parseInt(scaledX, 10)
- var topValue = parseInt(slide.offsetTop, 10) + parseInt(scaledY, 10)
- if (leftValue < 0){
- leftValue = 0
- }
- if (topValue < 0){
- topValue = 0
- }
- cursorStyle.left = leftValue + "px";
- cursorStyle.top = topValue + "px";
-
- }
-
-
- // Shows or hides the cursor object depending on true/false parameter passed.
- function showCursor(boolVal) {
- cursorStyle = document.getElementById("cursor").style;
- if(boolVal === false) {
- cursorStyle.height = "0px";
- cursorStyle.width = "0px";
- }
- else {
- cursorStyle.height = "10px";
- cursorStyle.width = "10px";
- }
- }
-
- function setViewBox(val) {
- if(svgobj.contentDocument) svgfile = svgobj.contentDocument.getElementById("svgfile");
- else svgfile = svgobj.getSVGDocument('svgfile').getElementById("svgfile");
- svgfile.setAttribute('viewBox', val);
- }
-
- function setCursor(val) {
- draw(val[0], val[1]);
- }
-
- function getImageAtTime(time) {
- var curr_t = parseFloat(time);
- var key;
- for (key in imageAtTime) {
- if(imageAtTime.hasOwnProperty(key)) {
- var arry = key.split(",");
- if ((parseFloat(arry[0]) <= curr_t) && (parseFloat(arry[1]) >= curr_t)) {
- return imageAtTime[key];
- }
- }
- }
- }
-
- function getViewboxAtTime(time) {
- var curr_t = parseFloat(time);
- var key;
- for (key in vboxValues) {
- if(vboxValues.hasOwnProperty(key)) {
- var arry = key.split(",");
- if(arry[1] == "end") {
- return vboxValues[key];
- }
- else if ((parseFloat(arry[0]) <= curr_t) && (parseFloat(arry[1]) >= curr_t)) {
- return vboxValues[key];
- }
- }
- }
- }
-
- function getCursorAtTime(time) {
- var coords = cursorValues[time];
- if(coords) return coords.split(' ');
- }
-
- function removeSlideChangeAttribute() {
- $('#video').removeAttr('slide-change');
- Popcorn('#video').unlisten(Popcorn.play, 'removeSlideChangeAttribute');
- }
-
- // - - - END OF JAVASCRIPT FUNCTIONS - - - //
-
- function runPopcorn() {
- if(svgobj.contentDocument) svgfile = svgobj.contentDocument.getElementById("svgfile");
- else svgfile = svgobj.getSVGDocument('svgfile');
-
- //making the object for requesting the read of the XML files.
- if (window.XMLHttpRequest) {
- // code for IE7+, Firefox, Chrome, Opera, Safari
- var xmlhttp = new XMLHttpRequest();
- } else {
- // code for IE6, IE5
- var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
- }
-
- // PROCESS SHAPES.SVG (in XML format).
- xmlhttp.open("GET", shapes_svg, false);
- xmlhttp.send();
- var xmlDoc = xmlhttp.responseXML;
- //getting all the event tags
- var shapeelements = xmlDoc.getElementsByTagName("svg");
-
- //get the array of values for the first shape (getDataPoints(0) is the first shape).
- var array = $(shapeelements[0]).find("g").filter(function(){ //get all the lines from the svg file
- return $(this).attr('class') == 'shape';
- });
- var images = shapeelements[0].getElementsByTagName("image");
-
- //fill the times array with the times of the svg images.
- for (var j = 0; j < array.length; j++) {
- times[j] = array[j].getAttribute("id").substr(4);
- }
-
- var times_length = times.length; //get the length of the times array.
-
- for(var m = 0; m < images.length; m++) {
- len = images[m].getAttribute("in").split(" ").length;
- for(var n = 0; n < len; n++) {
- imageAtTime[[images[m].getAttribute("in").split(" ")[n], images[m].getAttribute("out").split(" ")[n]]] = images[m].getAttribute("id");
- }
-
- // the logo at the start has no text attribute
- if (images[m].getAttribute("text")) {
- var txtFile = false;
- if (window.XMLHttpRequest) {
- // code for IE7+, Firefox, Chrome, Opera, Safari
- txtFile = new XMLHttpRequest();
- } else {
- // code for IE6, IE5
- txtFile = new ActiveXObject("Microsoft.XMLHTTP");
- }
- var imgid = images[m].getAttribute("id"); //have to save the value because images array might go out of scope
- txtFile.open("GET", url + "/" + images[m].getAttribute("text"), false);
- txtFile.onreadystatechange = function() {
- if (txtFile.readyState === 4) {
- if (txtFile.status === 200) {
- slidePlainText[imgid] = $('<div/>').text(txtFile.responseText).html();
- console.log("Text file read " + imgid);
- }
- }
- };
- txtFile.send(null);
- }
- }
-
- // PROCESS PANZOOMS.XML
- xmlhttp.open("GET", events_xml, false);
- xmlhttp.send();
- xmlDoc = xmlhttp.responseXML;
- //getting all the event tags
- var panelements = xmlDoc.getElementsByTagName("recording");
- var panZoomArray = panelements[0].getElementsByTagName("event");
- viewBoxes = xmlDoc.getElementsByTagName("viewBox");
-
- var pzlen = panZoomArray.length;
- var second_val;
- //fill the times array with the times of the svg images.
- for (var k = 0;k < pzlen; k++) {
- if(panZoomArray[k+1] == undefined) {
- second_val = "end";
- }
- else second_val = panZoomArray[k+1].getAttribute("timestamp");
- vboxValues[[panZoomArray[k].getAttribute("timestamp"), second_val]] = viewBoxes[k].childNodes[0].data;
- }
-
-
- // PROCESS CURSOR.XML
- xmlhttp.open("GET", cursor_xml, false);
- xmlhttp.send();
- xmlDoc = xmlhttp.responseXML;
- //getting all the event tags
- var curelements = xmlDoc.getElementsByTagName("recording");
- var cursorArray = curelements[0].getElementsByTagName("event");
- coords = xmlDoc.getElementsByTagName("cursor");
-
- var clen = cursorArray.length;
- //fill the times array with the times of the svg images.
- if(cursorArray.length != 0) cursorValues["0"] = "0 0";
- for (var m = 0; m < clen; m++) {
- cursorValues[cursorArray[m].getAttribute("timestamp")] = coords[m].childNodes[0].data;
- }
-
- svgobj.style.left = document.getElementById("slide").offsetLeft + "px";
- svgobj.style.top = "8px";
- var next_shape;
- var shape;
- for (var i = 0, len = times_length; i < len-1; i++) { //iterate through all the shapes and pick out the main ones
- var time = times[i];
- shape = svgobj.contentDocument.getElementById("draw" + time).getAttribute("shape");
- next_shape = svgobj.contentDocument.getElementById("draw" + times[i+1]).getAttribute("shape");
-
- if(shape !== next_shape) {
- main_shapes_times[main_shapes_times.length] = time;
- }
- }
- if(times.length !== 0) {
- main_shapes_times[main_shapes_times.length] = times[times.length-1]; //put last value into this array always!
- }
-
- var p = new Popcorn("#video");
- //update 60x / second the position of the next value.
- p.code({
- start: 1, // start time
- end: p.duration(),
- onFrame: function(options) {
- if(!((p.paused() === true) && (p.seeking() === false))) {
- var t = p.currentTime().toFixed(1); //get the time and round to 1 decimal place
-
- if(svgobj.contentDocument) current_shape = svgobj.contentDocument.getElementById("draw" + t);
- else current_shape = svgobj.getSVGDocument('svgfile').getElementById("draw" + t);
-
- if(current_shape !== null) { //if there is actually a new shape to be displayed
- current_shape = current_shape.getAttribute("shape"); //get actual shape tag for this specific time of playback
- }
- //redraw everything (only way to make everything elegant)
- for (var i = 0, len = times_length; i < len; i++) {
- var time_s = times[i];
- var time_f = parseFloat(time_s);
-
- if(svgobj.contentDocument) shape = svgobj.contentDocument.getElementById("draw" + time_s);
- else shape = svgobj.getSVGDocument('svgfile').getElementById("draw" + time_s);
-
- var shape_i = shape.getAttribute("shape");
- if (time_f < t) {
- if(shape_i === current_shape) { //currently drawing the same shape so don't draw the older steps
- shape.style.visibility = "hidden"; //hide older steps to shape
- }
- else if(main_shapes_times.indexOf(time_s) !== -1) { //as long as it is a main shape, it can be drawn... no intermediate steps.
- if(parseFloat(shape.getAttribute("undo")) === -1) { //As long as the undo event hasn't happened yet...
- shape.style.visibility = "visible";
- }
- else if (parseFloat(shape.getAttribute("undo")) > t) {
- shape.style.visibility = "visible";
- }
- else {
- shape.style.visibility = "hidden";
- }
- }
- }
- else if(time_s === t) { //for the shape with the time specific to the current time
- shape.style.visibility = "visible";
- }
- else { //for shapes that shouldn't be drawn yet (larger time than current time), don't draw them.
- shape.style.visibility = "hidden";
- }
- }
-
- var next_image = getImageAtTime(t); //fetch the name of the image at this time.
- var imageXOffset = 0;
- var imageYOffset = 0;
- if((current_image !== next_image) && (next_image !== undefined)){ //changing slide image
- if(svgobj.contentDocument) {
- svgobj.contentDocument.getElementById(current_image).style.visibility = "hidden";
- var ni = svgobj.contentDocument.getElementById(next_image);
- }
- else {
- svgobj.getSVGDocument('svgfile').getElementById(current_image).style.visibility = "hidden";
- var ni = svgobj.getSVGDocument('svgfile').getElementById(next_image);
- }
- document.getElementById("slideText").innerHTML = ""; //destroy old plain text
-
- ni.style.visibility = "visible";
- document.getElementById("slideText").innerHTML = slidePlainText[next_image] + next_image; //set new plain text
-
- if ($("#accEnabled").is(':checked')) {
- //pause the playback on slide change
- p.pause();
- $('#video').attr('slide-change', 'slide-change');
- p.listen(Popcorn.play, removeSlideChangeAttribute);
- }
-
- var num_current = current_image.substr(5);
- var num_next = next_image.substr(5);
-
- if(svgobj.contentDocument) currentcanvas = svgobj.contentDocument.getElementById("canvas" + num_current);
- else currentcanvas = svgobj.getSVGDocument('svgfile').getElementById("canvas" + num_current);
-
- if(currentcanvas !== null) {
- currentcanvas.setAttribute("display", "none");
- }
-
- if(svgobj.contentDocument) nextcanvas = svgobj.contentDocument.getElementById("canvas" + num_next);
- else nextcanvas = svgobj.getSVGDocument('svgfile').getElementById("canvas" + num_next);
-
- if((nextcanvas !== undefined) && (nextcanvas != null)) {
- nextcanvas.setAttribute("display", "");
- }
- current_image = next_image;
- }
-
- if(svgobj.contentDocument) var thisimg = svgobj.contentDocument.getElementById(current_image);
- else var thisimg = svgobj.getSVGDocument('svgfile').getElementById(current_image);
-
- var offsets = thisimg.getBoundingClientRect();
- // Offsets divided by 4. By 2 because of the padding and by 2 again because 800x600 is half 1600x1200
- imageXOffset = (1600 - parseInt(thisimg.getAttribute("width"), 10))/4;
- imageYOffset = (1200 - parseInt(thisimg.getAttribute("height"), 10))/4;
-
-
- var vboxVal = getViewboxAtTime(t);
- if(vboxVal !== undefined) {
- setViewBox(vboxVal);
- }
-
- var cursorVal = getCursorAtTime(t);
- var cursor_on = false;
- if(cursorVal != null) {
- if(!cursor_on) {
- document.getElementById("cursor").style.visibility = 'visible'; //make visible
- cursor_on = true;
- }
- setCursor([parseFloat(cursorVal[0]) + imageXOffset - 6, parseFloat(cursorVal[1]) + imageYOffset - 6]); //-6 is for radius of cursor offset
- }
- }
- }
- });
- };
-
- function defineStartTime() {
- if (params.t === undefined)
- return 1;
-
- var extractNumber = /\d+/g;
- var extractUnit = /\D+/g;
- var temp_start_time = 0;
-
- while (true) {
- var param1 = extractUnit.exec(params.t);
- var param2 = extractNumber.exec(params.t);
- if (param1 == null || param2 == null)
- break;
-
- var unit = String(param1).toLowerCase();
- var value = parseInt(String(param2));
-
- if (unit == "h")
- value *= 3600;
- else if (unit == "m")
- value *= 60;
-
- temp_start_time += value;
- }
-
- console.log("Start time: " + temp_start_time);
- return temp_start_time;
- }
-
- var current_canvas = "canvas0";
- var current_image = "image0";
- var currentcanvas;
- var shape;
- var nextcanvas;
- var next_image;
- var next_pgid;
- var curr_pgid;
- var svgfile;
- //current time
- var t;
- var len;
- var current_shape;
- //coordinates for x and y for each second
- var panAndZoomTimes = [];
- var viewBoxes = [];
- var coords = [];
- var times = [];
- var clearTimes = [];
- var main_shapes_times = [];
- var vboxValues = {};
- var cursorValues = {};
- var imageAtTime = {};
- var slidePlainText = {}; //holds slide plain text for retrieval
- var cursorStyle;
-
- var params = getUrlParameters();
- var MEETINGID = params.meetingId;
- var url = "/presentation/" + MEETINGID;
- var shapes_svg = url + '/shapes.svg';
- var events_xml = url + '/panzooms.xml';
- var cursor_xml = url + '/cursor.xml';
-
- var svgobj = document.createElement('object');
- svgobj.setAttribute('data', shapes_svg);
- svgobj.setAttribute('height', '600px');
- svgobj.setAttribute('width', '800px');
- svgobj.addEventListener('load', runPopcorn, false);
-
- /**
- * we need an urgently refactor here
- * first the writing.js must be loaded, and then runPopcorn loads, but it loads
- * only after the svg file gets loaded, and the generation of thumbnails must
- * came after that because it needs the popcorn element to be created properly
- */
- svgobj.addEventListener('load', function() {
- generateThumbnails();
- var p = Popcorn("#video");
- p.on('loadeddata', function() {
- p.currentTime(defineStartTime());
- });
-
- // Sometimes media has already loaded before our loadeddata listener is
- // attached. If the media is already past the loadeddata stage then we
- // trigger the event manually ourselves
- if ($('#video')[0].readyState > 0) {
- p.emit('loadeddata');
- }
- }, false);
-
-
- document.getElementById('slide').appendChild(svgobj);
-
- window.onresize = function(event) {
- svgobj.style.left = document.getElementById("slide").offsetLeft + "px";
- svgobj.style.top = "8px";
- };
|