From 08681e45bc6b404ca197f4c3f29bb32de00b1d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tu=C4=9F=C3=A7e=20K=C3=BC=C3=A7=C3=BCko=C4=9Flu?= Date: Wed, 4 Aug 2021 13:01:03 +0300 Subject: [PATCH] Fixed #1405 - New v-styleclass directive --- src/components/styleclass/StyleClass.d.ts | 5 + src/components/styleclass/StyleClass.js | 165 ++++++++++++++++++++++ src/components/styleclass/package.json | 6 + 3 files changed, 176 insertions(+) create mode 100644 src/components/styleclass/StyleClass.d.ts create mode 100644 src/components/styleclass/StyleClass.js create mode 100644 src/components/styleclass/package.json diff --git a/src/components/styleclass/StyleClass.d.ts b/src/components/styleclass/StyleClass.d.ts new file mode 100644 index 000000000..e21fdfd5c --- /dev/null +++ b/src/components/styleclass/StyleClass.d.ts @@ -0,0 +1,5 @@ +import { ObjectDirective } from 'vue'; + +declare const StyleClass: ObjectDirective; + +export default StyleClass; diff --git a/src/components/styleclass/StyleClass.js b/src/components/styleclass/StyleClass.js new file mode 100644 index 000000000..904c52984 --- /dev/null +++ b/src/components/styleclass/StyleClass.js @@ -0,0 +1,165 @@ +import {DomHandler} from 'primevue/utils'; + +function bind(el, binding) { + el.$_pstyleclass_clicklistener = () => { + const target = resolveTarget(el, binding); + + if (binding.value.toggleClass) { + if (DomHandler.hasClass(target, binding.value.toggleClass)) + DomHandler.removeClass(target, binding.value.toggleClass); + else + DomHandler.addClass(target, binding.value.toggleClass); + } + else { + if (target.offsetParent === null) + enter(target, el, binding); + else + leave(target, binding); + } + }; + el.addEventListener('click', el.$_pstyleclass_clicklistener); +} + +function unbind(el) { + if (el.$_pstyleclass_clicklistener) { + el.addEventListener('click', el.$_pstyleclass_clicklistener); + el.$_pstyleclass_clicklistener = null; + } + + unbindDocumentListener(el); +} + +function enter(target, el, binding) { + if (binding.value.enterActiveClass) { + if (!target.$_pstyleclass_animating) { + target.$_pstyleclass_animating = true; + + if (binding.value.enterActiveClass === 'slidedown') { + target.style.height = '0px'; + DomHandler.removeClass(target, 'hidden'); + target.style.maxHeight = target.scrollHeight + 'px'; + DomHandler.addClass(target, 'hidden'); + target.style.height = ''; + } + + DomHandler.addClass(target, binding.value.enterActiveClass); + if (binding.value.enterClass) { + DomHandler.removeClass(target, binding.value.enterClass); + } + + target.$p_styleclass_enterlistener = () => { + DomHandler.removeClass(target, binding.value.enterActiveClass); + if (binding.value.enterToClass) { + DomHandler.addClass(target, binding.value.enterToClass); + } + target.removeEventListener('animationend', target.$p_styleclass_enterlistener); + + if (binding.value.enterActiveClass === 'slidedown') { + target.style.maxHeight = ''; + } + + target.$_pstyleclass_animating = false; + }; + + target.addEventListener('animationend', target.$p_styleclass_enterlistener); + } + } + else { + if (binding.value.enterClass) { + DomHandler.removeClass(target, binding.value.enterClass); + } + + if (binding.value.enterToClass) { + DomHandler.addClass(target, binding.value.enterToClass); + } + } + + if (binding.value.hideOnOutsideClick) { + bindDocumentListener(target, el, binding); + } +} + +function leave(target, binding) { + if (binding.value.leaveActiveClass) { + if (!target.$_pstyleclass_animating) { + target.$_pstyleclass_animating = true; + DomHandler.addClass(target, binding.value.leaveActiveClass); + if (binding.value.leaveClass) { + DomHandler.removeClass(target, binding.value.leaveClass); + } + + target.$p_styleclass_leavelistener = () => { + DomHandler.removeClass(target, binding.value.leaveActiveClass); + if (binding.value.leaveToClass) { + DomHandler.addClass(target, binding.value.leaveToClass); + } + target.removeEventListener('animationend', target.$p_styleclass_leavelistener); + target.$_pstyleclass_animating = false; + }; + + target.addEventListener('animationend', target.$p_styleclass_leavelistener); + } + } + else { + if (binding.value.leaveClass) { + DomHandler.removeClass(target, binding.value.leaveClass); + } + + if (binding.value.leaveToClass) { + DomHandler.addClass(target, binding.value.leaveToClass); + } + } +} + +function resolveTarget(el, binding) { + switch (binding.value.selector) { + case '@next': + return el.nextElementSibling; + + case '@prev': + return el.previousElementSibling; + + case '@parent': + return el.parentElement; + + case '@grandparent': + return el.parentElement.parentElement; + + default: + return document.querySelector(binding.value.selector); + } +} + +function bindDocumentListener(target, el, binding) { + if (!target.$p_styleclass_documentlistener) { + target.$p_styleclass_documentlistener = (event) => { + if (getComputedStyle(target).getPropertyValue('position') === 'static') { + unbindDocumentListener(target); + } + else if (!el.isSameNode(event.target) && !el.contains(event.target) && !target.contains(event.target)) { + leave(target, binding); + unbindDocumentListener(target); + } + } + + target.ownerDocument.addEventListener('click', target.$p_styleclass_documentlistener); + } +} + +function unbindDocumentListener(target) { + if (target.$p_styleclass_documentlistener) { + target.ownerDocument.removeEventListener('click', target.$p_styleclass_documentlistener); + target.$p_styleclass_documentlistener = null; + } +} + +const StyleClass = { + mounted(el, binding) { + bind(el, binding); + }, + unmounted(el) { + unbind(el); + } +}; + +export default StyleClass; \ No newline at end of file diff --git a/src/components/styleclass/package.json b/src/components/styleclass/package.json new file mode 100644 index 000000000..55956be71 --- /dev/null +++ b/src/components/styleclass/package.json @@ -0,0 +1,6 @@ +{ + "main": "./styleclass.cjs.js", + "module": "./styleclass.esm.js", + "unpkg": "./styleclass.min.js", + "types": "./StyleClass.d.ts" + } \ No newline at end of file