2017-01-31 13:13:06 +00:00
|
|
|
import {module} from '../module';
|
2017-02-07 13:34:26 +00:00
|
|
|
import './style.css';
|
2017-01-31 13:13:06 +00:00
|
|
|
|
|
|
|
directive.$inject = ['vnPopover'];
|
2017-06-03 11:01:47 +00:00
|
|
|
export function directive(vnPopover) {
|
2017-01-31 13:13:06 +00:00
|
|
|
return {
|
|
|
|
restrict: 'A',
|
2017-05-16 10:37:48 +00:00
|
|
|
link: function($scope, $element, $attrs) {
|
2017-01-31 13:13:06 +00:00
|
|
|
$element.on('click', function(event) {
|
2017-06-03 11:01:47 +00:00
|
|
|
vnPopover.showComponent($attrs.vnDialog, $scope, $element);
|
2017-01-31 13:13:06 +00:00
|
|
|
event.preventDefault();
|
|
|
|
});
|
|
|
|
}
|
2017-05-16 10:37:48 +00:00
|
|
|
};
|
2017-01-31 13:13:06 +00:00
|
|
|
}
|
|
|
|
module.directive('vnPopover', directive);
|
|
|
|
|
2017-02-01 09:05:15 +00:00
|
|
|
export class Popover {
|
2017-07-05 11:02:49 +00:00
|
|
|
constructor($document, $compile, $transitions) {
|
2017-02-01 09:05:15 +00:00
|
|
|
this.document = $document[0];
|
|
|
|
this.$compile = $compile;
|
2017-07-05 11:02:49 +00:00
|
|
|
this.$transitions = $transitions;
|
2017-06-15 13:00:43 +00:00
|
|
|
this.removeScope = false;
|
2017-07-05 07:47:24 +00:00
|
|
|
this.popOpens = 0;
|
2017-02-01 09:05:15 +00:00
|
|
|
}
|
2017-07-05 11:02:49 +00:00
|
|
|
_init() {
|
|
|
|
this.docMouseDownHandler = e => this.onDocMouseDown(e);
|
|
|
|
this.document.addEventListener('mousedown', this.docMouseDownHandler);
|
|
|
|
this.docKeyDownHandler = e => this.onDocKeyDown(e);
|
|
|
|
this.document.addEventListener('keydown', this.docKeyDownHandler);
|
|
|
|
this.deregisterCallback = this.$transitions.onStart({},
|
|
|
|
() => this.hideAll());
|
|
|
|
}
|
|
|
|
_destroy() {
|
|
|
|
this.document.removeEventListener('mousedown', this.docMouseDownHandler);
|
|
|
|
this.document.removeEventListener('keydown', this.docKeyDownHandler);
|
|
|
|
this.docMouseDownHandler = null;
|
|
|
|
this.docKeyDownHandler = null;
|
|
|
|
this.deregisterCallback();
|
|
|
|
}
|
2017-07-05 07:47:24 +00:00
|
|
|
show(childElement, parent, popoverId) {
|
2017-06-08 12:57:23 +00:00
|
|
|
this.childElement = childElement;
|
2017-02-01 09:05:15 +00:00
|
|
|
let popover = this.document.createElement('div');
|
2017-07-05 07:47:24 +00:00
|
|
|
this.popOpens++;
|
|
|
|
|
|
|
|
if (!popoverId) {
|
|
|
|
popoverId = 'popover-' + this.popOpens;
|
|
|
|
popover.id = popoverId;
|
|
|
|
}
|
|
|
|
|
2017-02-01 09:05:15 +00:00
|
|
|
popover.className = 'vn-popover';
|
|
|
|
popover.addEventListener('mousedown',
|
2017-06-03 11:01:47 +00:00
|
|
|
e => this.onPopoverMouseDown(e));
|
2017-02-01 09:05:15 +00:00
|
|
|
popover.appendChild(childElement);
|
|
|
|
this.popover = popover;
|
2017-01-31 13:13:06 +00:00
|
|
|
|
2017-02-01 09:05:15 +00:00
|
|
|
let style = popover.style;
|
2017-01-31 13:13:06 +00:00
|
|
|
|
2017-02-01 09:05:15 +00:00
|
|
|
let spacing = 0;
|
|
|
|
let screenMargin = 20;
|
|
|
|
let dblMargin = screenMargin * 2;
|
2017-01-31 13:13:06 +00:00
|
|
|
|
2017-02-01 09:05:15 +00:00
|
|
|
let width = popover.offsetWidth;
|
|
|
|
let height = popover.offsetHeight;
|
|
|
|
let innerWidth = window.innerWidth;
|
|
|
|
let innerHeight = window.innerHeight;
|
2017-01-31 13:13:06 +00:00
|
|
|
|
2017-05-16 10:37:48 +00:00
|
|
|
if (width + dblMargin > innerWidth) {
|
2017-02-01 09:05:15 +00:00
|
|
|
width = innerWidth - dblMargin;
|
2017-05-16 10:37:48 +00:00
|
|
|
style.width = width + 'px';
|
2017-02-01 09:05:15 +00:00
|
|
|
}
|
2017-05-16 10:37:48 +00:00
|
|
|
if (height + dblMargin > innerHeight) {
|
2017-02-01 09:05:15 +00:00
|
|
|
height = innerHeight - dblMargin;
|
2017-05-16 10:37:48 +00:00
|
|
|
style.height = height + 'px';
|
2017-02-01 09:05:15 +00:00
|
|
|
}
|
2017-01-31 13:13:06 +00:00
|
|
|
|
2017-05-16 10:37:48 +00:00
|
|
|
if (parent) {
|
2017-02-01 09:05:15 +00:00
|
|
|
let parentNode = parent;
|
|
|
|
let rect = parentNode.getBoundingClientRect();
|
|
|
|
let left = rect.left;
|
|
|
|
let top = rect.top + spacing + parentNode.offsetHeight;
|
2017-01-31 13:13:06 +00:00
|
|
|
|
2017-05-16 10:37:48 +00:00
|
|
|
if (left + width > innerWidth)
|
2017-02-01 09:05:15 +00:00
|
|
|
left -= (left + width) - innerWidth + margin;
|
2017-05-16 10:37:48 +00:00
|
|
|
if (top + height > innerHeight)
|
2017-02-01 09:05:15 +00:00
|
|
|
top -= height + parentNode.offsetHeight + spacing * 2;
|
2017-01-31 13:13:06 +00:00
|
|
|
|
2017-05-16 10:37:48 +00:00
|
|
|
if (left < 0)
|
2017-02-01 09:05:15 +00:00
|
|
|
left = screenMargin;
|
2017-05-16 10:37:48 +00:00
|
|
|
if (top < 0)
|
2017-02-01 09:05:15 +00:00
|
|
|
top = screenMargin;
|
2017-01-31 13:13:06 +00:00
|
|
|
|
2017-05-16 10:37:48 +00:00
|
|
|
style.top = (top) + 'px';
|
|
|
|
style.left = (left) + 'px';
|
|
|
|
style.minWidth = (rect.width) + 'px';
|
2017-01-31 13:13:06 +00:00
|
|
|
}
|
2017-02-01 09:05:15 +00:00
|
|
|
|
|
|
|
this.document.body.appendChild(popover);
|
2017-06-03 11:01:47 +00:00
|
|
|
|
2017-07-05 07:47:24 +00:00
|
|
|
if (this.popOpens === 1) {
|
2017-07-05 11:02:49 +00:00
|
|
|
this._init();
|
2017-07-05 07:47:24 +00:00
|
|
|
}
|
|
|
|
return popoverId;
|
2017-02-01 09:05:15 +00:00
|
|
|
}
|
|
|
|
showComponent(childComponent, $scope, parent) {
|
|
|
|
let childElement = this.document.createElement(childComponent);
|
2017-07-05 07:47:24 +00:00
|
|
|
let id = 'popover-' + this.popOpens;
|
|
|
|
childElement.id = id;
|
2017-06-15 13:00:43 +00:00
|
|
|
this.removeScope = true;
|
|
|
|
this.$compile(childElement)($scope.$new());
|
2017-07-05 07:47:24 +00:00
|
|
|
this.show(childElement, parent, id);
|
2017-06-08 12:57:23 +00:00
|
|
|
return childElement;
|
2017-02-01 09:05:15 +00:00
|
|
|
}
|
2017-07-05 07:47:24 +00:00
|
|
|
_checkOpens() {
|
|
|
|
this.popOpens = this.document.querySelectorAll('*[id^="popover-"]').length;
|
|
|
|
if (this.popOpens === 0) {
|
2017-07-05 11:02:49 +00:00
|
|
|
this._destroy();
|
2017-06-15 13:00:43 +00:00
|
|
|
}
|
2017-02-01 09:05:15 +00:00
|
|
|
}
|
2017-07-05 07:47:24 +00:00
|
|
|
_removeElement(val) {
|
|
|
|
if (!val) return;
|
|
|
|
let element = angular.element(val);
|
|
|
|
let parent = val.parentNode;
|
|
|
|
if (element.scope() && element.scope().$id > 1) {
|
|
|
|
element.scope().$destroy();
|
|
|
|
}
|
|
|
|
element.remove();
|
|
|
|
if (parent.className.indexOf('vn-popover') !== -1)
|
|
|
|
this._removeElement(parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
hide(id) {
|
|
|
|
let popover = this.document.querySelector(`#${id}`);
|
|
|
|
if (popover) {
|
|
|
|
this._removeElement(popover);
|
|
|
|
}
|
|
|
|
this._checkOpens();
|
|
|
|
}
|
2017-07-05 12:01:03 +00:00
|
|
|
hideChilds(id) {
|
2017-07-05 07:47:24 +00:00
|
|
|
let popovers = this.document.querySelectorAll('*[id^="popover-"]');
|
2017-07-05 12:01:03 +00:00
|
|
|
let idNumber = parseInt(id.split('-')[1], 10);
|
2017-07-05 07:47:24 +00:00
|
|
|
popovers.forEach(
|
|
|
|
val => {
|
2017-07-05 12:41:10 +00:00
|
|
|
if (parseInt(val.id.split('-')[1], 10) > idNumber)
|
2017-07-05 07:47:24 +00:00
|
|
|
this._removeElement(val);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
this._checkOpens();
|
|
|
|
}
|
|
|
|
hideAll() {
|
|
|
|
let popovers = this.document.querySelectorAll('*[id^="popover-"]');
|
|
|
|
popovers.forEach(
|
|
|
|
val => {
|
|
|
|
this._removeElement(val);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
this._checkOpens();
|
|
|
|
}
|
2017-07-05 12:41:10 +00:00
|
|
|
_findPopOver(node) {
|
2017-07-05 07:47:24 +00:00
|
|
|
while (node != null) {
|
2017-07-06 07:02:27 +00:00
|
|
|
if (node.id && node.id.startsWith('popover-')) {
|
2017-07-05 12:41:10 +00:00
|
|
|
return node.id;
|
2017-07-05 07:47:24 +00:00
|
|
|
}
|
|
|
|
node = node.parentNode;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2017-02-01 09:05:15 +00:00
|
|
|
onDocMouseDown(event) {
|
2017-07-05 12:41:10 +00:00
|
|
|
let targetId = this._findPopOver(event.target);
|
2017-07-05 07:47:24 +00:00
|
|
|
if (targetId) {
|
2017-07-05 12:01:03 +00:00
|
|
|
this.hideChilds(targetId);
|
2017-07-05 07:47:24 +00:00
|
|
|
} else {
|
|
|
|
this.hideAll();
|
|
|
|
}
|
2017-02-01 09:05:15 +00:00
|
|
|
}
|
2017-06-03 11:01:47 +00:00
|
|
|
onDocKeyDown(event) {
|
2017-07-05 07:47:24 +00:00
|
|
|
if (event.keyCode === 27) {
|
2017-07-05 12:59:40 +00:00
|
|
|
let targetId = this._findPopOver(this.lastTarget);
|
2017-07-05 07:47:24 +00:00
|
|
|
if (targetId) {
|
2017-07-05 12:01:03 +00:00
|
|
|
this.hideChilds(targetId);
|
2017-07-05 07:47:24 +00:00
|
|
|
} else {
|
|
|
|
this.hideAll();
|
|
|
|
}
|
2017-07-05 12:59:40 +00:00
|
|
|
this.lastTarget = null;
|
2017-07-05 07:47:24 +00:00
|
|
|
}
|
2017-06-03 11:01:47 +00:00
|
|
|
}
|
2017-02-01 09:05:15 +00:00
|
|
|
onPopoverMouseDown(event) {
|
2017-07-05 12:59:40 +00:00
|
|
|
this.lastTarget = event.target;
|
2017-02-01 09:05:15 +00:00
|
|
|
}
|
2017-01-31 13:13:06 +00:00
|
|
|
}
|
2017-07-05 11:02:49 +00:00
|
|
|
Popover.$inject = ['$document', '$compile', '$transitions'];
|
2017-02-01 09:05:15 +00:00
|
|
|
module.service('vnPopover', Popover);
|