diff --git a/guacamole/src/main/webapp/client.xhtml b/guacamole/src/main/webapp/client.xhtml index 93a12f70f..f9ca5a569 100644 --- a/guacamole/src/main/webapp/client.xhtml +++ b/guacamole/src/main/webapp/client.xhtml @@ -127,12 +127,12 @@ + "&height=" + optimal_height; // Add audio mimetypes to connect_string - GuacamoleUI.supportedAudio.forEach(function(mimetype) { + GuacUI.Audio.supported.forEach(function(mimetype) { connect_string += "&audio=" + encodeURIComponent(mimetype); }); // Add video mimetypes to connect_string - GuacamoleUI.supportedVideo.forEach(function(mimetype) { + GuacUI.Video.supported.forEach(function(mimetype) { connect_string += "&video=" + encodeURIComponent(mimetype); }); diff --git a/guacamole/src/main/webapp/scripts/guac-ui.js b/guacamole/src/main/webapp/scripts/guac-ui.js index b07bda83a..58c0d6741 100644 --- a/guacamole/src/main/webapp/scripts/guac-ui.js +++ b/guacamole/src/main/webapp/scripts/guac-ui.js @@ -31,12 +31,168 @@ GuacUI.createElement = function(tagname, classname) { return new_element; }; +/** + * Creates a new element having the given tagname, CSS class, and specified + * parent element. + */ GuacUI.createChildElement = function(parent, tagname, classname) { var element = GuacUI.createElement(tagname, classname); parent.appendChild(element); return element; }; +/** + * Adds the given CSS class to the given element. + */ +GuacUI.addClass = function(element, classname) { + + // If supported, use native classlist for addClass() + if (Node.classlist) + element.classList.add(classname); + + // Otherwise, simply add new class via string manipulation + else + element.className += " " + classname; + +}; + +/** + * Removes the given CSS class from the given element. + */ +GuacUI.removeClass = function(element, classname) { + + // If supported, use native classlist for removeClass() + if (Node.classlist) + element.classList.remove(classname); + + // Otherwise, remove class via string manipulation + else { + + // Filter out classes with given name + element.className = element.className.replace(/([^ ]+)[ ]*/g, + function(match, testClassname, spaces, offset, string) { + + // If same class, remove + if (testClassname == classname) + return ""; + + // Otherwise, allow + return match; + + } + ); + + } // end if no classlist support + +}; + +/** + * Object describing the UI's level of audio support. If the user has request + * that audio be disabled, this object will pretend that audio is not + * supported. + */ +GuacUI.Audio = new (function() { + + var codecs = [ + 'audio/ogg; codecs="vorbis"', + 'audio/mp4; codecs="mp4a.40.5"', + 'audio/mpeg; codecs="mp3"', + 'audio/webm; codecs="vorbis"', + 'audio/wav; codecs=1' + ]; + + var probably_supported = []; + var maybe_supported = []; + + /** + * Array of all supported audio mimetypes, ordered by liklihood of + * working. + */ + this.supported = []; + + // If sound disabled, we're done now. + if (GuacamoleUI.sessionState.getProperty("disable-sound")) + return; + + // Build array of supported audio formats + codecs.forEach(function(mimetype) { + + var audio = new Audio(); + var support_level = audio.canPlayType(mimetype); + + // Trim semicolon and trailer + var semicolon = mimetype.indexOf(";"); + if (semicolon != -1) + mimetype = mimetype.substring(0, semicolon); + + // Partition by probably/maybe + if (support_level == "probably") + probably_supported.push(mimetype); + else if (support_level == "maybe") + maybe_supported.push(mimetype); + + }); + + // Add probably supported types first + Array.prototype.push.apply( + this.supported, probably_supported); + + // Prioritize "maybe" supported types second + Array.prototype.push.apply( + this.supported, maybe_supported); + +})(); + +/** + * Object describing the UI's level of video support. + */ +GuacUI.Video = new (function() { + + var codecs = [ + 'video/ogg; codecs="theora, vorbis"', + 'video/mp4; codecs="avc1.4D401E, mp4a.40.5"', + 'video/webm; codecs="vp8.0, vorbis"' + ]; + + var probably_supported = []; + var maybe_supported = []; + + /** + * Array of all supported video mimetypes, ordered by liklihood of + * working. + */ + this.supported = []; + + // Build array of supported audio formats + codecs.forEach(function(mimetype) { + + var video = document.createElement("video"); + var support_level = video.canPlayType(mimetype); + + // Trim semicolon and trailer + var semicolon = mimetype.indexOf(";"); + if (semicolon != -1) + mimetype = mimetype.substring(0, semicolon); + + // Partition by probably/maybe + if (support_level == "probably") + probably_supported.push(mimetype); + else if (support_level == "maybe") + maybe_supported.push(mimetype); + + }); + + // Add probably supported types first + Array.prototype.push.apply( + this.supported, probably_supported); + + // Prioritize "maybe" supported types second + Array.prototype.push.apply( + this.supported, maybe_supported); + +})(); + + /** * Central registry of all components for all states. */ diff --git a/guacamole/src/main/webapp/scripts/interface.js b/guacamole/src/main/webapp/scripts/interface.js index 7fa22ccf6..de3a891ec 100644 --- a/guacamole/src/main/webapp/scripts/interface.js +++ b/guacamole/src/main/webapp/scripts/interface.js @@ -45,77 +45,21 @@ var GuacamoleUI = { }; -/** - * Array of all supported audio mimetypes, populated when this script is - * loaded. - */ -GuacamoleUI.supportedAudio = []; - -/** - * Array of all supported video mimetypes, populated when this script is - * loaded. - */ -GuacamoleUI.supportedVideo = []; - -// If Node.classList is supported, implement addClass/removeClass using that -if (Node.classList) { - - GuacamoleUI.addClass = function(element, classname) { - element.classList.add(classname); - }; - - GuacamoleUI.removeClass = function(element, classname) { - element.classList.remove(classname); - }; - -} - -// Otherwise, implement own -else { - - GuacamoleUI.addClass = function(element, classname) { - - // Simply add new class - element.className += " " + classname; - - }; - - GuacamoleUI.removeClass = function(element, classname) { - - // Filter out classes with given name - element.className = element.className.replace(/([^ ]+)[ ]*/g, - function(match, testClassname, spaces, offset, string) { - - // If same class, remove - if (testClassname == classname) - return ""; - - // Otherwise, allow - return match; - - } - ); - - }; - -} - - GuacamoleUI.hideStatus = function() { - GuacamoleUI.removeClass(document.body, "guac-error"); + GuacUI.removeClass(document.body, "guac-error"); GuacamoleUI.containers.state.style.visibility = "hidden"; GuacamoleUI.display.style.opacity = "1"; }; GuacamoleUI.showStatus = function(text) { - GuacamoleUI.removeClass(document.body, "guac-error"); + GuacUI.removeClass(document.body, "guac-error"); GuacamoleUI.containers.state.style.visibility = "visible"; GuacamoleUI.state.textContent = text; GuacamoleUI.display.style.opacity = "1"; }; GuacamoleUI.showError = function(error) { - GuacamoleUI.addClass(document.body, "guac-error"); + GuacUI.addClass(document.body, "guac-error"); GuacamoleUI.state.textContent = error; GuacamoleUI.display.style.opacity = "0.1"; }; @@ -125,73 +69,6 @@ GuacamoleUI.buttons.reconnect.onclick = function() { window.location.reload(); }; -// Query audio support -if (!GuacamoleUI.sessionState.getProperty("disable-sound")) - (function () { - var probably_supported = []; - var maybe_supported = []; - - // Build array of supported audio formats - [ - 'audio/ogg; codecs="vorbis"', - 'audio/mp4; codecs="mp4a.40.5"', - 'audio/mpeg; codecs="mp3"', - 'audio/webm; codecs="vorbis"', - 'audio/wav; codecs=1' - ].forEach(function(mimetype) { - - var audio = new Audio(); - var support_level = audio.canPlayType(mimetype); - - // Trim semicolon and trailer - var semicolon = mimetype.indexOf(";"); - if (semicolon != -1) - mimetype = mimetype.substring(0, semicolon); - - // Partition by probably/maybe - if (support_level == "probably") - probably_supported.push(mimetype); - else if (support_level == "maybe") - maybe_supported.push(mimetype); - - }); - - Array.prototype.push.apply(GuacamoleUI.supportedAudio, probably_supported); - Array.prototype.push.apply(GuacamoleUI.supportedAudio, maybe_supported); - })(); - -// Query video support -(function () { - var probably_supported = []; - var maybe_supported = []; - - // Build array of supported video formats - [ - 'video/ogg; codecs="theora, vorbis"', - 'video/mp4; codecs="avc1.4D401E, mp4a.40.5"', - 'video/webm; codecs="vp8.0, vorbis"' - ].forEach(function(mimetype) { - - var video = document.createElement("video"); - var support_level = video.canPlayType(mimetype); - - // Trim semicolon and trailer - var semicolon = mimetype.indexOf(";"); - if (semicolon != -1) - mimetype = mimetype.substring(0, semicolon); - - // Partition by probably/maybe - if (support_level == "probably") - probably_supported.push(mimetype); - else if (support_level == "maybe") - maybe_supported.push(mimetype); - - }); - - Array.prototype.push.apply(GuacamoleUI.supportedVideo, probably_supported); - Array.prototype.push.apply(GuacamoleUI.supportedVideo, maybe_supported); -})(); - // Tie UI events / behavior to a specific Guacamole client GuacamoleUI.attach = function(guac) {