|
import { inject, bindable, Container, ViewEngine, View, bindingMode} from 'aurelia-framework'; |
|
import { DOM } from 'aurelia-pal'; |
|
|
|
@inject(Element, Container, ViewEngine) |
|
export class PickerCustomAttribute { |
|
show = false; |
|
mouseupListener; |
|
focusListener; |
|
divElement; |
|
@bindable({ defaultBindingMode: bindingMode.twoWay }) value; |
|
@bindable({ defaultBindingMode: bindingMode.twoWay }) items; |
|
|
|
constructor(element, container, viewEngine) { |
|
this.element = element; |
|
this.container = container; |
|
this.viewEngine = viewEngine; |
|
this.mouseupListener = e => this.handleMouseUp(e); |
|
this.focusListener = e => this.handleFocus(e); |
|
} |
|
|
|
attached() { |
|
if (this.isInputElement()) { |
|
this.element.addEventListener('focus', this.focusListener); |
|
this.element.addEventListener('blur', this.focusListener); |
|
} else { |
|
this.element.addEventListener('click', this.mouseupListener); |
|
} |
|
} |
|
|
|
detached() { |
|
if (this.isInputElement) { |
|
this.element.removeEventListener('focus', this.focusListener); |
|
this.element.removeEventListener('blur', this.focusListener); |
|
} else { |
|
this.element.removeEventListner('click', this.mouseupListener); |
|
} |
|
document.removeEventListener('mouseup', this.mouseupListener); |
|
} |
|
|
|
pick(item) { |
|
this.value = item; |
|
if (this.isInputElement()) { |
|
//Since we're not binding the value on the input element we update it here. |
|
this.element.value = item; |
|
} |
|
|
|
this.removePicker(); |
|
} |
|
|
|
handleMouseUp(e) { |
|
if (!this.isInputElement() && !this.show) { |
|
this.createPicker(); |
|
} |
|
if (this.show) { |
|
/* |
|
Remove picker if click is outside of it's client rectangle. |
|
*/ |
|
let containerRect = this.divElement.getBoundingClientRect(); |
|
let elementRect = this.element.getBoundingClientRect(); |
|
let inContainerRect = e.clientX > containerRect.left && e.clientX < containerRect.right && e.clientY > containerRect.top && e.clientY < containerRect.bottom; |
|
let inElementRect = e.clientX > elementRect.left && e.clientX < elementRect.right && e.clientY > elementRect.top && e.clientY < elementRect.bottom; |
|
if (!inContainerRect && !inElementRect) { |
|
this.removePicker(); |
|
} |
|
} |
|
} |
|
|
|
handleFocus(e) { |
|
if (e.type === 'focus' && !this.show) { |
|
this.createPicker(); |
|
} |
|
if (e.type === 'blur') { |
|
if (this.isInputElement() && this.element.value !== this.value && typeof this.value !== "undefined") { |
|
this.element.value = this.value |
|
} |
|
} |
|
} |
|
|
|
isInputElement() { |
|
return this.element.nodeType === 1 && this.element.tagName.toLowerCase() == 'input'; |
|
} |
|
|
|
createPicker() { |
|
this.viewEngine.loadViewFactory('./picker.html').then(factory => { |
|
const childContainer = this.container.createChild(); |
|
const view = factory.create(childContainer); |
|
view.bind(this); |
|
|
|
this.addElement(view) |
|
|
|
if (this.isInputElement) |
|
document.addEventListener('mouseup', this.mouseupListener); |
|
|
|
this.show = true; |
|
}) |
|
|
|
} |
|
|
|
removePicker() { |
|
const body = DOM.querySelectorAll('body')[0]; |
|
body.removeChild(this.divElement); |
|
|
|
if (this.isInputElement) |
|
document.removeEventListener('mouseup', this.mouseupListener); |
|
|
|
this.show = false; |
|
|
|
} |
|
|
|
addElement(view) { |
|
const body = DOM.querySelectorAll('body')[0]; |
|
|
|
this.divElement = DOM.createElement('div'); |
|
view.appendNodesTo(this.divElement); |
|
|
|
|
|
const elementRect = this.element.getBoundingClientRect(); |
|
const left = elementRect.left + window.scrollX; |
|
const height = this.divElement.getBoundingClientRect().height; |
|
var top = elementRect.top + elementRect.height; |
|
|
|
top = ((top+height) < window.innerHeight) ? top + window.scrollY : (elementRect.top - height + window.scrollY); |
|
|
|
this.divElement.style.top = top + 'px'; |
|
this.divElement.style.left = left + 'px'; |
|
this.divElement.style.position = 'absolute'; |
|
this.divElement.style.zIndex = '2001'; |
|
|
|
body.insertBefore(this.divElement, body.firstChild); |
|
} |
|
|
|
|
|
} |