LT-275: Creating class and jQuery extension to make an element always stay inside another element boundaries
This commit is contained in:
parent
77de389bb8
commit
4acf844eb1
@ -161,9 +161,9 @@ $gray6 = #303030
|
|||||||
height: 100%
|
height: 100%
|
||||||
padding-left: 6px
|
padding-left: 6px
|
||||||
position: absolute
|
position: absolute
|
||||||
right: -100%
|
right: 0
|
||||||
top: 0
|
top: 0
|
||||||
width: 100%
|
width: 50%
|
||||||
|
|
||||||
.content
|
.content
|
||||||
background-color: $gray6
|
background-color: $gray6
|
||||||
|
|||||||
@ -24,6 +24,9 @@ Template.selectTree.onRendered(() => {
|
|||||||
|
|
||||||
instance.component = component;
|
instance.component = component;
|
||||||
|
|
||||||
|
// Set the margin to display the common section
|
||||||
|
$treeRoot.children('.tree-content').css('margin-right', $treeRoot.width());
|
||||||
|
|
||||||
// Start the component transitions
|
// Start the component transitions
|
||||||
$treeRoot.addClass('started');
|
$treeRoot.addClass('started');
|
||||||
|
|
||||||
@ -96,8 +99,14 @@ Template.selectTree.onRendered(() => {
|
|||||||
|
|
||||||
Template.selectTree.events({
|
Template.selectTree.events({
|
||||||
'click .select-tree-root>.tree-content'(event, instance) {
|
'click .select-tree-root>.tree-content'(event, instance) {
|
||||||
|
// Get the tree root
|
||||||
|
const $treeRoot = $(event.currentTarget).closest('.select-tree-root');
|
||||||
|
|
||||||
// Detect the first interaction with the component and do the animation
|
// Detect the first interaction with the component and do the animation
|
||||||
$(event.currentTarget).parent().addClass('interacted');
|
$treeRoot.addClass('interacted');
|
||||||
|
|
||||||
|
// Remove the margin after the common section is closed
|
||||||
|
$treeRoot.children('.tree-content').css('margin-right', '');
|
||||||
},
|
},
|
||||||
|
|
||||||
'input .tree-search input'(event, instance) {
|
'input .tree-search input'(event, instance) {
|
||||||
|
|||||||
145
Packages/ohif-core/client/ui/bounded/bounded.js
Normal file
145
Packages/ohif-core/client/ui/bounded/bounded.js
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 || window;
|
||||||
|
this.$boundingElement = $(this.boundingElement);
|
||||||
|
this.allowResizing = allowResizing;
|
||||||
|
|
||||||
|
// 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');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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');
|
||||||
|
}
|
||||||
|
|
||||||
|
spatialInfo(element) {
|
||||||
|
// Create the result object
|
||||||
|
const result = {};
|
||||||
|
|
||||||
|
// Get the jQuery object for the element
|
||||||
|
const el = element === window ? window.document.body : element;
|
||||||
|
const $element = $(el);
|
||||||
|
|
||||||
|
// Get the element style
|
||||||
|
const style = el.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 element's start position
|
||||||
|
const offset = $element.offset();
|
||||||
|
result.x0 = offset.left;
|
||||||
|
result.y0 = offset.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 = this.spatialInfo(this.element);
|
||||||
|
const boundingInfo = this.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);
|
||||||
|
} else if (elementInfo.x0 < boundingInfo.x0) {
|
||||||
|
this.$element.css('left', boundingInfo.x0);
|
||||||
|
} else if (elementInfo.x1 > boundingInfo.x1) {
|
||||||
|
this.$element.css('left', boundingInfo.x1 - elementInfo.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
} else if (elementInfo.y0 < boundingInfo.y0) {
|
||||||
|
this.$element.css('top', boundingInfo.y0);
|
||||||
|
} else if (elementInfo.y1 > boundingInfo.y1) {
|
||||||
|
this.$element.css('top', boundingInfo.y1 - elementInfo.height);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,2 +1,3 @@
|
|||||||
|
import './bounded/bounded.js';
|
||||||
import './draggable/draggable.js';
|
import './draggable/draggable.js';
|
||||||
import './resizable/resizable.js';
|
import './resizable/resizable.js';
|
||||||
|
|||||||
@ -39,6 +39,8 @@ class Resizable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
this.defineEventHandlers();
|
||||||
|
|
||||||
for (var x = -1; x <= 1; x++) {
|
for (var x = -1; x <= 1; x++) {
|
||||||
for (var y = -1; y <= 1; y++) {
|
for (var y = -1; y <= 1; y++) {
|
||||||
this.createBound(x, y);
|
this.createBound(x, y);
|
||||||
@ -49,13 +51,23 @@ class Resizable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
this.$element.removeClass('resizable').find('resize-bound').remove();
|
// Remove the instance added classes
|
||||||
|
this.$element.removeClass('resizable resizing');
|
||||||
|
|
||||||
|
// Get the bound borders
|
||||||
|
const $bound = this.$element.find('resize-bound');
|
||||||
|
|
||||||
|
// Remove the bound borders
|
||||||
|
$bound.remove();
|
||||||
|
|
||||||
|
// Detach the event handlers
|
||||||
|
this.detachEventHandlers($bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
attachEventHandlers($bound, xDirection, yDirection) {
|
defineEventHandlers() {
|
||||||
const $window = $(window);
|
this.initResizeHandler = event => {
|
||||||
|
const $window = $(window);
|
||||||
|
|
||||||
const initResizeHandler = event => {
|
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
this.width = this.initialWidth = this.$element.width();
|
this.width = this.initialWidth = this.$element.width();
|
||||||
@ -73,11 +85,12 @@ class Resizable {
|
|||||||
|
|
||||||
this.$element.addClass('resizing');
|
this.$element.addClass('resizing');
|
||||||
|
|
||||||
$window.on('mousemove', resizeHandler);
|
$window.on('mousemove', event.data, this.resizeHandler);
|
||||||
$window.on('mouseup', endResizeHandler);
|
$window.on('mouseup', event.data, this.endResizeHandler);
|
||||||
};
|
};
|
||||||
|
|
||||||
const resizeHandler = event => {
|
this.resizeHandler = event => {
|
||||||
|
const { xDirection, yDirection } = event.data;
|
||||||
let x, y;
|
let x, y;
|
||||||
x = event.clientX < 0 ? 0 : event.clientX;
|
x = event.clientX < 0 ? 0 : event.clientX;
|
||||||
x = x > window.innerWidth ? window.innerWidth : x;
|
x = x > window.innerWidth ? window.innerWidth : x;
|
||||||
@ -113,14 +126,30 @@ class Resizable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const endResizeHandler = event => {
|
this.endResizeHandler = event => {
|
||||||
$window.off('mousemove', resizeHandler);
|
const $window = $(window);
|
||||||
$window.off('mouseup', endResizeHandler);
|
|
||||||
|
$window.off('mousemove', this.resizeHandler);
|
||||||
|
$window.off('mouseup', this.endResizeHandler);
|
||||||
|
|
||||||
this.$element.removeClass('resizing');
|
this.$element.removeClass('resizing');
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
$bound.on('mousedown', initResizeHandler);
|
attachEventHandlers($bound, xDirection, yDirection) {
|
||||||
|
const eventData = {
|
||||||
|
xDirection,
|
||||||
|
yDirection
|
||||||
|
};
|
||||||
|
$bound.on('mousedown', eventData, this.initResizeHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
detachEventHandlers($bound) {
|
||||||
|
const $window = $(window);
|
||||||
|
|
||||||
|
$bound.off('mousedown', this.initResizeHandler);
|
||||||
|
$window.off('mousemove', this.resizeHandler);
|
||||||
|
$window.off('mouseup', this.endResizeHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
createBound(xDirection, yDirection) {
|
createBound(xDirection, yDirection) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user