{"version":3,"file":"index.mjs","sources":[""],"sourcesContent":["import { getDocument } from \"ssr-window\";\r\nimport { getAttr } from \"../../utils/getAttr\";\r\n\r\n/**\r\n * Singleton. Наблюдатель, использующий `MutationObserver` для фиксирования изменений в DOM-дереве и вызывающий специальный метод коллекции `init`, чтобы создать новые вызовы для появившихся элементов, соответствующих селектору коллекции. По умолчанию подключается в самую последнюю очередь.\r\n * По умолчанию `Observer` не реагирует на изменения в следующих тегах: `iframe`, `script`, `svg`, `ymaps`, `object`, `img`, `template`, `picture`. Эти исключения определяются в параметре `observerExcludedTags` для повышения производительности.\r\n * @module Observer\r\n * @param cfg{Object} объект пользовательских настроек\r\n * @param cfg.observerExcludedTags{Array} массив исключаемых из наблюдения тегов\r\n * @param cfg.observerCfg{MutationObserverInit} конфигурация наблюдателя\r\n * @param cfg.excludedSelector{String} селектор для элементов-исключений\r\n * @param cfg.includedSelector{String} селектор для элементов-включений (приоритетнее над исключениями)\r\n * @param cfg.target{HTMLElement|null} наблюдаемый элемент\r\n * @example\r\n * import { Core, Observer } from \"@delement/ui/plugins\"\r\n *\r\n * new Core({\r\n *   ObserverPlugin: () => new Observer({\r\n *     observerExcludedTags: [ \"iframe\", \"script\", \"svg\", \"object\", \"img\", \"template\", \"picture\" ]\r\n *   })\r\n * })\r\n */\r\nexport class Observer {\r\n\r\n  static #instance: Observer | null = null;\r\n\r\n  /**\r\n   * Конфигурация по умолчанию\r\n   * @type {{observerExcludedTags, isDebug: boolean, excludedSelector: string, includedSelector: string, observerCfg: {subtree: boolean, attributes: boolean, childList: boolean, characterData: boolean, attributeOldValue: boolean, characterDataOldValue: boolean}}}\r\n   */\r\n  static defaultCfg = {\r\n    observerExcludedTags: [ \"iframe\", \"script\", \"svg\", \"ymaps\", \"object\", \"img\", \"template\", \"picture\" ],\r\n    observerCfg: {\r\n      attributes: false,\r\n      childList: true,\r\n      subtree: true,\r\n      characterData: false,\r\n      attributeOldValue: false,\r\n      characterDataOldValue: false,\r\n    },\r\n    excludedSelector: \"[data-js-ObserverExclude]\",\r\n    includedSelector: \"[data-js-ObserverInclude]\",\r\n    isDebug: false,\r\n  };\r\n\r\n  /**\r\n   * Хранилище callback-функций классов\r\n   * @type {Object}\r\n   */\r\n  static callbacks = new Map<string, (mutationList: MutationRecord[]) => void>();\r\n\r\n  /**\r\n   * Присвоение в глобальный namespace внутри Core\r\n   * @type {boolean}\r\n   */\r\n  static isApp = true;\r\n\r\n  /**\r\n   * Получает наблюдаемый элемент (по умолчанию body документа)\r\n   * @returns {HTMLElement|null} наблюдаемый элемент\r\n   */\r\n  static getTarget() {\r\n    return getDocument().body;\r\n  }\r\n\r\n  observerExcludedTags: string[];\r\n\r\n   \r\n  observerCfg: MutationObserverInit;\r\n\r\n  excludedSelector: string;\r\n\r\n  includedSelector: string;\r\n\r\n  isDebug: boolean;\r\n\r\n  observer: MutationObserver;\r\n\r\n  isConnected: boolean;\r\n\r\n  constructor(cfg: Partial<typeof Observer.defaultCfg> = {}) {\r\n\r\n    if (Observer.#instance) {\r\n      return Observer.#instance;\r\n    }\r\n\r\n    const {\r\n      observerExcludedTags,\r\n      observerCfg,\r\n      excludedSelector,\r\n      includedSelector,\r\n      isDebug,\r\n      target = Observer.getTarget(),\r\n    } = {\r\n      ...Observer.defaultCfg,\r\n      ...cfg,\r\n    };\r\n    this.observerExcludedTags = observerExcludedTags;\r\n    this.observerCfg = observerCfg;\r\n    this.excludedSelector = excludedSelector;\r\n    this.includedSelector = includedSelector;\r\n    this.isDebug = isDebug;\r\n    this.observer = new MutationObserver(this.#collectionObserveCallback.bind(this));\r\n    this.isConnected = false;\r\n    if (Observer.callbacks.size && target) {\r\n      this.connect(target, this.observerCfg);\r\n    }\r\n    Observer.#instance = this;\r\n  }\r\n\r\n  /**\r\n   * Включает наблюдение за изменениями в DOM\r\n   * @param target{HTMLElement|null=} наблюдаемый элемент, по умолчанию body\r\n   * @param cfg{MutationObserverInit=} конфигурация наблюдателя\r\n   */\r\n   \r\n  connect(target: HTMLElement | null = Observer.getTarget(), cfg: MutationObserverInit = Observer.defaultCfg.observerCfg) {\r\n    if (!this.isConnected && target) {\r\n      this.observer.observe(target, cfg);\r\n      this.isConnected = true;\r\n      if (this.isDebug) {\r\n        console.debug(\"[Observer] connected with config and callbacks: \", cfg, Observer.callbacks);\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Управляет состоянием видимости для наблюдателя у конкретного элемента\r\n   * @param el{Element} DOM-элемент\r\n   * @param isObservable{Boolean=} состояние видимости (true = наблюдаемый, false = исключённый)\r\n   */\r\n  static setElObservableState(el: Element, isObservable = true) {\r\n    const { includedSelector, excludedSelector } = Observer.defaultCfg;\r\n    const included = getAttr(includedSelector);\r\n    const excluded = getAttr(excludedSelector);\r\n    el.setAttribute(isObservable ? included : excluded, \"\");\r\n    el.removeAttribute(isObservable ? excluded : included);\r\n  }\r\n\r\n  /**\r\n   * Проверяет включение тега в массив исключенных тегов\r\n   * @param tagName\r\n   * @returns {boolean}\r\n   */\r\n  #isTagExcluded(tagName: string) {\r\n    return !!this.observerExcludedTags.includes(tagName.toLowerCase());\r\n  }\r\n\r\n  /**\r\n   * Проверяет массив элементов на наличие исключенных тегов\r\n   * @param nodes\r\n   * @returns {boolean}\r\n   */\r\n  #isExcludedEls(nodes: NodeList = [] as unknown as NodeList) {\r\n    return !!nodes.length && [ ...nodes ].every((el) => {\r\n      const { nodeType, tagName } = el as Element;\r\n      return nodeType === 1 && !(el as Element).closest(this.includedSelector) && this.#isTagExcluded(tagName);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Проверка на исключение из наблюдения\r\n   * @param mutationList{MutationRecord} запись из наблюдателя\r\n   * @returns {boolean}\r\n   */\r\n  #isExcludedMutationRecord(mutationList: MutationRecord[]) {\r\n    return [ ...mutationList ].some(({ target, addedNodes = [] as unknown as NodeList, removedNodes = [] as unknown as NodeList }) => {\r\n      const { nodeType, tagName } = target as Element;\r\n      return this.#isExcludedEls(addedNodes) || this.#isExcludedEls(removedNodes) || (nodeType === 1 && ((target as Element).closest(this.excludedSelector) || this.#isTagExcluded(tagName)));\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Callback-функция, вызываемая при изменениях содержимого документа\r\n   * @type {MutationCallback}\r\n   * @param mutationsList{MutationRecord} принимает список массив мутауий\r\n   * @private\r\n   */\r\n  #collectionObserveCallback(mutationsList: MutationRecord[]) {\r\n    if (!this.#isExcludedMutationRecord(mutationsList)) {\r\n      Observer.callbacks.forEach((callback) => callback(mutationsList));\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Проверяет, добавлен ли callback для указанного селектора класса\r\n   * @param selector{String} селектор класса\r\n   * @returns {Boolean} результат проверки\r\n   */\r\n  static isCallbackExist(selector: string) {\r\n    return Observer.callbacks.has(selector);\r\n  }\r\n\r\n  /**\r\n   * Устанавливает callback для класса, вызываемый при изменениях в DOM\r\n   * @param params{Object} параметры подписки\r\n   * @param params.selector{String} селектор класса для идентификации\r\n   * @param params.callback{Function} callback-функция (обычно инициатор класса)\r\n   */\r\n  static set subscribe({ selector, callback }: { selector: string; callback: (mutationList: MutationRecord[]) => void; }) {\r\n    if (typeof selector === \"string\" && typeof callback === \"function\" && !Observer.isCallbackExist(selector)) {\r\n      Observer.callbacks.set(selector, callback);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Удаляет callback по селектору класса\r\n   * @param selector{String} селектор класса для удаления\r\n   */\r\n  static set unsubscribe(selector: string) {\r\n    if (typeof selector === \"string\" && Observer.isCallbackExist(selector)) {\r\n      Observer.callbacks.delete(selector);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Отключает наблюдатель и очищает все callback\r\n   */\r\n  disconnect() {\r\n    if (this.isConnected) {\r\n      this.observer.disconnect();\r\n      this.isConnected = false;\r\n      Observer.callbacks.clear();\r\n      if (this.isDebug) {\r\n        console.debug(\"[Observer] disconnected\");\r\n      }\r\n    }\r\n  }\r\n\r\n}\r\n"],"names":["Observer","static","observerExcludedTags","observerCfg","attributes","childList","subtree","characterData","attributeOldValue","characterDataOldValue","excludedSelector","includedSelector","isDebug","Map","getTarget","getDocument","body","observer","isConnected","constructor","cfg","instance","target","defaultCfg","this","MutationObserver","collectionObserveCallback","bind","callbacks","size","connect","observe","console","debug","setElObservableState","el","isObservable","included","getAttr","excluded","setAttribute","removeAttribute","isTagExcluded","tagName","includes","toLowerCase","isExcludedEls","nodes","length","every","nodeType","closest","isExcludedMutationRecord","mutationList","some","addedNodes","removedNodes","mutationsList","forEach","callback","isCallbackExist","selector","has","subscribe","set","unsubscribe","delete","disconnect","clear"],"mappings":"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"}