@logo-elements/component-base
Version:
A set of mixins used by Logo Elements which is extended from Vaadin components.
158 lines (137 loc) • 4.94 kB
JavaScript
/**
* @license
* Copyright LOGO YAZILIM SANAYİ VE TİCARET A.Ş.
*
* Save to the extent permitted by law, you may not use, copy, modify,
* distribute or create derivative works of this material or any part
* of it without the prior written consent of LOGO YAZILIM SANAYİ VE TİCARET A.Ş. Limited.
* Any reproduction of this material must contain this notice.
*/
import { DirHelper } from './dir-helper.js';
/**
* Array of Logo Elements custom element classes that have been subscribed to the dir changes.
*/
const directionSubscribers = [];
const directionUpdater = function () {
const documentDir = getDocumentDir();
directionSubscribers.forEach((element) => {
alignDirs(element, documentDir);
});
};
let scrollType;
const directionObserver = new MutationObserver(directionUpdater);
directionObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['dir'] });
const alignDirs = function (element, documentDir, elementDir = element.getAttribute('dir')) {
if (documentDir) {
element.setAttribute('dir', documentDir);
} else if (elementDir != null) {
element.removeAttribute('dir');
}
};
const getDocumentDir = function () {
return document.documentElement.getAttribute('dir');
};
/**
* A mixin to handle `dir` attribute based on the one set on the `<html>` element.
*
* @polymerMixin
*/
export const DirMixin = (superClass) =>
class LogoElementsDirMixin extends superClass {
static get properties() {
return {
/**
* @protected
*/
dir: {
type: String,
value: '',
reflectToAttribute: true
}
};
}
/** @protected */
static finalize() {
super.finalize();
if (!scrollType) {
scrollType = DirHelper.detectScrollType();
}
}
/** @protected */
connectedCallback() {
super.connectedCallback();
if (!this.hasAttribute('dir')) {
this.__subscribe();
alignDirs(this, getDocumentDir(), null);
}
}
/** @protected */
attributeChangedCallback(name, oldValue, newValue) {
super.attributeChangedCallback(name, oldValue, newValue);
if (name !== 'dir') {
return;
}
const documentDir = getDocumentDir();
// New value equals to the document direction and the element is not subscribed to the changes
const newValueEqlDocDir = newValue === documentDir && directionSubscribers.indexOf(this) === -1;
// Value was emptied and the element is not subscribed to the changes
const newValueEmptied = !newValue && oldValue && directionSubscribers.indexOf(this) === -1;
// New value is different and the old equals to document direction and the element is not subscribed to the changes
const newDiffValue = newValue !== documentDir && oldValue === documentDir;
if (newValueEqlDocDir || newValueEmptied) {
this.__subscribe();
alignDirs(this, documentDir, newValue);
} else if (newDiffValue) {
this.__subscribe(false);
}
}
/** @protected */
disconnectedCallback() {
super.disconnectedCallback();
this.__subscribe(false);
this.removeAttribute('dir');
}
/** @protected */
_valueToNodeAttribute(node, value, attribute) {
// Override default Polymer attribute reflection to match native behavior of HTMLElement.dir property
// If the property contains an empty string then it should not create an empty attribute
if (attribute === 'dir' && value === '' && !node.hasAttribute('dir')) {
return;
}
super._valueToNodeAttribute(node, value, attribute);
}
/** @protected */
_attributeToProperty(attribute, value, type) {
// Override default Polymer attribute reflection to match native behavior of HTMLElement.dir property
// If the attribute is removed, then the dir property should contain an empty string instead of null
if (attribute === 'dir' && !value) {
this.dir = '';
} else {
super._attributeToProperty(attribute, value, type);
}
}
/** @private */
__subscribe(push = true) {
if (push) {
directionSubscribers.indexOf(this) === -1 && directionSubscribers.push(this);
} else {
directionSubscribers.indexOf(this) > -1 && directionSubscribers.splice(directionSubscribers.indexOf(this), 1);
}
}
/**
* @param {Element} element
* @return {number}
* @protected
*/
__getNormalizedScrollLeft(element) {
return DirHelper.getNormalizedScrollLeft(scrollType, this.getAttribute('dir') || 'ltr', element);
}
/**
* @param {Element} element
* @param {number} scrollLeft
* @protected
*/
__setNormalizedScrollLeft(element, scrollLeft) {
return DirHelper.setNormalizedScrollLeft(scrollType, this.getAttribute('dir') || 'ltr', element, scrollLeft);
}
};