{{'CLIENT.HELP_CLIPBOARD' | translate}}
diff --git a/guacamole/src/main/webapp/app/client/templates/guacViewport.html b/guacamole/src/main/webapp/app/client/templates/guacViewport.html new file mode 100644 index 000000000..e31e61aa3 --- /dev/null +++ b/guacamole/src/main/webapp/app/client/templates/guacViewport.html @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/guacamole/src/main/webapp/app/login/directives/guacFocus.js b/guacamole/src/main/webapp/app/element/directives/guacFocus.js similarity index 96% rename from guacamole/src/main/webapp/app/login/directives/guacFocus.js rename to guacamole/src/main/webapp/app/element/directives/guacFocus.js index 2689d1796..693770712 100644 --- a/guacamole/src/main/webapp/app/login/directives/guacFocus.js +++ b/guacamole/src/main/webapp/app/element/directives/guacFocus.js @@ -23,7 +23,7 @@ /** * A directive which allows elements to be manually focused / blurred. */ -angular.module('login').directive('guacFocus', ['$timeout', '$parse', function guacFocus($timeout, $parse) { +angular.module('element').directive('guacFocus', ['$timeout', '$parse', function guacFocus($timeout, $parse) { return { restrict: 'A', diff --git a/guacamole/src/main/webapp/app/element/directives/guacScroll.js b/guacamole/src/main/webapp/app/element/directives/guacScroll.js new file mode 100644 index 000000000..57bbf410c --- /dev/null +++ b/guacamole/src/main/webapp/app/element/directives/guacScroll.js @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2014 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * A directive which allows elements to be manually scrolled, and for their + * scroll state to be observed. + */ +angular.module('element').directive('guacScroll', [function guacScroll() { + + return { + restrict: 'A', + + link: function linkGuacScroll($scope, $element, $attrs) { + + /** + * The current scroll state of the element. + * + * @type ScrollState + */ + var guacScroll = $scope.$eval($attrs.guacScroll); + + /** + * The element which is being scrolled, or monitored for changes + * in scroll. + * + * @type Element + */ + var element = $element[0]; + + /** + * Returns the current left edge of the scrolling rectangle. + * + * @returns {Number} + * The current left edge of the scrolling rectangle. + */ + var getScrollLeft = function getScrollLeft() { + return guacScroll.left; + }; + + /** + * Returns the current top edge of the scrolling rectangle. + * + * @returns {Number} + * The current top edge of the scrolling rectangle. + */ + var getScrollTop = function getScrollTop() { + return guacScroll.top; + }; + + // Update underlying scrollLeft property when left changes + $scope.$watch(getScrollLeft, function scrollLeftChanged(left) { + element.scrollLeft = left; + guacScroll.left = element.scrollLeft; + }); + + // Update underlying scrollTop property when top changes + $scope.$watch(getScrollTop, function scrollTopChanged(top) { + element.scrollTop = top; + guacScroll.top = element.scrollTop; + }); + + } // end guacScroll link function + + }; + +}]); diff --git a/guacamole/src/main/webapp/app/element/elementModule.js b/guacamole/src/main/webapp/app/element/elementModule.js new file mode 100644 index 000000000..f43a0ab96 --- /dev/null +++ b/guacamole/src/main/webapp/app/element/elementModule.js @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2014 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Module for manipulating element state, such as focus or scroll position, as + * well as handling browser events. + */ +angular.module('element', []); diff --git a/guacamole/src/main/webapp/app/element/types/ScrollState.js b/guacamole/src/main/webapp/app/element/types/ScrollState.js new file mode 100644 index 000000000..23d6b336f --- /dev/null +++ b/guacamole/src/main/webapp/app/element/types/ScrollState.js @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2014 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Provides the ScrollState class definition. + */ +angular.module('element').factory('ScrollState', [function defineScrollState() { + + /** + * Creates a new ScrollState, representing the current scroll position of + * an arbitrary element. This constructor initializes the properties of the + * new ScrollState with the corresponding properties of the given template. + * + * @constructor + * @param {ScrollState|Object} [template={}] + * The object whose properties should be copied within the new + * ScrollState. + */ + var ScrollState = function ScrollState(template) { + + // Use empty object by default + template = template || {}; + + /** + * The left edge of the view rectangle within the scrollable area. This + * value naturally increases as the user scrolls right. + * + * @type Number + */ + this.left = template.left || 0; + + /** + * The top edge of the view rectangle within the scrollable area. This + * value naturally increases as the user scrolls down. + * + * @type Number + */ + this.top = template.top || 0; + + }; + + return ScrollState; + +}]); diff --git a/guacamole/src/main/webapp/app/login/loginModule.js b/guacamole/src/main/webapp/app/login/loginModule.js index c6ad0d637..7f7577a80 100644 --- a/guacamole/src/main/webapp/app/login/loginModule.js +++ b/guacamole/src/main/webapp/app/login/loginModule.js @@ -23,4 +23,4 @@ /** * The module for the login functionality. */ -angular.module('login', []); +angular.module('login', ['element']); diff --git a/guacamole/src/main/webapp/app/osk/directives/guacOsk.js b/guacamole/src/main/webapp/app/osk/directives/guacOsk.js index f8891e437..b9ee43963 100644 --- a/guacamole/src/main/webapp/app/osk/directives/guacOsk.js +++ b/guacamole/src/main/webapp/app/osk/directives/guacOsk.js @@ -57,6 +57,13 @@ angular.module('osk').directive('guacOsk', [function guacOsk() { */ var main = $element[0]; + /** + * The element which functions as a detector for size changes. + * + * @type Element + */ + var resizeSensor = $element.find('.resize-sensor')[0]; + /** * Event listener which resizes the current keyboard, if any, such * that it fits within available space. @@ -73,8 +80,10 @@ angular.module('osk').directive('guacOsk', [function guacOsk() { $scope.$watch("layout", function setLayout(layout) { // Remove current keyboard - keyboard = null; - main.innerHTML = ""; + if (keyboard) { + main.removeChild(keyboard.getElement()); + keyboard = null; + } // Load new keyboard if (layout) { @@ -96,18 +105,13 @@ angular.module('osk').directive('guacOsk', [function guacOsk() { $rootScope.$broadcast('guacSyntheticKeyup', keysym); }; - // Resize keyboard whenever window changes size - $window.addEventListener('resize', resizeListener); + // Resize keyboard whenever element changes size + resizeSensor.contentWindow.addEventListener('resize', resizeListener); } }); // end layout scope watch - // Clean up event listeners upon destroy - $scope.$on('$destroy', function destroyKeyboard() { - $window.removeEventListener('resize', resizeListener); - }); - }] }; diff --git a/guacamole/src/main/webapp/app/osk/styles/osk.css b/guacamole/src/main/webapp/app/osk/styles/osk.css index ae5d26bf9..c36d40629 100644 --- a/guacamole/src/main/webapp/app/osk/styles/osk.css +++ b/guacamole/src/main/webapp/app/osk/styles/osk.css @@ -20,6 +20,18 @@ * THE SOFTWARE. */ +.osk .resize-sensor { + height: 100%; + width: 100%; + position: absolute; + left: 0; + top: 0; + overflow: hidden; + border: none; + opacity: 0; + z-index: -1; +} + .guac-keyboard { display: inline-block; width: 100%; diff --git a/guacamole/src/main/webapp/app/osk/templates/blank.html b/guacamole/src/main/webapp/app/osk/templates/blank.html new file mode 100644 index 000000000..62b9f6aa2 --- /dev/null +++ b/guacamole/src/main/webapp/app/osk/templates/blank.html @@ -0,0 +1,22 @@ + + diff --git a/guacamole/src/main/webapp/app/osk/templates/guacOsk.html b/guacamole/src/main/webapp/app/osk/templates/guacOsk.html index 42a73462c..e541dc64b 100644 --- a/guacamole/src/main/webapp/app/osk/templates/guacOsk.html +++ b/guacamole/src/main/webapp/app/osk/templates/guacOsk.html @@ -21,4 +21,7 @@ THE SOFTWARE. --> + + +