guacamole-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jmuehl...@apache.org
Subject [32/52] [abbrv] [partial] incubator-guacamole-website git commit: Add 0.9.10-incubating documentation.
Date Sat, 19 Nov 2016 00:43:42 GMT
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-website/blob/5d2c3c74/doc/0.9.10-incubating/guacamole-common-js/OnScreenKeyboard.js.html
----------------------------------------------------------------------
diff --git a/doc/0.9.10-incubating/guacamole-common-js/OnScreenKeyboard.js.html b/doc/0.9.10-incubating/guacamole-common-js/OnScreenKeyboard.js.html
new file mode 100644
index 0000000..793b2ee
--- /dev/null
+++ b/doc/0.9.10-incubating/guacamole-common-js/OnScreenKeyboard.js.html
@@ -0,0 +1,994 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: OnScreenKeyboard.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: OnScreenKeyboard.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 Guacamole = Guacamole || {};
+
+/**
+ * Dynamic on-screen keyboard. Given the layout object for an on-screen
+ * keyboard, this object will construct a clickable on-screen keyboard with its
+ * own key events.
+ *
+ * @constructor
+ * @param {Guacamole.OnScreenKeyboard.Layout} layout
+ *     The layout of the on-screen keyboard to display.
+ */
+Guacamole.OnScreenKeyboard = function(layout) {
+
+    /**
+     * Reference to this Guacamole.OnScreenKeyboard.
+     *
+     * @private
+     * @type {Guacamole.OnScreenKeyboard}
+     */
+    var osk = this;
+
+    /**
+     * Map of currently-set modifiers to the keysym associated with their
+     * original press. When the modifier is cleared, this keysym must be
+     * released.
+     *
+     * @private
+     * @type {Object.&lt;String, Number>}
+     */
+    var modifierKeysyms = {};
+
+    /**
+     * Map of all key names to their current pressed states. If a key is not
+     * pressed, it may not be in this map at all, but all pressed keys will
+     * have a corresponding mapping to true.
+     *
+     * @private
+     * @type {Object.&lt;String, Boolean>}
+     */
+    var pressed = {};
+
+    /**
+     * All scalable elements which are part of the on-screen keyboard. Each
+     * scalable element is carefully controlled to ensure the interface layout
+     * and sizing remains constant, even on browsers that would otherwise
+     * experience rounding error due to unit conversions.
+     *
+     * @private
+     * @type {ScaledElement[]}
+     */
+    var scaledElements = [];
+
+    /**
+     * Adds a CSS class to an element.
+     * 
+     * @private
+     * @function
+     * @param {Element} element
+     *     The element to add a class to.
+     *
+     * @param {String} classname
+     *     The name of the class to add.
+     */
+    var addClass = function addClass(element, classname) {
+
+        // If classList supported, use that
+        if (element.classList)
+            element.classList.add(classname);
+
+        // Otherwise, simply append the class
+        else
+            element.className += " " + classname;
+
+    };
+
+    /**
+     * Removes a CSS class from an element.
+     * 
+     * @private
+     * @function
+     * @param {Element} element
+     *     The element to remove a class from.
+     *
+     * @param {String} classname
+     *     The name of the class to remove.
+     */
+    var removeClass = function removeClass(element, classname) {
+
+        // If classList supported, use that
+        if (element.classList)
+            element.classList.remove(classname);
+
+        // Otherwise, manually filter out classes with given name
+        else {
+            element.className = element.className.replace(/([^ ]+)[ ]*/g,
+                function removeMatchingClasses(match, testClassname) {
+
+                    // If same class, remove
+                    if (testClassname === classname)
+                        return "";
+
+                    // Otherwise, allow
+                    return match;
+                    
+                }
+            );
+        }
+
+    };
+
+    /**
+     * Counter of mouse events to ignore. This decremented by mousemove, and
+     * while non-zero, mouse events will have no effect.
+     *
+     * @private
+     * @type {Number}
+     */
+    var ignoreMouse = 0;
+
+    /**
+     * Ignores all pending mouse events when touch events are the apparent
+     * source. Mouse events are ignored until at least touchMouseThreshold
+     * mouse events occur without corresponding touch events.
+     *
+     * @private
+     */
+    var ignorePendingMouseEvents = function ignorePendingMouseEvents() {
+        ignoreMouse = osk.touchMouseThreshold;
+    };
+
+    /**
+     * An element whose dimensions are maintained according to an arbitrary
+     * scale. The conversion factor for these arbitrary units to pixels is
+     * provided later via a call to scale().
+     *
+     * @private
+     * @constructor
+     * @param {Element} element
+     *     The element whose scale should be maintained.
+     *
+     * @param {Number} width
+     *     The width of the element, in arbitrary units, relative to other
+     *     ScaledElements.
+     *
+     * @param {Number} height
+     *     The height of the element, in arbitrary units, relative to other
+     *     ScaledElements.
+     *     
+     * @param {Boolean} [scaleFont=false]
+     *     Whether the line height and font size should be scaled as well.
+     */
+    var ScaledElement = function ScaledElement(element, width, height, scaleFont) {
+
+        /**
+         * The width of this ScaledElement, in arbitrary units, relative to
+         * other ScaledElements.
+         *
+         * @type {Number}
+         */
+         this.width = width;
+
+        /**
+         * The height of this ScaledElement, in arbitrary units, relative to
+         * other ScaledElements.
+         *
+         * @type {Number}
+         */
+         this.height = height;
+ 
+        /**
+         * Resizes the associated element, updating its dimensions according to
+         * the given pixels per unit.
+         *
+         * @param {Number} pixels
+         *     The number of pixels to assign per arbitrary unit.
+         */
+        this.scale = function(pixels) {
+
+            // Scale element width/height
+            element.style.width  = (width  * pixels) + "px";
+            element.style.height = (height * pixels) + "px";
+
+            // Scale font, if requested
+            if (scaleFont) {
+                element.style.lineHeight = (height * pixels) + "px";
+                element.style.fontSize   = pixels + "px";
+            }
+
+        };
+
+    };
+
+    /**
+     * Returns whether all modifiers having the given names are currently
+     * active.
+     *
+     * @private
+     * @param {String[]} names
+     *     The names of all modifiers to test.
+     *
+     * @returns {Boolean}
+     *     true if all specified modifiers are pressed, false otherwise.
+     */
+    var modifiersPressed = function modifiersPressed(names) {
+
+        // If any required modifiers are not pressed, return false
+        for (var i=0; i &lt; names.length; i++) {
+
+            // Test whether current modifier is pressed
+            var name = names[i];
+            if (!(name in modifierKeysyms))
+                return false;
+
+        }
+
+        // Otherwise, all required modifiers are pressed
+        return true;
+
+    };
+
+    /**
+     * Returns the single matching Key object associated with the key of the
+     * given name, where that Key object's requirements (such as pressed
+     * modifiers) are all currently satisfied.
+     *
+     * @private
+     * @param {String} keyName
+     *     The name of the key to retrieve.
+     *
+     * @returns {Guacamole.OnScreenKeyboard.Key}
+     *     The Key object associated with the given name, where that object's
+     *     requirements are all currently satisfied, or null if no such Key
+     *     can be found.
+     */
+    var getActiveKey = function getActiveKey(keyName) {
+
+        // Get key array for given name
+        var keys = osk.keys[keyName];
+        if (!keys)
+            return null;
+
+        // Find last matching key
+        for (var i = keys.length - 1; i >= 0; i--) {
+
+            // Get candidate key
+            var candidate = keys[i];
+
+            // If all required modifiers are pressed, use that key
+            if (modifiersPressed(candidate.requires))
+                return candidate;
+
+        }
+
+        // No valid key
+        return null;
+
+    };
+
+    /**
+     * Presses the key having the given name, updating the associated key
+     * element with the "guac-keyboard-pressed" CSS class. If the key is
+     * already pressed, this function has no effect.
+     *
+     * @private
+     * @param {String} keyName
+     *     The name of the key to press.
+     *
+     * @param {String} keyElement
+     *     The element associated with the given key.
+     */
+    var press = function press(keyName, keyElement) {
+
+        // Press key if not yet pressed
+        if (!pressed[keyName]) {
+
+            addClass(keyElement, "guac-keyboard-pressed");
+
+            // Get current key based on modifier state
+            var key = getActiveKey(keyName);
+
+            // Update modifier state
+            if (key.modifier) {
+
+                // Construct classname for modifier
+                var modifierClass = "guac-keyboard-modifier-" + getCSSName(key.modifier);
+
+                // Retrieve originally-pressed keysym, if modifier was already pressed
+                var originalKeysym = modifierKeysyms[key.modifier];
+
+                // Activate modifier if not pressed
+                if (!originalKeysym) {
+                    
+                    addClass(keyboard, modifierClass);
+                    modifierKeysyms[key.modifier] = key.keysym;
+                    
+                    // Send key event
+                    if (osk.onkeydown)
+                        osk.onkeydown(key.keysym);
+
+                }
+
+                // Deactivate if not pressed
+                else {
+
+                    removeClass(keyboard, modifierClass);
+                    delete modifierKeysyms[key.modifier];
+                    
+                    // Send key event
+                    if (osk.onkeyup)
+                        osk.onkeyup(originalKeysym);
+
+                }
+
+            }
+
+            // If not modifier, send key event now
+            else if (osk.onkeydown)
+                osk.onkeydown(key.keysym);
+
+            // Mark key as pressed
+            pressed[keyName] = true;
+
+        }
+
+    };
+
+    /**
+     * Releases the key having the given name, removing the
+     * "guac-keyboard-pressed" CSS class from the associated element. If the
+     * key is already released, this function has no effect.
+     *
+     * @private
+     * @param {String} keyName
+     *     The name of the key to release.
+     *
+     * @param {String} keyElement
+     *     The element associated with the given key.
+     */
+    var release = function release(keyName, keyElement) {
+
+        // Release key if currently pressed
+        if (pressed[keyName]) {
+
+            removeClass(keyElement, "guac-keyboard-pressed");
+
+            // Get current key based on modifier state
+            var key = getActiveKey(keyName);
+
+            // Send key event if not a modifier key
+            if (!key.modifier &amp;&amp; osk.onkeyup)
+                osk.onkeyup(key.keysym);
+
+            // Mark key as released
+            pressed[keyName] = false;
+
+        }
+
+    };
+
+    // Create keyboard
+    var keyboard = document.createElement("div");
+    keyboard.className = "guac-keyboard";
+
+    // Do not allow selection or mouse movement to propagate/register.
+    keyboard.onselectstart =
+    keyboard.onmousemove   =
+    keyboard.onmouseup     =
+    keyboard.onmousedown   = function handleMouseEvents(e) {
+
+        // If ignoring events, decrement counter
+        if (ignoreMouse)
+            ignoreMouse--;
+
+        e.stopPropagation();
+        return false;
+
+    };
+
+    /**
+     * The number of mousemove events to require before re-enabling mouse
+     * event handling after receiving a touch event.
+     *
+     * @type {Number}
+     */
+    this.touchMouseThreshold = 3;
+
+    /**
+     * Fired whenever the user presses a key on this Guacamole.OnScreenKeyboard.
+     * 
+     * @event
+     * @param {Number} keysym The keysym of the key being pressed.
+     */
+    this.onkeydown = null;
+
+    /**
+     * Fired whenever the user releases a key on this Guacamole.OnScreenKeyboard.
+     * 
+     * @event
+     * @param {Number} keysym The keysym of the key being released.
+     */
+    this.onkeyup = null;
+
+    /**
+     * The keyboard layout provided at time of construction.
+     *
+     * @type {Guacamole.OnScreenKeyboard.Layout}
+     */
+    this.layout = new Guacamole.OnScreenKeyboard.Layout(layout);
+
+    /**
+     * Returns the element containing the entire on-screen keyboard.
+     * @returns {Element} The element containing the entire on-screen keyboard.
+     */
+    this.getElement = function() {
+        return keyboard;
+    };
+
+    /**
+     * Resizes all elements within this Guacamole.OnScreenKeyboard such that
+     * the width is close to but does not exceed the specified width. The
+     * height of the keyboard is determined based on the width.
+     * 
+     * @param {Number} width The width to resize this Guacamole.OnScreenKeyboard
+     *                       to, in pixels.
+     */
+    this.resize = function(width) {
+
+        // Get pixel size of a unit
+        var unit = Math.floor(width * 10 / osk.layout.width) / 10;
+
+        // Resize all scaled elements
+        for (var i=0; i&lt;scaledElements.length; i++) {
+            var scaledElement = scaledElements[i];
+            scaledElement.scale(unit);
+        }
+
+    };
+
+    /**
+     * Given the name of a key and its corresponding definition, which may be
+     * an array of keys objects, a number (keysym), a string (key title), or a
+     * single key object, returns an array of key objects, deriving any missing
+     * properties as needed, and ensuring the key name is defined.
+     *
+     * @private
+     * @param {String} name
+     *     The name of the key being coerced into an array of Key objects.
+     *
+     * @param {Number|String|Guacamole.OnScreenKeyboard.Key|Guacamole.OnScreenKeyboard.Key[]} object
+     *     The object defining the behavior of the key having the given name,
+     *     which may be the title of the key (a string), the keysym (a number),
+     *     a single Key object, or an array of Key objects.
+     *     
+     * @returns {Guacamole.OnScreenKeyboard.Key[]}
+     *     An array of all keys associated with the given name.
+     */
+    var asKeyArray = function asKeyArray(name, object) {
+
+        // If already an array, just coerce into a true Key[] 
+        if (object instanceof Array) {
+            var keys = [];
+            for (var i=0; i &lt; object.length; i++) {
+                keys.push(new Guacamole.OnScreenKeyboard.Key(object[i], name));
+            }
+            return keys;
+        }
+
+        // Derive key object from keysym if that's all we have
+        if (typeof object === 'number') {
+            return [new Guacamole.OnScreenKeyboard.Key({
+                name   : name,
+                keysym : object
+            })];
+        }
+
+        // Derive key object from title if that's all we have
+        if (typeof object === 'string') {
+            return [new Guacamole.OnScreenKeyboard.Key({
+                name  : name,
+                title : object
+            })];
+        }
+
+        // Otherwise, assume it's already a key object, just not an array
+        return [new Guacamole.OnScreenKeyboard.Key(object, name)];
+
+    };
+
+    /**
+     * Converts the rather forgiving key mapping allowed by
+     * Guacamole.OnScreenKeyboard.Layout into a rigorous mapping of key name
+     * to key definition, where the key definition is always an array of Key
+     * objects.
+     *
+     * @private
+     * @param {Object.&lt;String, Number|String|Guacamole.OnScreenKeyboard.Key|Guacamole.OnScreenKeyboard.Key[]>} keys
+     *     A mapping of key name to key definition, where the key definition is
+     *     the title of the key (a string), the keysym (a number), a single
+     *     Key object, or an array of Key objects.
+     *
+     * @returns {Object.&lt;String, Guacamole.OnScreenKeyboard.Key[]>}
+     *     A more-predictable mapping of key name to key definition, where the
+     *     key definition is always simply an array of Key objects.
+     */
+    var getKeys = function getKeys(keys) {
+
+        var keyArrays = {};
+
+        // Coerce all keys into individual key arrays
+        for (var name in layout.keys) {
+            keyArrays[name] = asKeyArray(name, keys[name]);
+        }
+
+        return keyArrays;
+
+    };
+
+    /**
+     * Map of all key names to their corresponding set of keys. Each key name
+     * may correspond to multiple keys due to the effect of modifiers.
+     *
+     * @type {Object.&lt;String, Guacamole.OnScreenKeyboard.Key[]>}
+     */
+    this.keys = getKeys(layout.keys);
+
+    /**
+     * Given an arbitrary string representing the name of some component of the
+     * on-screen keyboard, returns a string formatted for use as a CSS class
+     * name. The result will be lowercase. Word boundaries previously denoted
+     * by CamelCase will be replaced by individual hyphens, as will all
+     * contiguous non-alphanumeric characters.
+     *
+     * @private
+     * @param {String} name
+     *     An arbitrary string representing the name of some component of the
+     *     on-screen keyboard.
+     *
+     * @returns {String}
+     *     A string formatted for use as a CSS class name.
+     */
+    var getCSSName = function getCSSName(name) {
+
+        // Convert name from possibly-CamelCase to hyphenated lowercase
+        var cssName = name
+               .replace(/([a-z])([A-Z])/g, '$1-$2')
+               .replace(/[^A-Za-z0-9]+/g, '-')
+               .toLowerCase();
+
+        return cssName;
+
+    };
+
+    /**
+     * Appends DOM elements to the given element as dictated by the layout
+     * structure object provided. If a name is provided, an additional CSS
+     * class, prepended with "guac-keyboard-", will be added to the top-level
+     * element.
+     * 
+     * If the layout structure object is an array, all elements within that
+     * array will be recursively appended as children of a group, and the
+     * top-level element will be given the CSS class "guac-keyboard-group".
+     *
+     * If the layout structure object is an object, all properties within that
+     * object will be recursively appended as children of a group, and the
+     * top-level element will be given the CSS class "guac-keyboard-group". The
+     * name of each property will be applied as the name of each child object
+     * for the sake of CSS. Each property will be added in sorted order.
+     *
+     * If the layout structure object is a string, the key having that name
+     * will be appended. The key will be given the CSS class
+     * "guac-keyboard-key" and "guac-keyboard-key-NAME", where NAME is the name
+     * of the key. If the name of the key is a single character, this will
+     * first be transformed into the C-style hexadecimal literal for the
+     * Unicode codepoint of that character. For example, the key "A" would
+     * become "guac-keyboard-key-0x41".
+     * 
+     * If the layout structure object is a number, a gap of that size will be
+     * inserted. The gap will be given the CSS class "guac-keyboard-gap", and
+     * will be scaled according to the same size units as each key.
+     *
+     * @private
+     * @param {Element} element
+     *     The element to append elements to.
+     *
+     * @param {Array|Object|String|Number} object
+     *     The layout structure object to use when constructing the elements to
+     *     append.
+     *
+     * @param {String} [name]
+     *     The name of the top-level element being appended, if any.
+     */
+    var appendElements = function appendElements(element, object, name) {
+
+        var i;
+
+        // Create div which will become the group or key
+        var div = document.createElement('div');
+
+        // Add class based on name, if name given
+        if (name)
+            addClass(div, 'guac-keyboard-' + getCSSName(name));
+
+        // If an array, append each element
+        if (object instanceof Array) {
+
+            // Add group class
+            addClass(div, 'guac-keyboard-group');
+
+            // Append all elements of array
+            for (i=0; i &lt; object.length; i++)
+                appendElements(div, object[i]);
+
+        }
+
+        // If an object, append each property value
+        else if (object instanceof Object) {
+
+            // Add group class
+            addClass(div, 'guac-keyboard-group');
+
+            // Append all children, sorted by name
+            var names = Object.keys(object).sort();
+            for (i=0; i &lt; names.length; i++) {
+                var name = names[i];
+                appendElements(div, object[name], name);
+            }
+
+        }
+
+        // If a number, create as a gap 
+        else if (typeof object === 'number') {
+
+            // Add gap class
+            addClass(div, 'guac-keyboard-gap');
+
+            // Maintain scale
+            scaledElements.push(new ScaledElement(div, object, object));
+
+        }
+
+        // If a string, create as a key
+        else if (typeof object === 'string') {
+
+            // If key name is only one character, use codepoint for name
+            var keyName = object;
+            if (keyName.length === 1)
+                keyName = '0x' + keyName.charCodeAt(0).toString(16);
+
+            // Add key container class
+            addClass(div, 'guac-keyboard-key-container');
+
+            // Create key element which will contain all possible caps
+            var keyElement = document.createElement('div');
+            keyElement.className = 'guac-keyboard-key '
+                                 + 'guac-keyboard-key-' + getCSSName(keyName);
+
+            // Add all associated keys as caps within DOM
+            var keys = osk.keys[object];
+            if (keys) {
+                for (i=0; i &lt; keys.length; i++) {
+
+                    // Get current key
+                    var key = keys[i];
+
+                    // Create cap element for key
+                    var capElement = document.createElement('div');
+                    capElement.className   = 'guac-keyboard-cap';
+                    capElement.textContent = key.title;
+
+                    // Add classes for any requirements
+                    for (var j=0; j &lt; key.requires.length; j++) {
+                        var requirement = key.requires[j];
+                        addClass(capElement, 'guac-keyboard-requires-' + getCSSName(requirement));
+                        addClass(keyElement, 'guac-keyboard-uses-'     + getCSSName(requirement));
+                    }
+
+                    // Add cap to key within DOM
+                    keyElement.appendChild(capElement);
+
+                }
+            }
+
+            // Add key to DOM, maintain scale
+            div.appendChild(keyElement);
+            scaledElements.push(new ScaledElement(div, osk.layout.keyWidths[object] || 1, 1, true));
+
+            /**
+             * Handles a touch event which results in the pressing of an OSK
+             * key. Touch events will result in mouse events being ignored for
+             * touchMouseThreshold events.
+             *
+             * @private
+             * @param {TouchEvent} e
+             *     The touch event being handled.
+             */
+            var touchPress = function touchPress(e) {
+                e.preventDefault();
+                ignoreMouse = osk.touchMouseThreshold;
+                press(object, keyElement);
+            };
+
+            /**
+             * Handles a touch event which results in the release of an OSK
+             * key. Touch events will result in mouse events being ignored for
+             * touchMouseThreshold events.
+             *
+             * @private
+             * @param {TouchEvent} e
+             *     The touch event being handled.
+             */
+            var touchRelease = function touchRelease(e) {
+                e.preventDefault();
+                ignoreMouse = osk.touchMouseThreshold;
+                release(object, keyElement);
+            };
+
+            /**
+             * Handles a mouse event which results in the pressing of an OSK
+             * key. If mouse events are currently being ignored, this handler
+             * does nothing.
+             *
+             * @private
+             * @param {MouseEvent} e
+             *     The touch event being handled.
+             */
+            var mousePress = function mousePress(e) {
+                e.preventDefault();
+                if (ignoreMouse === 0)
+                    press(object, keyElement);
+            };
+
+            /**
+             * Handles a mouse event which results in the release of an OSK
+             * key. If mouse events are currently being ignored, this handler
+             * does nothing.
+             *
+             * @private
+             * @param {MouseEvent} e
+             *     The touch event being handled.
+             */
+            var mouseRelease = function mouseRelease(e) {
+                e.preventDefault();
+                if (ignoreMouse === 0)
+                    release(object, keyElement);
+            };
+
+            // Handle touch events on key
+            keyElement.addEventListener("touchstart", touchPress,   true);
+            keyElement.addEventListener("touchend",   touchRelease, true);
+
+            // Handle mouse events on key
+            keyElement.addEventListener("mousedown", mousePress,   true);
+            keyElement.addEventListener("mouseup",   mouseRelease, true);
+            keyElement.addEventListener("mouseout",  mouseRelease, true);
+
+        } // end if object is key name
+
+        // Add newly-created group/key
+        element.appendChild(div);
+
+    };
+
+    // Create keyboard layout in DOM
+    appendElements(keyboard, layout.layout);
+
+};
+
+/**
+ * Represents an entire on-screen keyboard layout, including all available
+ * keys, their behaviors, and their relative position and sizing.
+ *
+ * @constructor
+ * @param {Guacamole.OnScreenKeyboard.Layout|Object} template
+ *     The object whose identically-named properties will be used to initialize
+ *     the properties of this layout.
+ */
+Guacamole.OnScreenKeyboard.Layout = function(template) {
+
+    /**
+     * The language of keyboard layout, such as "en_US". This property is for
+     * informational purposes only, but it is recommend to conform to the
+     * [language code]_[country code] format.
+     *
+     * @type {String}
+     */
+    this.language = template.language;
+
+    /**
+     * The type of keyboard layout, such as "qwerty". This property is for
+     * informational purposes only, and does not conform to any standard.
+     *
+     * @type {String}
+     */
+    this.type = template.type;
+
+    /**
+     * Map of key name to corresponding keysym, title, or key object. If only
+     * the keysym or title is provided, the key object will be created
+     * implicitly. In all cases, the name property of the key object will be
+     * taken from the name given in the mapping.
+     *
+     * @type {Object.&lt;String, Number|String|Guacamole.OnScreenKeyboard.Key|Guacamole.OnScreenKeyboard.Key[]>}
+     */
+    this.keys = template.keys;
+
+    /**
+     * Arbitrarily nested, arbitrarily grouped key names. The contents of the
+     * layout will be traversed to produce an identically-nested grouping of
+     * keys in the DOM tree. All strings will be transformed into their
+     * corresponding sets of keys, while all objects and arrays will be
+     * transformed into named groups and anonymous groups respectively. Any
+     * numbers present will be transformed into gaps of that size, scaled
+     * according to the same units as each key.
+     *
+     * @type {Object}
+     */
+    this.layout = template.layout;
+
+    /**
+     * The width of the entire keyboard, in arbitrary units. The width of each
+     * key is relative to this width, as both width values are assumed to be in
+     * the same units. The conversion factor between these units and pixels is
+     * derived later via a call to resize() on the Guacamole.OnScreenKeyboard.
+     *
+     * @type {Number}
+     */
+    this.width = template.width;
+
+    /**
+     * The width of each key, in arbitrary units, relative to other keys in
+     * this layout. The true pixel size of each key will be determined by the
+     * overall size of the keyboard. If not defined here, the width of each
+     * key will default to 1.
+     *
+     * @type {Object.&lt;String, Number>}
+     */
+    this.keyWidths = template.keyWidths || {};
+
+};
+
+/**
+ * Represents a single key, or a single possible behavior of a key. Each key
+ * on the on-screen keyboard must have at least one associated
+ * Guacamole.OnScreenKeyboard.Key, whether that key is explicitly defined or
+ * implied, and may have multiple Guacamole.OnScreenKeyboard.Key if behavior
+ * depends on modifier states.
+ *
+ * @constructor
+ * @param {Guacamole.OnScreenKeyboard.Key|Object} template
+ *     The object whose identically-named properties will be used to initialize
+ *     the properties of this key.
+ *     
+ * @param {String} [name]
+ *     The name to use instead of any name provided within the template, if
+ *     any. If omitted, the name within the template will be used, assuming the
+ *     template contains a name.
+ */
+Guacamole.OnScreenKeyboard.Key = function(template, name) {
+
+    /**
+     * The unique name identifying this key within the keyboard layout.
+     *
+     * @type {String}
+     */
+    this.name = name || template.name;
+
+    /**
+     * The human-readable title that will be displayed to the user within the
+     * key. If not provided, this will be derived from the key name.
+     *
+     * @type {String}
+     */
+    this.title = template.title || this.name;
+
+    /**
+     * The keysym to be pressed/released when this key is pressed/released. If
+     * not provided, this will be derived from the title if the title is a
+     * single character.
+     *
+     * @type {Number}
+     */
+    this.keysym = template.keysym || (function deriveKeysym(title) {
+
+        // Do not derive keysym if title is not exactly one character
+        if (!title || title.length !== 1)
+            return null;
+
+        // For characters between U+0000 and U+00FF, the keysym is the codepoint
+        var charCode = title.charCodeAt(0);
+        if (charCode >= 0x0000 &amp;&amp; charCode &lt;= 0x00FF)
+            return charCode;
+
+        // For characters between U+0100 and U+10FFFF, the keysym is the codepoint or'd with 0x01000000
+        if (charCode >= 0x0100 &amp;&amp; charCode &lt;= 0x10FFFF)
+            return 0x01000000 | charCode;
+
+        // Unable to derive keysym
+        return null;
+
+    })(this.title);
+
+    /**
+     * The name of the modifier set when the key is pressed and cleared when
+     * this key is released, if any. The names of modifiers are distinct from
+     * the names of keys; both the "RightShift" and "LeftShift" keys may set
+     * the "shift" modifier, for example. By default, the key will affect no
+     * modifiers.
+     * 
+     * @type {String}
+     */
+    this.modifier = template.modifier;
+
+    /**
+     * An array containing the names of each modifier required for this key to
+     * have an effect. For example, a lowercase letter may require nothing,
+     * while an uppercase letter would require "shift", assuming the Shift key
+     * is named "shift" within the layout. By default, the key will require
+     * no modifiers.
+     *
+     * @type {String[]}
+     */
+    this.requires = template.requires || [];
+
+};
+</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.html">ChainedTunnel</a></li><li><a href="Guacamole.Client.html">Client</a></li><li><a href="Guacamole.DataURIReader.html">DataURIReader</a></li><li><a href="Guacamole.Display.html">Display</a></li><li><a href="Guacamole.Display.VisibleLayer.html">VisibleLayer</a></li><li><a href="Guacamole.HTTPTunnel.html">HTTPTunnel</a></li><li><a href="Guacamole.InputStream.html">InputStream</a></li><li><a href="Guacamole.IntegerPool.html">IntegerPool</a></li><li><a href="Guacamole.JSONReader.html">JSONReader</a></li>
 <li><a href="Guacamole.Keyboard.html">Keyboard</a></li><li><a href="Guacamole.Keyboard.ModifierState.html">ModifierState</a></li><li><a href="Guacamole.Layer.html">Layer</a></li><li><a href="Guacamole.Layer.Pixel.html">Pixel</a></li><li><a href="Guacamole.Mouse.html">Mouse</a></li><li><a href="Guacamole.Mouse.State.html">State</a></li><li><a href="Guacamole.Mouse.Touchpad.html">Touchpad</a></li><li><a href="Guacamole.Mouse.Touchscreen.html">Touchscreen</a></li><li><a href="Guacamole.Object.html">Object</a></li><li><a href="Guacamole.OnScreenKeyboard.html">OnScreenKeyboard</a></li><li><a href="Guacamole.OnScreenKeyboard.Key.html">Key</a></li><li><a href="Guacamole.OnScreenKeyboard.Layout.html">Layout</a></li><li><a href="Guacamole.OutputStream.html">OutputStream</a></li><li><a href="Guacamole.Parser.html">Parser</a></li><li><a href="Guacamole.RawAudioFormat.html">RawAudioFormat</a></li><li><a href="Guacamole.RawAudioPlayer.html">RawAudioPlayer</a></li><li><a href="Guacamole.RawAudioR
 ecorder.html">RawAudioRecorder</a></li><li><a href="Guacamole.Status.html">Status</a></li><li><a href="Guacamole.StringReader.html">StringReader</a></li><li><a href="Guacamole.StringWriter.html">StringWriter</a></li><li><a href="Guacamole.Tunnel.html">Tunnel</a></li><li><a href="Guacamole.VideoPlayer.html">VideoPlayer</a></li><li><a href="Guacamole.WebSocketTunnel.html">WebSocketTunnel</a></li></ul><h3>Events</h3><ul><li><a href="Guacamole.ArrayBufferReader.html#event:ondata">ondata</a></li><li><a href="Guacamole.ArrayBufferReader.html#event:onend">onend</a></li><li><a href="Guacamole.ArrayBufferWriter.html#event:onack">onack</a></li><li><a href="Guacamole.AudioRecorder.html#event:onclose">onclose</a></li><li><a href="Guacamole.AudioRecorder.html#event:onerror">onerror</a></li><li><a href="Guacamole.BlobReader.html#event:onend">onend</a></li><li><a href="Guacamole.BlobReader.html#event:onprogress">onprogress</a></li><li><a href="Guacamole.BlobWriter.html#event:onack">onack</a></li><
 li><a href="Guacamole.BlobWriter.html#event:oncomplete">oncomplete</a></li><li><a href="Guacamole.BlobWriter.html#event:onerror">onerror</a></li><li><a href="Guacamole.BlobWriter.html#event:onprogress">onprogress</a></li><li><a href="Guacamole.ChainedTunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.ChainedTunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.ChainedTunnel.html#event:onstatechange">onstatechange</a></li><li><a href="Guacamole.Client.html#event:onaudio">onaudio</a></li><li><a href="Guacamole.Client.html#event:onclipboard">onclipboard</a></li><li><a href="Guacamole.Client.html#event:onerror">onerror</a></li><li><a href="Guacamole.Client.html#event:onfile">onfile</a></li><li><a href="Guacamole.Client.html#event:onfilesystem">onfilesystem</a></li><li><a href="Guacamole.Client.html#event:onname">onname</a></li><li><a href="Guacamole.Client.html#event:onpipe">onpipe</a></li><li><a href="Guacamole.Client.html#event:onstatechange">ons
 tatechange</a></li><li><a href="Guacamole.Client.html#event:onsync">onsync</a></li><li><a href="Guacamole.Client.html#event:onvideo">onvideo</a></li><li><a href="Guacamole.DataURIReader.html#event:onend">onend</a></li><li><a href="Guacamole.Display.html#event:oncursor">oncursor</a></li><li><a href="Guacamole.Display.html#event:onresize">onresize</a></li><li><a href="Guacamole.HTTPTunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.HTTPTunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.HTTPTunnel.html#event:onstatechange">onstatechange</a></li><li><a href="Guacamole.InputStream.html#event:onblob">onblob</a></li><li><a href="Guacamole.InputStream.html#event:onend">onend</a></li><li><a href="Guacamole.JSONReader.html#event:onend">onend</a></li><li><a href="Guacamole.JSONReader.html#event:onprogress">onprogress</a></li><li><a href="Guacamole.Keyboard.html#event:onkeydown">onkeydown</a></li><li><a href="Guacamole.Keyboard.html#event:onkeyup">onkey
 up</a></li><li><a href="Guacamole.Mouse.Touchpad.html#event:onmousedown">onmousedown</a></li><li><a href="Guacamole.Mouse.Touchpad.html#event:onmousemove">onmousemove</a></li><li><a href="Guacamole.Mouse.Touchpad.html#event:onmouseup">onmouseup</a></li><li><a href="Guacamole.Mouse.Touchscreen.html#event:onmousedown">onmousedown</a></li><li><a href="Guacamole.Mouse.Touchscreen.html#event:onmousemove">onmousemove</a></li><li><a href="Guacamole.Mouse.Touchscreen.html#event:onmouseup">onmouseup</a></li><li><a href="Guacamole.Mouse.html#event:onmousedown">onmousedown</a></li><li><a href="Guacamole.Mouse.html#event:onmousemove">onmousemove</a></li><li><a href="Guacamole.Mouse.html#event:onmouseout">onmouseout</a></li><li><a href="Guacamole.Mouse.html#event:onmouseup">onmouseup</a></li><li><a href="Guacamole.Object.html#event:onbody">onbody</a></li><li><a href="Guacamole.Object.html#event:onundefine">onundefine</a></li><li><a href="Guacamole.OnScreenKeyboard.html#event:onkeydown">onkeydown
 </a></li><li><a href="Guacamole.OnScreenKeyboard.html#event:onkeyup">onkeyup</a></li><li><a href="Guacamole.OutputStream.html#event:onack">onack</a></li><li><a href="Guacamole.Parser.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.RawAudioRecorder.html#event:onclose">onclose</a></li><li><a href="Guacamole.RawAudioRecorder.html#event:onerror">onerror</a></li><li><a href="Guacamole.StringReader.html#event:onend">onend</a></li><li><a href="Guacamole.StringReader.html#event:ontext">ontext</a></li><li><a href="Guacamole.StringWriter.html#event:onack">onack</a></li><li><a href="Guacamole.Tunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.Tunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.Tunnel.html#event:onstatechange">onstatechange</a></li><li><a href="Guacamole.WebSocketTunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.WebSocketTunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.W
 ebSocketTunnel.html#event:onstatechange">onstatechange</a></li></ul><h3>Namespaces</h3><ul><li><a href="Guacamole.html">Guacamole</a></li><li><a href="Guacamole.AudioContextFactory.html">AudioContextFactory</a></li></ul>
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Mon Oct 31 2016 20:22:21 GMT-0700 (PDT)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-website/blob/5d2c3c74/doc/0.9.10-incubating/guacamole-common-js/OutputStream.js.html
----------------------------------------------------------------------
diff --git a/doc/0.9.10-incubating/guacamole-common-js/OutputStream.js.html b/doc/0.9.10-incubating/guacamole-common-js/OutputStream.js.html
new file mode 100644
index 0000000..d4cc970
--- /dev/null
+++ b/doc/0.9.10-incubating/guacamole-common-js/OutputStream.js.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: OutputStream.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: OutputStream.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 Guacamole = Guacamole || {};
+
+/**
+ * Abstract stream which can receive data.
+ * 
+ * @constructor
+ * @param {Guacamole.Client} client The client owning this stream.
+ * @param {Number} index The index of this stream.
+ */
+Guacamole.OutputStream = function(client, index) {
+
+    /**
+     * Reference to this stream.
+     * @private
+     */
+    var guac_stream = this;
+
+    /**
+     * The index of this stream.
+     * @type {Number}
+     */
+    this.index = index;
+
+    /**
+     * Fired whenever an acknowledgement is received from the server, indicating
+     * that a stream operation has completed, or an error has occurred.
+     * 
+     * @event
+     * @param {Guacamole.Status} status The status of the operation.
+     */
+    this.onack = null;
+
+    /**
+     * Writes the given base64-encoded data to this stream as a blob.
+     * 
+     * @param {String} data The base64-encoded data to send.
+     */
+    this.sendBlob = function(data) {
+        client.sendBlob(guac_stream.index, data);
+    };
+
+    /**
+     * Closes this stream.
+     */
+    this.sendEnd = function() {
+        client.endStream(guac_stream.index);
+    };
+
+};
+</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.html">ChainedTunnel</a></li><li><a href="Guacamole.Client.html">Client</a></li><li><a href="Guacamole.DataURIReader.html">DataURIReader</a></li><li><a href="Guacamole.Display.html">Display</a></li><li><a href="Guacamole.Display.VisibleLayer.html">VisibleLayer</a></li><li><a href="Guacamole.HTTPTunnel.html">HTTPTunnel</a></li><li><a href="Guacamole.InputStream.html">InputStream</a></li><li><a href="Guacamole.IntegerPool.html">IntegerPool</a></li><li><a href="Guacamole.JSONReader.html">JSONReader</a></li>
 <li><a href="Guacamole.Keyboard.html">Keyboard</a></li><li><a href="Guacamole.Keyboard.ModifierState.html">ModifierState</a></li><li><a href="Guacamole.Layer.html">Layer</a></li><li><a href="Guacamole.Layer.Pixel.html">Pixel</a></li><li><a href="Guacamole.Mouse.html">Mouse</a></li><li><a href="Guacamole.Mouse.State.html">State</a></li><li><a href="Guacamole.Mouse.Touchpad.html">Touchpad</a></li><li><a href="Guacamole.Mouse.Touchscreen.html">Touchscreen</a></li><li><a href="Guacamole.Object.html">Object</a></li><li><a href="Guacamole.OnScreenKeyboard.html">OnScreenKeyboard</a></li><li><a href="Guacamole.OnScreenKeyboard.Key.html">Key</a></li><li><a href="Guacamole.OnScreenKeyboard.Layout.html">Layout</a></li><li><a href="Guacamole.OutputStream.html">OutputStream</a></li><li><a href="Guacamole.Parser.html">Parser</a></li><li><a href="Guacamole.RawAudioFormat.html">RawAudioFormat</a></li><li><a href="Guacamole.RawAudioPlayer.html">RawAudioPlayer</a></li><li><a href="Guacamole.RawAudioR
 ecorder.html">RawAudioRecorder</a></li><li><a href="Guacamole.Status.html">Status</a></li><li><a href="Guacamole.StringReader.html">StringReader</a></li><li><a href="Guacamole.StringWriter.html">StringWriter</a></li><li><a href="Guacamole.Tunnel.html">Tunnel</a></li><li><a href="Guacamole.VideoPlayer.html">VideoPlayer</a></li><li><a href="Guacamole.WebSocketTunnel.html">WebSocketTunnel</a></li></ul><h3>Events</h3><ul><li><a href="Guacamole.ArrayBufferReader.html#event:ondata">ondata</a></li><li><a href="Guacamole.ArrayBufferReader.html#event:onend">onend</a></li><li><a href="Guacamole.ArrayBufferWriter.html#event:onack">onack</a></li><li><a href="Guacamole.AudioRecorder.html#event:onclose">onclose</a></li><li><a href="Guacamole.AudioRecorder.html#event:onerror">onerror</a></li><li><a href="Guacamole.BlobReader.html#event:onend">onend</a></li><li><a href="Guacamole.BlobReader.html#event:onprogress">onprogress</a></li><li><a href="Guacamole.BlobWriter.html#event:onack">onack</a></li><
 li><a href="Guacamole.BlobWriter.html#event:oncomplete">oncomplete</a></li><li><a href="Guacamole.BlobWriter.html#event:onerror">onerror</a></li><li><a href="Guacamole.BlobWriter.html#event:onprogress">onprogress</a></li><li><a href="Guacamole.ChainedTunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.ChainedTunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.ChainedTunnel.html#event:onstatechange">onstatechange</a></li><li><a href="Guacamole.Client.html#event:onaudio">onaudio</a></li><li><a href="Guacamole.Client.html#event:onclipboard">onclipboard</a></li><li><a href="Guacamole.Client.html#event:onerror">onerror</a></li><li><a href="Guacamole.Client.html#event:onfile">onfile</a></li><li><a href="Guacamole.Client.html#event:onfilesystem">onfilesystem</a></li><li><a href="Guacamole.Client.html#event:onname">onname</a></li><li><a href="Guacamole.Client.html#event:onpipe">onpipe</a></li><li><a href="Guacamole.Client.html#event:onstatechange">ons
 tatechange</a></li><li><a href="Guacamole.Client.html#event:onsync">onsync</a></li><li><a href="Guacamole.Client.html#event:onvideo">onvideo</a></li><li><a href="Guacamole.DataURIReader.html#event:onend">onend</a></li><li><a href="Guacamole.Display.html#event:oncursor">oncursor</a></li><li><a href="Guacamole.Display.html#event:onresize">onresize</a></li><li><a href="Guacamole.HTTPTunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.HTTPTunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.HTTPTunnel.html#event:onstatechange">onstatechange</a></li><li><a href="Guacamole.InputStream.html#event:onblob">onblob</a></li><li><a href="Guacamole.InputStream.html#event:onend">onend</a></li><li><a href="Guacamole.JSONReader.html#event:onend">onend</a></li><li><a href="Guacamole.JSONReader.html#event:onprogress">onprogress</a></li><li><a href="Guacamole.Keyboard.html#event:onkeydown">onkeydown</a></li><li><a href="Guacamole.Keyboard.html#event:onkeyup">onkey
 up</a></li><li><a href="Guacamole.Mouse.Touchpad.html#event:onmousedown">onmousedown</a></li><li><a href="Guacamole.Mouse.Touchpad.html#event:onmousemove">onmousemove</a></li><li><a href="Guacamole.Mouse.Touchpad.html#event:onmouseup">onmouseup</a></li><li><a href="Guacamole.Mouse.Touchscreen.html#event:onmousedown">onmousedown</a></li><li><a href="Guacamole.Mouse.Touchscreen.html#event:onmousemove">onmousemove</a></li><li><a href="Guacamole.Mouse.Touchscreen.html#event:onmouseup">onmouseup</a></li><li><a href="Guacamole.Mouse.html#event:onmousedown">onmousedown</a></li><li><a href="Guacamole.Mouse.html#event:onmousemove">onmousemove</a></li><li><a href="Guacamole.Mouse.html#event:onmouseout">onmouseout</a></li><li><a href="Guacamole.Mouse.html#event:onmouseup">onmouseup</a></li><li><a href="Guacamole.Object.html#event:onbody">onbody</a></li><li><a href="Guacamole.Object.html#event:onundefine">onundefine</a></li><li><a href="Guacamole.OnScreenKeyboard.html#event:onkeydown">onkeydown
 </a></li><li><a href="Guacamole.OnScreenKeyboard.html#event:onkeyup">onkeyup</a></li><li><a href="Guacamole.OutputStream.html#event:onack">onack</a></li><li><a href="Guacamole.Parser.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.RawAudioRecorder.html#event:onclose">onclose</a></li><li><a href="Guacamole.RawAudioRecorder.html#event:onerror">onerror</a></li><li><a href="Guacamole.StringReader.html#event:onend">onend</a></li><li><a href="Guacamole.StringReader.html#event:ontext">ontext</a></li><li><a href="Guacamole.StringWriter.html#event:onack">onack</a></li><li><a href="Guacamole.Tunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.Tunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.Tunnel.html#event:onstatechange">onstatechange</a></li><li><a href="Guacamole.WebSocketTunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.WebSocketTunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.W
 ebSocketTunnel.html#event:onstatechange">onstatechange</a></li></ul><h3>Namespaces</h3><ul><li><a href="Guacamole.html">Guacamole</a></li><li><a href="Guacamole.AudioContextFactory.html">AudioContextFactory</a></li></ul>
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Mon Oct 31 2016 20:22:21 GMT-0700 (PDT)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-website/blob/5d2c3c74/doc/0.9.10-incubating/guacamole-common-js/Parser.js.html
----------------------------------------------------------------------
diff --git a/doc/0.9.10-incubating/guacamole-common-js/Parser.js.html b/doc/0.9.10-incubating/guacamole-common-js/Parser.js.html
new file mode 100644
index 0000000..56208ac
--- /dev/null
+++ b/doc/0.9.10-incubating/guacamole-common-js/Parser.js.html
@@ -0,0 +1,207 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: Parser.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: Parser.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 Guacamole = Guacamole || {};
+
+/**
+ * Simple Guacamole protocol parser that invokes an oninstruction event when
+ * full instructions are available from data received via receive().
+ * 
+ * @constructor
+ */
+Guacamole.Parser = function() {
+
+    /**
+     * Reference to this parser.
+     * @private
+     */
+    var parser = this;
+
+    /**
+     * Current buffer of received data. This buffer grows until a full
+     * element is available. After a full element is available, that element
+     * is flushed into the element buffer.
+     * 
+     * @private
+     */
+    var buffer = "";
+
+    /**
+     * Buffer of all received, complete elements. After an entire instruction
+     * is read, this buffer is flushed, and a new instruction begins.
+     * 
+     * @private
+     */
+    var element_buffer = [];
+
+    // The location of the last element's terminator
+    var element_end = -1;
+
+    // Where to start the next length search or the next element
+    var start_index = 0;
+
+    /**
+     * Appends the given instruction data packet to the internal buffer of
+     * this Guacamole.Parser, executing all completed instructions at
+     * the beginning of this buffer, if any.
+     *
+     * @param {String} packet The instruction data to receive.
+     */
+    this.receive = function(packet) {
+
+        // Truncate buffer as necessary
+        if (start_index > 4096 &amp;&amp; element_end >= start_index) {
+
+            buffer = buffer.substring(start_index);
+
+            // Reset parse relative to truncation
+            element_end -= start_index;
+            start_index = 0;
+
+        }
+
+        // Append data to buffer
+        buffer += packet;
+
+        // While search is within currently received data
+        while (element_end &lt; buffer.length) {
+
+            // If we are waiting for element data
+            if (element_end >= start_index) {
+
+                // We now have enough data for the element. Parse.
+                var element = buffer.substring(start_index, element_end);
+                var terminator = buffer.substring(element_end, element_end+1);
+
+                // Add element to array
+                element_buffer.push(element);
+
+                // If last element, handle instruction
+                if (terminator == ";") {
+
+                    // Get opcode
+                    var opcode = element_buffer.shift();
+
+                    // Call instruction handler.
+                    if (parser.oninstruction != null)
+                        parser.oninstruction(opcode, element_buffer);
+
+                    // Clear elements
+                    element_buffer.length = 0;
+
+                }
+                else if (terminator != ',')
+                    throw new Error("Illegal terminator.");
+
+                // Start searching for length at character after
+                // element terminator
+                start_index = element_end + 1;
+
+            }
+
+            // Search for end of length
+            var length_end = buffer.indexOf(".", start_index);
+            if (length_end != -1) {
+
+                // Parse length
+                var length = parseInt(buffer.substring(element_end+1, length_end));
+                if (length == NaN)
+                    throw new Error("Non-numeric character in element length.");
+
+                // Calculate start of element
+                start_index = length_end + 1;
+
+                // Calculate location of element terminator
+                element_end = start_index + length;
+
+            }
+            
+            // If no period yet, continue search when more data
+            // is received
+            else {
+                start_index = buffer.length;
+                break;
+            }
+
+        } // end parse loop
+
+    };
+
+    /**
+     * Fired once for every complete Guacamole instruction received, in order.
+     * 
+     * @event
+     * @param {String} opcode The Guacamole instruction opcode.
+     * @param {Array} parameters The parameters provided for the instruction,
+     *                           if any.
+     */
+    this.oninstruction = null;
+
+};
+</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.html">ChainedTunnel</a></li><li><a href="Guacamole.Client.html">Client</a></li><li><a href="Guacamole.DataURIReader.html">DataURIReader</a></li><li><a href="Guacamole.Display.html">Display</a></li><li><a href="Guacamole.Display.VisibleLayer.html">VisibleLayer</a></li><li><a href="Guacamole.HTTPTunnel.html">HTTPTunnel</a></li><li><a href="Guacamole.InputStream.html">InputStream</a></li><li><a href="Guacamole.IntegerPool.html">IntegerPool</a></li><li><a href="Guacamole.JSONReader.html">JSONReader</a></li>
 <li><a href="Guacamole.Keyboard.html">Keyboard</a></li><li><a href="Guacamole.Keyboard.ModifierState.html">ModifierState</a></li><li><a href="Guacamole.Layer.html">Layer</a></li><li><a href="Guacamole.Layer.Pixel.html">Pixel</a></li><li><a href="Guacamole.Mouse.html">Mouse</a></li><li><a href="Guacamole.Mouse.State.html">State</a></li><li><a href="Guacamole.Mouse.Touchpad.html">Touchpad</a></li><li><a href="Guacamole.Mouse.Touchscreen.html">Touchscreen</a></li><li><a href="Guacamole.Object.html">Object</a></li><li><a href="Guacamole.OnScreenKeyboard.html">OnScreenKeyboard</a></li><li><a href="Guacamole.OnScreenKeyboard.Key.html">Key</a></li><li><a href="Guacamole.OnScreenKeyboard.Layout.html">Layout</a></li><li><a href="Guacamole.OutputStream.html">OutputStream</a></li><li><a href="Guacamole.Parser.html">Parser</a></li><li><a href="Guacamole.RawAudioFormat.html">RawAudioFormat</a></li><li><a href="Guacamole.RawAudioPlayer.html">RawAudioPlayer</a></li><li><a href="Guacamole.RawAudioR
 ecorder.html">RawAudioRecorder</a></li><li><a href="Guacamole.Status.html">Status</a></li><li><a href="Guacamole.StringReader.html">StringReader</a></li><li><a href="Guacamole.StringWriter.html">StringWriter</a></li><li><a href="Guacamole.Tunnel.html">Tunnel</a></li><li><a href="Guacamole.VideoPlayer.html">VideoPlayer</a></li><li><a href="Guacamole.WebSocketTunnel.html">WebSocketTunnel</a></li></ul><h3>Events</h3><ul><li><a href="Guacamole.ArrayBufferReader.html#event:ondata">ondata</a></li><li><a href="Guacamole.ArrayBufferReader.html#event:onend">onend</a></li><li><a href="Guacamole.ArrayBufferWriter.html#event:onack">onack</a></li><li><a href="Guacamole.AudioRecorder.html#event:onclose">onclose</a></li><li><a href="Guacamole.AudioRecorder.html#event:onerror">onerror</a></li><li><a href="Guacamole.BlobReader.html#event:onend">onend</a></li><li><a href="Guacamole.BlobReader.html#event:onprogress">onprogress</a></li><li><a href="Guacamole.BlobWriter.html#event:onack">onack</a></li><
 li><a href="Guacamole.BlobWriter.html#event:oncomplete">oncomplete</a></li><li><a href="Guacamole.BlobWriter.html#event:onerror">onerror</a></li><li><a href="Guacamole.BlobWriter.html#event:onprogress">onprogress</a></li><li><a href="Guacamole.ChainedTunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.ChainedTunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.ChainedTunnel.html#event:onstatechange">onstatechange</a></li><li><a href="Guacamole.Client.html#event:onaudio">onaudio</a></li><li><a href="Guacamole.Client.html#event:onclipboard">onclipboard</a></li><li><a href="Guacamole.Client.html#event:onerror">onerror</a></li><li><a href="Guacamole.Client.html#event:onfile">onfile</a></li><li><a href="Guacamole.Client.html#event:onfilesystem">onfilesystem</a></li><li><a href="Guacamole.Client.html#event:onname">onname</a></li><li><a href="Guacamole.Client.html#event:onpipe">onpipe</a></li><li><a href="Guacamole.Client.html#event:onstatechange">ons
 tatechange</a></li><li><a href="Guacamole.Client.html#event:onsync">onsync</a></li><li><a href="Guacamole.Client.html#event:onvideo">onvideo</a></li><li><a href="Guacamole.DataURIReader.html#event:onend">onend</a></li><li><a href="Guacamole.Display.html#event:oncursor">oncursor</a></li><li><a href="Guacamole.Display.html#event:onresize">onresize</a></li><li><a href="Guacamole.HTTPTunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.HTTPTunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.HTTPTunnel.html#event:onstatechange">onstatechange</a></li><li><a href="Guacamole.InputStream.html#event:onblob">onblob</a></li><li><a href="Guacamole.InputStream.html#event:onend">onend</a></li><li><a href="Guacamole.JSONReader.html#event:onend">onend</a></li><li><a href="Guacamole.JSONReader.html#event:onprogress">onprogress</a></li><li><a href="Guacamole.Keyboard.html#event:onkeydown">onkeydown</a></li><li><a href="Guacamole.Keyboard.html#event:onkeyup">onkey
 up</a></li><li><a href="Guacamole.Mouse.Touchpad.html#event:onmousedown">onmousedown</a></li><li><a href="Guacamole.Mouse.Touchpad.html#event:onmousemove">onmousemove</a></li><li><a href="Guacamole.Mouse.Touchpad.html#event:onmouseup">onmouseup</a></li><li><a href="Guacamole.Mouse.Touchscreen.html#event:onmousedown">onmousedown</a></li><li><a href="Guacamole.Mouse.Touchscreen.html#event:onmousemove">onmousemove</a></li><li><a href="Guacamole.Mouse.Touchscreen.html#event:onmouseup">onmouseup</a></li><li><a href="Guacamole.Mouse.html#event:onmousedown">onmousedown</a></li><li><a href="Guacamole.Mouse.html#event:onmousemove">onmousemove</a></li><li><a href="Guacamole.Mouse.html#event:onmouseout">onmouseout</a></li><li><a href="Guacamole.Mouse.html#event:onmouseup">onmouseup</a></li><li><a href="Guacamole.Object.html#event:onbody">onbody</a></li><li><a href="Guacamole.Object.html#event:onundefine">onundefine</a></li><li><a href="Guacamole.OnScreenKeyboard.html#event:onkeydown">onkeydown
 </a></li><li><a href="Guacamole.OnScreenKeyboard.html#event:onkeyup">onkeyup</a></li><li><a href="Guacamole.OutputStream.html#event:onack">onack</a></li><li><a href="Guacamole.Parser.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.RawAudioRecorder.html#event:onclose">onclose</a></li><li><a href="Guacamole.RawAudioRecorder.html#event:onerror">onerror</a></li><li><a href="Guacamole.StringReader.html#event:onend">onend</a></li><li><a href="Guacamole.StringReader.html#event:ontext">ontext</a></li><li><a href="Guacamole.StringWriter.html#event:onack">onack</a></li><li><a href="Guacamole.Tunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.Tunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.Tunnel.html#event:onstatechange">onstatechange</a></li><li><a href="Guacamole.WebSocketTunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.WebSocketTunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.W
 ebSocketTunnel.html#event:onstatechange">onstatechange</a></li></ul><h3>Namespaces</h3><ul><li><a href="Guacamole.html">Guacamole</a></li><li><a href="Guacamole.AudioContextFactory.html">AudioContextFactory</a></li></ul>
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Mon Oct 31 2016 20:22:21 GMT-0700 (PDT)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-website/blob/5d2c3c74/doc/0.9.10-incubating/guacamole-common-js/RawAudioFormat.js.html
----------------------------------------------------------------------
diff --git a/doc/0.9.10-incubating/guacamole-common-js/RawAudioFormat.js.html b/doc/0.9.10-incubating/guacamole-common-js/RawAudioFormat.js.html
new file mode 100644
index 0000000..b55efcd
--- /dev/null
+++ b/doc/0.9.10-incubating/guacamole-common-js/RawAudioFormat.js.html
@@ -0,0 +1,197 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: RawAudioFormat.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: RawAudioFormat.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 Guacamole = Guacamole || {};
+
+/**
+ * A description of the format of raw PCM audio, such as that used by
+ * Guacamole.RawAudioPlayer and Guacamole.RawAudioRecorder. This object
+ * describes the number of bytes per sample, the number of channels, and the
+ * overall sample rate.
+ *
+ * @constructor
+ * @param {Guacamole.RawAudioFormat|Object} template
+ *     The object whose properties should be copied into the corresponding
+ *     properties of the new Guacamole.RawAudioFormat.
+ */
+Guacamole.RawAudioFormat = function RawAudioFormat(template) {
+
+    /**
+     * The number of bytes in each sample of audio data. This value is
+     * independent of the number of channels.
+     *
+     * @type {Number}
+     */
+    this.bytesPerSample = template.bytesPerSample;
+
+    /**
+     * The number of audio channels (ie: 1 for mono, 2 for stereo).
+     *
+     * @type {Number}
+     */
+    this.channels = template.channels;
+
+    /**
+     * The number of samples per second, per channel.
+     *
+     * @type {Number}
+     */
+    this.rate = template.rate;
+
+};
+
+/**
+ * Parses the given mimetype, returning a new Guacamole.RawAudioFormat
+ * which describes the type of raw audio data represented by that mimetype. If
+ * the mimetype is not a supported raw audio data mimetype, null is returned.
+ *
+ * @param {String} mimetype
+ *     The audio mimetype to parse.
+ *
+ * @returns {Guacamole.RawAudioFormat}
+ *     A new Guacamole.RawAudioFormat which describes the type of raw
+ *     audio data represented by the given mimetype, or null if the given
+ *     mimetype is not supported.
+ */
+Guacamole.RawAudioFormat.parse = function parseFormat(mimetype) {
+
+    var bytesPerSample;
+
+    // Rate is absolutely required - if null is still present later, the
+    // mimetype must not be supported
+    var rate = null;
+
+    // Default for both "audio/L8" and "audio/L16" is one channel
+    var channels = 1;
+
+    // "audio/L8" has one byte per sample
+    if (mimetype.substring(0, 9) === 'audio/L8;') {
+        mimetype = mimetype.substring(9);
+        bytesPerSample = 1;
+    }
+
+    // "audio/L16" has two bytes per sample
+    else if (mimetype.substring(0, 10) === 'audio/L16;') {
+        mimetype = mimetype.substring(10);
+        bytesPerSample = 2;
+    }
+
+    // All other types are unsupported
+    else
+        return null;
+
+    // Parse all parameters
+    var parameters = mimetype.split(',');
+    for (var i = 0; i &lt; parameters.length; i++) {
+
+        var parameter = parameters[i];
+
+        // All parameters must have an equals sign separating name from value
+        var equals = parameter.indexOf('=');
+        if (equals === -1)
+            return null;
+
+        // Parse name and value from parameter string
+        var name  = parameter.substring(0, equals);
+        var value = parameter.substring(equals+1);
+
+        // Handle each supported parameter
+        switch (name) {
+
+            // Number of audio channels
+            case 'channels':
+                channels = parseInt(value);
+                break;
+
+            // Sample rate
+            case 'rate':
+                rate = parseInt(value);
+                break;
+
+            // All other parameters are unsupported
+            default:
+                return null;
+
+        }
+
+    };
+
+    // The rate parameter is required
+    if (rate === null)
+        return null;
+
+    // Return parsed format details
+    return new Guacamole.RawAudioFormat({
+        bytesPerSample : bytesPerSample,
+        channels       : channels,
+        rate           : rate
+    });
+
+};
+</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Guacamole.ArrayBufferReader.html">ArrayBufferReader</a></li><li><a href="Guacamole.ArrayBufferWriter.html">ArrayBufferWriter</a></li><li><a href="Guacamole.AudioPlayer.html">AudioPlayer</a></li><li><a href="Guacamole.AudioRecorder.html">AudioRecorder</a></li><li><a href="Guacamole.BlobReader.html">BlobReader</a></li><li><a href="Guacamole.BlobWriter.html">BlobWriter</a></li><li><a href="Guacamole.ChainedTunnel.html">ChainedTunnel</a></li><li><a href="Guacamole.Client.html">Client</a></li><li><a href="Guacamole.DataURIReader.html">DataURIReader</a></li><li><a href="Guacamole.Display.html">Display</a></li><li><a href="Guacamole.Display.VisibleLayer.html">VisibleLayer</a></li><li><a href="Guacamole.HTTPTunnel.html">HTTPTunnel</a></li><li><a href="Guacamole.InputStream.html">InputStream</a></li><li><a href="Guacamole.IntegerPool.html">IntegerPool</a></li><li><a href="Guacamole.JSONReader.html">JSONReader</a></li>
 <li><a href="Guacamole.Keyboard.html">Keyboard</a></li><li><a href="Guacamole.Keyboard.ModifierState.html">ModifierState</a></li><li><a href="Guacamole.Layer.html">Layer</a></li><li><a href="Guacamole.Layer.Pixel.html">Pixel</a></li><li><a href="Guacamole.Mouse.html">Mouse</a></li><li><a href="Guacamole.Mouse.State.html">State</a></li><li><a href="Guacamole.Mouse.Touchpad.html">Touchpad</a></li><li><a href="Guacamole.Mouse.Touchscreen.html">Touchscreen</a></li><li><a href="Guacamole.Object.html">Object</a></li><li><a href="Guacamole.OnScreenKeyboard.html">OnScreenKeyboard</a></li><li><a href="Guacamole.OnScreenKeyboard.Key.html">Key</a></li><li><a href="Guacamole.OnScreenKeyboard.Layout.html">Layout</a></li><li><a href="Guacamole.OutputStream.html">OutputStream</a></li><li><a href="Guacamole.Parser.html">Parser</a></li><li><a href="Guacamole.RawAudioFormat.html">RawAudioFormat</a></li><li><a href="Guacamole.RawAudioPlayer.html">RawAudioPlayer</a></li><li><a href="Guacamole.RawAudioR
 ecorder.html">RawAudioRecorder</a></li><li><a href="Guacamole.Status.html">Status</a></li><li><a href="Guacamole.StringReader.html">StringReader</a></li><li><a href="Guacamole.StringWriter.html">StringWriter</a></li><li><a href="Guacamole.Tunnel.html">Tunnel</a></li><li><a href="Guacamole.VideoPlayer.html">VideoPlayer</a></li><li><a href="Guacamole.WebSocketTunnel.html">WebSocketTunnel</a></li></ul><h3>Events</h3><ul><li><a href="Guacamole.ArrayBufferReader.html#event:ondata">ondata</a></li><li><a href="Guacamole.ArrayBufferReader.html#event:onend">onend</a></li><li><a href="Guacamole.ArrayBufferWriter.html#event:onack">onack</a></li><li><a href="Guacamole.AudioRecorder.html#event:onclose">onclose</a></li><li><a href="Guacamole.AudioRecorder.html#event:onerror">onerror</a></li><li><a href="Guacamole.BlobReader.html#event:onend">onend</a></li><li><a href="Guacamole.BlobReader.html#event:onprogress">onprogress</a></li><li><a href="Guacamole.BlobWriter.html#event:onack">onack</a></li><
 li><a href="Guacamole.BlobWriter.html#event:oncomplete">oncomplete</a></li><li><a href="Guacamole.BlobWriter.html#event:onerror">onerror</a></li><li><a href="Guacamole.BlobWriter.html#event:onprogress">onprogress</a></li><li><a href="Guacamole.ChainedTunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.ChainedTunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.ChainedTunnel.html#event:onstatechange">onstatechange</a></li><li><a href="Guacamole.Client.html#event:onaudio">onaudio</a></li><li><a href="Guacamole.Client.html#event:onclipboard">onclipboard</a></li><li><a href="Guacamole.Client.html#event:onerror">onerror</a></li><li><a href="Guacamole.Client.html#event:onfile">onfile</a></li><li><a href="Guacamole.Client.html#event:onfilesystem">onfilesystem</a></li><li><a href="Guacamole.Client.html#event:onname">onname</a></li><li><a href="Guacamole.Client.html#event:onpipe">onpipe</a></li><li><a href="Guacamole.Client.html#event:onstatechange">ons
 tatechange</a></li><li><a href="Guacamole.Client.html#event:onsync">onsync</a></li><li><a href="Guacamole.Client.html#event:onvideo">onvideo</a></li><li><a href="Guacamole.DataURIReader.html#event:onend">onend</a></li><li><a href="Guacamole.Display.html#event:oncursor">oncursor</a></li><li><a href="Guacamole.Display.html#event:onresize">onresize</a></li><li><a href="Guacamole.HTTPTunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.HTTPTunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.HTTPTunnel.html#event:onstatechange">onstatechange</a></li><li><a href="Guacamole.InputStream.html#event:onblob">onblob</a></li><li><a href="Guacamole.InputStream.html#event:onend">onend</a></li><li><a href="Guacamole.JSONReader.html#event:onend">onend</a></li><li><a href="Guacamole.JSONReader.html#event:onprogress">onprogress</a></li><li><a href="Guacamole.Keyboard.html#event:onkeydown">onkeydown</a></li><li><a href="Guacamole.Keyboard.html#event:onkeyup">onkey
 up</a></li><li><a href="Guacamole.Mouse.Touchpad.html#event:onmousedown">onmousedown</a></li><li><a href="Guacamole.Mouse.Touchpad.html#event:onmousemove">onmousemove</a></li><li><a href="Guacamole.Mouse.Touchpad.html#event:onmouseup">onmouseup</a></li><li><a href="Guacamole.Mouse.Touchscreen.html#event:onmousedown">onmousedown</a></li><li><a href="Guacamole.Mouse.Touchscreen.html#event:onmousemove">onmousemove</a></li><li><a href="Guacamole.Mouse.Touchscreen.html#event:onmouseup">onmouseup</a></li><li><a href="Guacamole.Mouse.html#event:onmousedown">onmousedown</a></li><li><a href="Guacamole.Mouse.html#event:onmousemove">onmousemove</a></li><li><a href="Guacamole.Mouse.html#event:onmouseout">onmouseout</a></li><li><a href="Guacamole.Mouse.html#event:onmouseup">onmouseup</a></li><li><a href="Guacamole.Object.html#event:onbody">onbody</a></li><li><a href="Guacamole.Object.html#event:onundefine">onundefine</a></li><li><a href="Guacamole.OnScreenKeyboard.html#event:onkeydown">onkeydown
 </a></li><li><a href="Guacamole.OnScreenKeyboard.html#event:onkeyup">onkeyup</a></li><li><a href="Guacamole.OutputStream.html#event:onack">onack</a></li><li><a href="Guacamole.Parser.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.RawAudioRecorder.html#event:onclose">onclose</a></li><li><a href="Guacamole.RawAudioRecorder.html#event:onerror">onerror</a></li><li><a href="Guacamole.StringReader.html#event:onend">onend</a></li><li><a href="Guacamole.StringReader.html#event:ontext">ontext</a></li><li><a href="Guacamole.StringWriter.html#event:onack">onack</a></li><li><a href="Guacamole.Tunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.Tunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.Tunnel.html#event:onstatechange">onstatechange</a></li><li><a href="Guacamole.WebSocketTunnel.html#event:onerror">onerror</a></li><li><a href="Guacamole.WebSocketTunnel.html#event:oninstruction">oninstruction</a></li><li><a href="Guacamole.W
 ebSocketTunnel.html#event:onstatechange">onstatechange</a></li></ul><h3>Namespaces</h3><ul><li><a href="Guacamole.html">Guacamole</a></li><li><a href="Guacamole.AudioContextFactory.html">AudioContextFactory</a></li></ul>
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Mon Oct 31 2016 20:22:21 GMT-0700 (PDT)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+</body>
+</html>


Mime
View raw message