From cf2c56c7061b7ed40fdd3b40a352ddb9c9b7371f Mon Sep 17 00:00:00 2001 From: alexwl Date: Tue, 2 Oct 2018 13:17:04 +0300 Subject: Initial commit --- javascript/app/components/info-window.js | 144 +++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 javascript/app/components/info-window.js (limited to 'javascript/app/components/info-window.js') diff --git a/javascript/app/components/info-window.js b/javascript/app/components/info-window.js new file mode 100644 index 0000000..a011f99 --- /dev/null +++ b/javascript/app/components/info-window.js @@ -0,0 +1,144 @@ +import Ember from 'ember'; + +let resizing = false; +let dragging = false; + +function updatePosition(component) { + const targetElement = component.get('targetElement'); + if(targetElement) { + const infoWindowHeight = component.element.offsetHeight; + const targetElementHeight = targetElement.offsetHeight; + + const parent = targetElement.parentNode;// element + const containerElement = document.querySelector("#" + component.get('containerElementId')); + + //getBoundingClientRect() returns the smallest rectangle which contains + //the entire element, with read-only left, top, right, bottom, x, y, width, + //and height properties describing the overall border-box in pixels. Properties + //other than width and height are relative to the top-left of the *viewport*. + const targetTopViewport = targetElement.getBoundingClientRect().top; + + let containerTopViewport; + if (containerElement) { + containerTopViewport = containerElement.getBoundingClientRect().top; + } else { + containerTopViewport = 0; + } + + let infoWindowTop; + if(targetTopViewport < infoWindowHeight + containerTopViewport) { + //offsetTop is the number of pixels from the top of the closest relatively + //positioned parent element. + infoWindowTop = targetElement.offsetTop + parent.offsetTop + + targetElementHeight + 10 + "px"; + } else { + infoWindowTop = targetElement.offsetTop + parent.offsetTop + - infoWindowHeight + "px"; + } + + const infoWindowLeft = targetElement.offsetLeft + parent.offsetLeft + "px"; + + component.$().css({ + top:infoWindowTop, + left:infoWindowLeft + }); + } else { + component.set('isPinned',false); + } +} + +export default Ember.Component.extend({ + classNames : ["info-window-container"], + attributeBindings: ['hidden'], + isPinned : false, + isFocused: false, + didInsertElement () { + const component = this; + + const $headerElement = Ember.$(component.element.querySelector(".info-window-header")); + const $contentElement = Ember.$(component.element.querySelector(".info-window-content")); + const $infoWindowElement = Ember.$(component.element.querySelector(".info-window")); + const $infoWindowContainerElement = Ember.$(component.element); + + this.$headerElement = $headerElement; + this.$contentElement = $contentElement; + + this.$().resizable({ + handles: "n,w", + minHeight: 80, + minWidth: 400, + start: function() { + resizing = true; + }, + stop: function() { + resizing = false; + }, + resize : function() { + const containerHeight = $infoWindowContainerElement.height(); + $infoWindowElement.css({ + "height": containerHeight + 2 + "px" + }); + $contentElement.css({ + "max-height":(containerHeight - $headerElement.outerHeight(true)) + "px" + }); + } + }); + this.$().draggable({ + containment:"#" + this.get('containerElementId'), + handle: $headerElement, + start: function() { + dragging = true; + }, + stop: function() { + dragging = false; + } + }); + }, + mouseEnter () { + if(!this.get('hasSelectedExpression')) { + this.set('isFocused',true); + } + }, + mouseLeave (event) { + //Workaround for a bug in Chrome + const element = document.elementFromPoint(event.clientX,event.clientY); + if(element && element.classList.contains('link')) { + return; + } + if(!resizing + && !dragging + && !this.get('isPinned') + && !this.get('hasSelectedExpression')) { + this.set('isFocused',false); + } + }, + hidden : Ember.computed('isHoveredOverIdentifier', + 'isFocused', + 'hasSelectedExpression', + 'isPinned', function() { + if (this.$contentElement) { + this.$contentElement.scrollTop(0); + } + if (this.get('isPinned') + || this.get('isFocused') + || this.get('isHoveredOverIdentifier') + || this.get('hasSelectedExpression')) { + return false; + } else { + return true; + } + }), + didUpdate() { + updatePosition(this); + }, + actions : { + close() { + this.set('isPinned',false); + this.set('isFocused',false); + this.set('hasSelectedExpression',false); + }, + pin() { + this.toggleProperty('isPinned'); + } + } +}); -- cgit v1.2.3