[Time Conductor] Add popupService

...to consolidate positioning of popups, based on
commonality between InfoService and MCTPopup.
nasa/openmctweb#104.
This commit is contained in:
Victor Woeltjen 2015-10-01 15:26:00 -07:00
parent 571beb8df2
commit 5104a7990a

View File

@ -0,0 +1,135 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed 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.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
function () {
"use strict";
/**
* Displays popup elements at specific positions within the document.
* @memberof platform/commonUI/general
* @constructor
*/
function PopupService($document, $window) {
this.$document = $document;
this.$window = $window;
}
/**
* Options controlling how the popup is displaed.
*
* @typedef PopupOptions
* @memberof platform/commonUI/general
* @property {number} [offsetX] the horizontal distance, in pixels,
* to offset the element in whichever direction it is
* displayed. Defaults to 0.
* @property {number} [offsetY] the vertical distance, in pixels,
* to offset the element in whichever direction it is
* displayed. Defaults to 0.
* @property {number} [marginX] the horizontal position, in pixels,
* after which to prefer to display the element to the left.
* If negative, this is relative to the right edge of the
* page. Defaults to half the window's width.
* @property {number} [marginY] the vertical position, in pixels,
* after which to prefer to display the element upward.
* If negative, this is relative to the right edge of the
* page. Defaults to half the window's height.
* @property {string} [leftClass] class to apply when shifting to the left
* @property {string} [rightClass] class to apply when shifting to the right
* @property {string} [upClass] class to apply when shifting upward
* @property {string} [downClass] class to apply when shifting downward
*/
/**
* Display a popup at a particular location. The location chosen will
* be the corner of the element; the element will be positioned either
* to the left or the right of this point depending on available
* horizontal space, and will similarly be shifted upward or downward
* depending on available vertical space.
*
* @param element the jqLite-wrapped DOM element to pop up
* @param {number[]} position x,y position of the element, in
* pixel coordinates.
* @param {PopupOptions} [options] additional options to control
* positioning of the popup
* @returns {Function} a function that may be invoked to
* dismiss the info bubble
*/
PopupService.prototype.display = function (element, position, options) {
var $document = this.$document,
$window = this.$window,
body = $document.find('body'),
winDim = [ $window.innerWidth, $window.innerHeight ],
margin,
offset,
bubble;
function applyClassOption(direction) {
if (options[direction + 'Class']) {
element.addClass(options[direction + 'Class']);
}
}
// Defaults
options = options || {};
offset = [
options.offsetX !== undefined ? options.offsetX : 0,
options.offsetY !== undefined ? options.offsetY : 0
];
margin = [ options.marginX, options.marginY ].map(function (m, i) {
return m === undefined ? (winDim[i] / 2) :
m < 0 ? (m + winDim[i]) : m;
});
// Position the element
element.css('position', 'absolute');
if (position[0] > margin[0]) {
element.css('right', (winDim[0] - position[0] + offset[0]) + 'px');
applyClassOption('left');
} else {
element.css('left', position[0] + offset[0] + 'px');
applyClassOption('right');
}
if (position[1] > margin[1]) {
element.css('bottom', (winDim[1] - position[1] + offset[1]) + 'px');
applyClassOption('up');
} else {
element.css('top', position[1] + offset[1] + 'px');
applyClassOption('down');
}
// Add the menu to the body
body.append(element);
// Return a function to dismiss the bubble
return function () {
element.remove();
};
};
return PopupService;
}
);