Artifact
7fb3b95cb66c0820e4013995a2471de26c50214e4dd8619c14df30f1ee471cf6:
import {
__TAGS_CACHE,
ATTRS_PREFIX,
RIOT_EVENTS_KEY
} from './../../common/global-variables'
import removeAttribute from './../../common/util/dom/remove-attribute'
import walkAttributes from './../../common/util/dom/walk-attributes'
import setInnerHTML from './../../common/util/dom/set-inner-HTML'
import each from './../../common/util/misc/each'
import startsWith from './../../common/util/misc/starts-with'
import unmountAll from './../../common/util/tags/unmount-all'
import arrayishRemove from './../../common/util/tags/arrayish-remove'
import getImmediateCustomParent from './../../common/util/tags/get-immediate-custom-parent'
import setMountState from './../../common/util/tags/set-mount-state'
/**
* Unmount the tag instance
* @param { Boolean } mustKeepRoot - if it's true the root node will not be removed
* @returns { Tag } the current tag instance
*/
export default function tagUnmount(tag, mustKeepRoot, expressions) {
const __ = tag.__
const root = __.root
const tagIndex = __TAGS_CACHE.indexOf(tag)
const p = root.parentNode
if (!__.skipAnonymous) tag.trigger('before-unmount')
// clear all attributes coming from the mounted tag
walkAttributes(__.impl.attrs, (name) => {
if (startsWith(name, ATTRS_PREFIX))
name = name.slice(ATTRS_PREFIX.length)
removeAttribute(root, name)
})
// remove all the event listeners
tag.__.listeners.forEach((dom) => {
Object.keys(dom[RIOT_EVENTS_KEY]).forEach((eventName) => {
dom.removeEventListener(eventName, dom[RIOT_EVENTS_KEY][eventName])
})
})
// remove tag instance from the global tags cache collection
if (tagIndex !== -1) __TAGS_CACHE.splice(tagIndex, 1)
// clean up the parent tags object
if (__.parent && !__.isAnonymous) {
const ptag = getImmediateCustomParent(__.parent)
if (__.isVirtual) {
Object
.keys(tag.tags)
.forEach(tagName => arrayishRemove(ptag.tags, tagName, tag.tags[tagName]))
} else {
arrayishRemove(ptag.tags, __.tagName, tag)
}
}
// unmount all the virtual directives
if (tag.__.virts) {
each(tag.__.virts, (v) => {
if (v.parentNode) v.parentNode.removeChild(v)
})
}
// allow expressions to unmount themselves
unmountAll(expressions)
each(__.instAttrs, a => a.expr && a.expr.unmount && a.expr.unmount())
// clear the tag html if it's necessary
if (mustKeepRoot) setInnerHTML(root, '')
// otherwise detach the root tag from the DOM
else if (p) p.removeChild(root)
// custom internal unmount function to avoid relying on the observable
if (__.onUnmount) __.onUnmount()
// weird fix for a weird edge case #2409 and #2436
// some users might use your software not as you've expected
// so I need to add these dirty hacks to mitigate unexpected issues
if (!tag.isMounted) setMountState.call(tag, true)
setMountState.call(tag, false)
delete root._tag
return tag
}