mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-07 05:31:22 +00:00
GUACAMOLE-352: Allow additional elements to be added to a single Guacamole.Keyboard.
This commit is contained in:
@@ -25,9 +25,12 @@ var Guacamole = Guacamole || {};
|
|||||||
* which represent keys as their corresponding X11 keysym.
|
* which represent keys as their corresponding X11 keysym.
|
||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {Element} element The Element to use to provide keyboard events.
|
* @param {Element} [element]
|
||||||
|
* The Element to use to provide keyboard events. If omitted, at least one
|
||||||
|
* Element must be manually provided through the listenTo() function for
|
||||||
|
* the Guacamole.Keyboard instance to have any effect.
|
||||||
*/
|
*/
|
||||||
Guacamole.Keyboard = function(element) {
|
Guacamole.Keyboard = function Keyboard(element) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to this Guacamole.Keyboard.
|
* Reference to this Guacamole.Keyboard.
|
||||||
@@ -35,6 +38,25 @@ Guacamole.Keyboard = function(element) {
|
|||||||
*/
|
*/
|
||||||
var guac_keyboard = this;
|
var guac_keyboard = this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An integer value which uniquely identifies this Guacamole.Keyboard
|
||||||
|
* instance with respect to other Guacamole.Keyboard instances.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type {Number}
|
||||||
|
*/
|
||||||
|
var guacKeyboardID = Guacamole.Keyboard._nextID++;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the property which is added to event objects via markEvent()
|
||||||
|
* to note that they have already been handled by this Guacamole.Keyboard.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @constant
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
var EVENT_MARKER = '_GUAC_KEYBOARD_HANDLED_BY_' + guacKeyboardID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fired whenever the user presses a key with the element associated
|
* Fired whenever the user presses a key with the element associated
|
||||||
* with this Guacamole.Keyboard in focus.
|
* with this Guacamole.Keyboard in focus.
|
||||||
@@ -1134,130 +1156,196 @@ Guacamole.Keyboard = function(element) {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// When key pressed
|
|
||||||
element.addEventListener("keydown", function(e) {
|
|
||||||
|
|
||||||
// Only intercept if handler set
|
|
||||||
if (!guac_keyboard.onkeydown) return;
|
|
||||||
|
|
||||||
var keyCode;
|
|
||||||
if (window.event) keyCode = window.event.keyCode;
|
|
||||||
else if (e.which) keyCode = e.which;
|
|
||||||
|
|
||||||
// Fix modifier states
|
|
||||||
syncModifierStates(e);
|
|
||||||
|
|
||||||
// Ignore (but do not prevent) the "composition" keycode sent by some
|
|
||||||
// browsers when an IME is in use (see: http://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html)
|
|
||||||
if (keyCode === 229)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Log event
|
|
||||||
var keydownEvent = new KeydownEvent(keyCode, e.keyIdentifier, e.key, getEventLocation(e));
|
|
||||||
eventLog.push(keydownEvent);
|
|
||||||
|
|
||||||
// Interpret as many events as possible, prevent default if indicated
|
|
||||||
if (interpret_events())
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
// When key pressed
|
|
||||||
element.addEventListener("keypress", function(e) {
|
|
||||||
|
|
||||||
// Only intercept if handler set
|
|
||||||
if (!guac_keyboard.onkeydown && !guac_keyboard.onkeyup) return;
|
|
||||||
|
|
||||||
var charCode;
|
|
||||||
if (window.event) charCode = window.event.keyCode;
|
|
||||||
else if (e.which) charCode = e.which;
|
|
||||||
|
|
||||||
// Fix modifier states
|
|
||||||
syncModifierStates(e);
|
|
||||||
|
|
||||||
// Log event
|
|
||||||
var keypressEvent = new KeypressEvent(charCode);
|
|
||||||
eventLog.push(keypressEvent);
|
|
||||||
|
|
||||||
// Interpret as many events as possible, prevent default if indicated
|
|
||||||
if (interpret_events())
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
// When key released
|
|
||||||
element.addEventListener("keyup", function(e) {
|
|
||||||
|
|
||||||
// Only intercept if handler set
|
|
||||||
if (!guac_keyboard.onkeyup) return;
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
var keyCode;
|
|
||||||
if (window.event) keyCode = window.event.keyCode;
|
|
||||||
else if (e.which) keyCode = e.which;
|
|
||||||
|
|
||||||
// Fix modifier states
|
|
||||||
syncModifierStates(e);
|
|
||||||
|
|
||||||
// Log event, call for interpretation
|
|
||||||
var keyupEvent = new KeyupEvent(keyCode, e.keyIdentifier, e.key, getEventLocation(e));
|
|
||||||
eventLog.push(keyupEvent);
|
|
||||||
interpret_events();
|
|
||||||
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the given "input" event, typing the data within the input text.
|
* Attempts to mark the given Event as having been handled by this
|
||||||
* If the event is complete (text is provided), handling of "compositionend"
|
* Guacamole.Keyboard. If the Event has already been marked as handled,
|
||||||
* events is suspended, as such events may conflict with input events.
|
* false is returned.
|
||||||
*
|
*
|
||||||
* @private
|
* @param {Event} e
|
||||||
* @param {InputEvent} e
|
* The Event to mark.
|
||||||
* The "input" event to handle.
|
*
|
||||||
|
* @returns {Boolean}
|
||||||
|
* true if the given Event was successfully marked, false if the given
|
||||||
|
* Event was already marked.
|
||||||
*/
|
*/
|
||||||
var handleInput = function handleInput(e) {
|
var markEvent = function markEvent(e) {
|
||||||
|
|
||||||
// Only intercept if handler set
|
// Fail if event is already marked
|
||||||
if (!guac_keyboard.onkeydown && !guac_keyboard.onkeyup) return;
|
if (e[EVENT_MARKER])
|
||||||
|
return false;
|
||||||
|
|
||||||
// Type all content written
|
// Mark event otherwise
|
||||||
if (e.data && !e.isComposing) {
|
e[EVENT_MARKER] = true;
|
||||||
element.removeEventListener("compositionend", handleComposition, false);
|
return true;
|
||||||
guac_keyboard.type(e.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the given "compositionend" event, typing the data within the
|
* Attaches event listeners to the given Element, automatically translating
|
||||||
* composed text. If the event is complete (composed text is provided),
|
* received key, input, and composition events into simple keydown/keyup
|
||||||
* handling of "input" events is suspended, as such events may conflict
|
* events signalled through this Guacamole.Keyboard's onkeydown and
|
||||||
* with composition events.
|
* onkeyup handlers.
|
||||||
*
|
*
|
||||||
* @private
|
* @param {Element} element
|
||||||
* @param {CompositionEvent} e
|
* The Element to attach event listeners to for the sake of handling
|
||||||
* The "compositionend" event to handle.
|
* key or input events.
|
||||||
*/
|
*/
|
||||||
var handleComposition = function handleComposition(e) {
|
this.listenTo = function listenTo(element) {
|
||||||
|
|
||||||
// Only intercept if handler set
|
// When key pressed
|
||||||
if (!guac_keyboard.onkeydown && !guac_keyboard.onkeyup) return;
|
element.addEventListener("keydown", function(e) {
|
||||||
|
|
||||||
// Type all content written
|
// Only intercept if handler set
|
||||||
if (e.data) {
|
if (!guac_keyboard.onkeydown) return;
|
||||||
element.removeEventListener("input", handleInput, false);
|
|
||||||
guac_keyboard.type(e.data);
|
// Ignore events which have already been handled
|
||||||
}
|
if (!markEvent(e)) return;
|
||||||
|
|
||||||
|
var keyCode;
|
||||||
|
if (window.event) keyCode = window.event.keyCode;
|
||||||
|
else if (e.which) keyCode = e.which;
|
||||||
|
|
||||||
|
// Fix modifier states
|
||||||
|
syncModifierStates(e);
|
||||||
|
|
||||||
|
// Ignore (but do not prevent) the "composition" keycode sent by some
|
||||||
|
// browsers when an IME is in use (see: http://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html)
|
||||||
|
if (keyCode === 229)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Log event
|
||||||
|
var keydownEvent = new KeydownEvent(keyCode, e.keyIdentifier, e.key, getEventLocation(e));
|
||||||
|
eventLog.push(keydownEvent);
|
||||||
|
|
||||||
|
// Interpret as many events as possible, prevent default if indicated
|
||||||
|
if (interpret_events())
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
// When key pressed
|
||||||
|
element.addEventListener("keypress", function(e) {
|
||||||
|
|
||||||
|
// Only intercept if handler set
|
||||||
|
if (!guac_keyboard.onkeydown && !guac_keyboard.onkeyup) return;
|
||||||
|
|
||||||
|
// Ignore events which have already been handled
|
||||||
|
if (!markEvent(e)) return;
|
||||||
|
|
||||||
|
var charCode;
|
||||||
|
if (window.event) charCode = window.event.keyCode;
|
||||||
|
else if (e.which) charCode = e.which;
|
||||||
|
|
||||||
|
// Fix modifier states
|
||||||
|
syncModifierStates(e);
|
||||||
|
|
||||||
|
// Log event
|
||||||
|
var keypressEvent = new KeypressEvent(charCode);
|
||||||
|
eventLog.push(keypressEvent);
|
||||||
|
|
||||||
|
// Interpret as many events as possible, prevent default if indicated
|
||||||
|
if (interpret_events())
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
// When key released
|
||||||
|
element.addEventListener("keyup", function(e) {
|
||||||
|
|
||||||
|
// Only intercept if handler set
|
||||||
|
if (!guac_keyboard.onkeyup) return;
|
||||||
|
|
||||||
|
// Ignore events which have already been handled
|
||||||
|
if (!markEvent(e)) return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var keyCode;
|
||||||
|
if (window.event) keyCode = window.event.keyCode;
|
||||||
|
else if (e.which) keyCode = e.which;
|
||||||
|
|
||||||
|
// Fix modifier states
|
||||||
|
syncModifierStates(e);
|
||||||
|
|
||||||
|
// Log event, call for interpretation
|
||||||
|
var keyupEvent = new KeyupEvent(keyCode, e.keyIdentifier, e.key, getEventLocation(e));
|
||||||
|
eventLog.push(keyupEvent);
|
||||||
|
interpret_events();
|
||||||
|
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the given "input" event, typing the data within the input text.
|
||||||
|
* If the event is complete (text is provided), handling of "compositionend"
|
||||||
|
* events is suspended, as such events may conflict with input events.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {InputEvent} e
|
||||||
|
* The "input" event to handle.
|
||||||
|
*/
|
||||||
|
var handleInput = function handleInput(e) {
|
||||||
|
|
||||||
|
// Only intercept if handler set
|
||||||
|
if (!guac_keyboard.onkeydown && !guac_keyboard.onkeyup) return;
|
||||||
|
|
||||||
|
// Ignore events which have already been handled
|
||||||
|
if (!markEvent(e)) return;
|
||||||
|
|
||||||
|
// Type all content written
|
||||||
|
if (e.data && !e.isComposing) {
|
||||||
|
element.removeEventListener("compositionend", handleComposition, true);
|
||||||
|
guac_keyboard.type(e.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the given "compositionend" event, typing the data within the
|
||||||
|
* composed text. If the event is complete (composed text is provided),
|
||||||
|
* handling of "input" events is suspended, as such events may conflict
|
||||||
|
* with composition events.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {CompositionEvent} e
|
||||||
|
* The "compositionend" event to handle.
|
||||||
|
*/
|
||||||
|
var handleComposition = function handleComposition(e) {
|
||||||
|
|
||||||
|
// Only intercept if handler set
|
||||||
|
if (!guac_keyboard.onkeydown && !guac_keyboard.onkeyup) return;
|
||||||
|
|
||||||
|
// Ignore events which have already been handled
|
||||||
|
if (!markEvent(e)) return;
|
||||||
|
|
||||||
|
// Type all content written
|
||||||
|
if (e.data) {
|
||||||
|
element.removeEventListener("input", handleInput, true);
|
||||||
|
guac_keyboard.type(e.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Automatically type text entered into the wrapped field
|
||||||
|
element.addEventListener("input", handleInput, true);
|
||||||
|
element.addEventListener("compositionend", handleComposition, true);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Automatically type text entered into the wrapped element
|
// Listen to given element, if any
|
||||||
element.addEventListener("input", handleInput, false);
|
if (element)
|
||||||
element.addEventListener("compositionend", handleComposition, false);
|
guac_keyboard.listenTo(element);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The unique numerical identifier to assign to the next Guacamole.Keyboard
|
||||||
|
* instance.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type {Number}
|
||||||
|
*/
|
||||||
|
Guacamole.Keyboard._nextID = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The state of all supported keyboard modifiers.
|
* The state of all supported keyboard modifiers.
|
||||||
* @constructor
|
* @constructor
|
||||||
|
Reference in New Issue
Block a user