aurelia-templating-resources
Version: 
A standard set of behaviors, converters and other resources for use with the Aurelia templating library.
104 lines (96 loc) • 2.19 kB
text/typescript
import {customAttribute} from 'aurelia-templating';
import {bindingMode} from 'aurelia-binding';
import {TaskQueue} from 'aurelia-task-queue';
import {DOM} from 'aurelia-pal';
/**
 * CustomAttribute that binds provided DOM element's focus attribute with a property on the viewmodel.
 */
export class Focus {
  /**
   *@internal
   */
  element: any;
  /**
   *@internal
   */
  taskQueue: any;
  /**
   *@internal
   */
  isAttached: boolean;
  /**
   *@internal
   */
  needsApply: boolean;
  /**
   *@internal
   */
  value: any;
  /**@internal */
  static inject() {
    return [DOM.Element, TaskQueue];
  }
  /**
   * Creates an instance of Focus.
   * @paramelement Target element on where attribute is placed on.
   * @param taskQueue The TaskQueue instance.
   */
  constructor(element, taskQueue) {
    this.element = element;
    this.taskQueue = taskQueue;
    this.isAttached = false;
    this.needsApply = false;
  }
  /**
   * Invoked everytime the bound value changes.
   */
  valueChanged() {
    if (this.isAttached) {
      this._apply();
    } else {
      this.needsApply = true;
    }
  }
  /**
   * @internal
   */
  _apply() {
    if (this.value) {
      this.taskQueue.queueMicroTask(() => {
        if (this.value) {
          this.element.focus();
        }
      });
    } else {
      this.element.blur();
    }
  }
  /**
   * Invoked when the attribute is attached to the DOM.
   */
  attached() {
    this.isAttached = true;
    if (this.needsApply) {
      this.needsApply = false;
      this._apply();
    }
    this.element.addEventListener('focus', this);
    this.element.addEventListener('blur', this);
  }
  /**
   * Invoked when the attribute is detached from the DOM.
   */
  detached() {
    this.isAttached = false;
    this.element.removeEventListener('focus', this);
    this.element.removeEventListener('blur', this);
  }
  handleEvent(e) {
    if (e.type === 'focus') {
      this.value = true;
    } else if (DOM.activeElement !== this.element) {
      this.value = false;
    }
  }
}