ohif-viewer/Packages/ohif-core/client/ui/bounded/bounded.js
2016-11-15 08:24:01 +01:00

187 lines
6.2 KiB
JavaScript

import { OHIF } from 'meteor/ohif:core';
// Allow attaching to jQuery selectors
$.fn.bounded = function(options) {
_.each(this, element => {
const boundedInstance = $(element).data('boundedInstance');
if (options === 'destroy' && boundedInstance) {
$(element).removeData('boundedInstance');
boundedInstance.destroy();
} else {
if (boundedInstance) {
boundedInstance.options(options);
} else {
$(element).data('boundedInstance', new Bounded(element, options));
}
}
});
return this;
};
/**
* This class makes an element bounded to other element's borders.
*/
class Bounded {
// Initialize the instance with the given element and options
constructor(element, options={}) {
this.element = element;
this.$element = $(element);
this.options(options);
this.setBoundedFlag(false);
}
// Set or change the instance options
options(options={}) {
// Process the given options and store it in the instance
const { boundingElement, allowResizing } = options;
this.boundingElement = boundingElement;
this.$boundingElement = $(this.boundingElement);
this.allowResizing = allowResizing;
// Check for fixed positioning
if (this.$element.css('position') === 'fixed') {
this.boundingElement = window;
}
// Destroy and initialize again the instance
this.destroy();
this.init();
}
// Initialize the bounding behaviour
init() {
// Create the event handlers
this.defineEventHandlers();
// Attach the created event handlers to the component
this.attachEventHandlers();
// Add the bounded class to the element
this.$element.addClass('bounded');
// Trigger the bounding check for the first timepoint
setTimeout(() => this.$element.trigger('spatialChanged'));
}
// Destroy this instance, returning the element to its previous state
destroy() {
// Detach the event handlers
this.detachEventHandlers();
// Remove the bounded class from the element
this.$element.removeClass('bounded');
}
static spatialInfo(element) {
// Create the result object
const result = {};
// Check if the element is the window
if (element === window) {
const $window = $(window);
const width = $window.outerWidth();
const height = $window.outerHeight();
return {
width,
height,
x0: 0,
y0: 0,
x1: width,
y1: height
};
}
// Get the jQuery object for the element
const $element = $(element);
// Get the element style
const style = element.style;
// Get the integer numbers for element's width
if (style.width && style.width.indexOf('px') > -1) {
result.width = parseInt(style.width);
} else {
result.width = $element.outerWidth();
}
// Get the integer numbers for element's height
if (style.height && style.height.indexOf('px') > -1) {
result.height = parseInt(style.height);
} else {
result.height = $element.outerHeight();
}
// Get the position property based on the element position CSS attribute
const positionProperty = $element.css('position') === 'fixed' ? 'position' : 'offset';
// Get the element's start position
const position = $element[positionProperty]();
result.x0 = position.left;
result.y0 = position.top;
// Get the element's end position
result.x1 = result.x0 + result.width;
result.y1 = result.y0 + result.height;
// Return the result object
return result;
}
// Define the event handlers for this class
defineEventHandlers() {
this.spatialChangedHandler = event => {
// Get the spatial information for element and its bounding element
const elementInfo = Bounded.spatialInfo(this.element);
const boundingInfo = Bounded.spatialInfo(this.boundingElement);
// Fix element's x positioning and width
if (this.allowResizing && elementInfo.width > boundingInfo.width) {
this.$element.width(boundingInfo.width);
this.$element.css('left', boundingInfo.x0);
this.setBoundedFlag(true);
} else if (elementInfo.x0 < boundingInfo.x0) {
this.$element.css('left', boundingInfo.x0);
this.setBoundedFlag(true);
} else if (elementInfo.x1 > boundingInfo.x1) {
this.$element.css('left', boundingInfo.x1 - elementInfo.width);
this.setBoundedFlag(true);
}
// Fix element's y positioning and height
if (this.allowResizing && elementInfo.height > boundingInfo.height) {
this.$element.height(boundingInfo.height);
this.$element.css('top', boundingInfo.y0);
this.setBoundedFlag(true);
} else if (elementInfo.y0 < boundingInfo.y0) {
this.$element.css('top', boundingInfo.y0);
this.setBoundedFlag(true);
} else if (elementInfo.y1 > boundingInfo.y1) {
this.$element.css('top', boundingInfo.y1 - elementInfo.height);
this.setBoundedFlag(true);
}
};
}
// Attach the event handlers to the element in order to bound it
attachEventHandlers() {
this.$element.on('spatialChanged', this.spatialChangedHandler);
this.$boundingElement.on('resize', this.spatialChangedHandler);
}
// Detach the event handlers from the element
detachEventHandlers() {
this.$element.off('spatialChanged', this.spatialChangedHandler);
this.$boundingElement.off('resize', this.spatialChangedHandler);
}
// This is a means to let outside world know that the element in question has been moved
setBoundedFlag(value) {
this.$element.data('wasBounded', value);
}
}
OHIF.ui.Bounded = Bounded;