diff --git a/packages/core/src/Twig/AppExtension.php b/packages/core/src/Twig/AppExtension.php index 8020ca03d..df2d8b69e 100755 --- a/packages/core/src/Twig/AppExtension.php +++ b/packages/core/src/Twig/AppExtension.php @@ -125,8 +125,8 @@ public function getOpenGraphImageGeneratedPath(PageInterface $page): ?string public function getPagePosition(PageInterface $page): int { - if (null !== $page->getParentPage()) { - return $this->getPagePosition($page->getParentPage()) + 1; + if (null !== ($parentPage = $page->getParentPage())) { + return $this->getPagePosition($parentPage) + 1; } return 1; diff --git a/packages/js-helper/package.json b/packages/js-helper/package.json index 7a24e740f..492c5b3dd 100755 --- a/packages/js-helper/package.json +++ b/packages/js-helper/package.json @@ -1,6 +1,6 @@ { "name": "@pushword/js-helper", - "version": "0.0.96", + "version": "0.0.97", "description": "Pushword front end helpers. ", "author": "Robin@PiedWeb ", "license": "MIT", diff --git a/packages/js-helper/src/MouseSlider.js b/packages/js-helper/src/MouseSlider.js deleted file mode 100644 index 7388abd10..000000000 --- a/packages/js-helper/src/MouseSlider.js +++ /dev/null @@ -1,29 +0,0 @@ -export function mouseSlider(toSlide, speed = 1) { - if (!('ontouchstart' in document.documentElement)) { - toSlide.classList.add('overflow-x-hidden'); - } - let isDown = false; - let startX; - let scrollLeft; - toSlide.addEventListener('mousedown', (e) => { - isDown = true; - //toSlide.classList.add('active'); - startX = e.pageX - toSlide.offsetLeft; - scrollLeft = toSlide.scrollLeft; - }); - toSlide.addEventListener('mouseleave', () => { - isDown = false; - //toSlide.classList.remove('active'); - }); - toSlide.addEventListener('mouseup', () => { - isDown = false; - //toSlide.classList.remove('active'); - }); - toSlide.addEventListener('mousemove', (e) => { - if (!isDown) return; - e.preventDefault(); - const x = e.pageX - toSlide.offsetLeft; - const walk = (x - startX) * speed; - toSlide.scrollLeft = scrollLeft - walk; - }); -} diff --git a/packages/js-helper/src/ScrollEnhancer.js b/packages/js-helper/src/ScrollEnhancer.js new file mode 100644 index 000000000..a444b0340 --- /dev/null +++ b/packages/js-helper/src/ScrollEnhancer.js @@ -0,0 +1,194 @@ +/** + * Demo in Draft + */ + +class ScrollYEnhancer { + constructor( + selector = '.enhance-scroll-y', + chevron = '
', + insertAfterBegin = '
' + ) { + this.chevron = chevron; + this.insertAfterBegin = insertAfterBegin; + window.scrollPreviousDiv = this.scrollPreviousDiv; + window.manageScrollYControllerVisibility = this.manageScrollYControllerVisibility; + + document.querySelectorAll(selector).forEach((element) => { + this.enhanceScrollY(element) + this.mouseSliderY(element) + this.wheelScroll(element) + element.onscroll = function () { + manageScrollYControllerVisibility(this) + } + }) + } + + wheelScroll(element) { + element.addEventListener('wheel', (evt) => { + evt.preventDefault() + element.classList.toggle('scroll-smooth') + element.scrollTop += evt.deltaY + element.classList.toggle('scroll-smooth') + }) + return this + } + + enhanceScrollY(element) { + if (element.scrollHeight <= element.clientHeight) return; + element.insertAdjacentHTML('afterBegin', this.insertAfterBegin); + element.insertAdjacentHTML('afterEnd', this.chevron); + } + + scrollPreviousDiv(element) { + const previousDiv = element.previousElementSibling; + if (!previousDiv) return; + if (element.textContent === '⌄') { + previousDiv.scrollTop += 25; // ~ one line + return; + } + previousDiv.scrollTop = 0; + } + + manageScrollYControllerVisibility(element) { + const scroller = element.parentNode.querySelector('.scroller'); + if (scroller.textContent === '⌄') { + const isAtMaxScroll = element.scrollTop >= element.scrollHeight - element.clientHeight - 10; + if (isAtMaxScroll) { + scroller.textContent = '⌃'; + scroller.classList.add('pt-[11px]'); + scroller.classList.add('text-gray-200'); + } + return; + } else { + scroller.textContent = '⌄'; + scroller.classList.remove('pt-[11px]'); + scroller.classList.remove('text-gray-200'); + } + } + + mouseSliderY(toSlide, speed = 1) { + if ('ontouchstart' in document.documentElement) { + return; + } + toSlide.classList.add('overflow-y-hidden'); + let isDown = false; + let startX; + let scrollTop; + toSlide.addEventListener('mousedown', (e) => { + isDown = true; + //toSlide.classList.add('active'); + startX = e.pageY - toSlide.offsetTop; + scrollTop = toSlide.scrollTop; + }); + toSlide.addEventListener('mouseleave', () => { + isDown = false; + //toSlide.classList.remove('active'); + }); + toSlide.addEventListener('mouseup', () => { + isDown = false; + //toSlide.classList.remove('active'); + }); + toSlide.addEventListener('mousemove', (e) => { + if (!isDown) return; + e.preventDefault(); + const x = e.pageY - toSlide.offsetTop; + const walk = (x - startX) * speed; + toSlide.scrollTop = scrollTop - walk; + }); + } +} + +class ScrollXEnhancer { + constructor( + selector = '.enhance-scroll-x', + chevronRight = '
🠆
', + chevronLeft = '
🠄
' + ) { + this.chevronLeft = chevronLeft; + this.chevronRight = chevronRight; + window.scrollLeft = this.scrollLeft; + window.scrollX = this.scrollX; + window.manageScrollXControllerVisibility = this.manageScrollXControllerVisibility; + + document.querySelectorAll(selector).forEach((element) => { + this.enhanceScrollX(element) + this.mouseSliderX(element) + this.wheelScroll(element) + element.onscroll = function () { + manageScrollXControllerVisibility(this) + } + }) + } + + wheelScroll(element) { + element.addEventListener('wheel', (evt) => { + evt.preventDefault() + if (evt.target.closest('.enhance-scroll-y')) return + if (window.isScrolling === true) return + element.classList.toggle('scroll-smooth') + element.scrollLeft += evt.deltaY + element.classList.toggle('scroll-smooth') + }) + } + + enhanceScrollX(element) { + if (element.scrollWidth <= element.clientWidth) return; + element.insertAdjacentHTML('afterbegin', this.chevronLeft + this.chevronRight); + } + + scrollX(scroller) { + const element = scroller.parentNode; + if (!element) return; + + const scrollToRight = scroller.classList.contains('scroll-right'); + + const oppositeSelector = scrollToRight ? 'scroll-left' : 'scroll-right'; + const oppositeController = element.querySelector('.' + oppositeSelector); + + const nextElementToScroll = element.children[3]; // work only with equal width block + const toScrollWidth = + nextElementToScroll.offsetWidth + + parseInt(window.getComputedStyle(nextElementToScroll).marginLeft); + element.scrollLeft += scrollToRight ? toScrollWidth : -toScrollWidth; + + } + + manageScrollXControllerVisibility(element) { + const scrollLeftElement = element.querySelector('.scroll-left'); + const scrollRightElement = element.querySelector('.scroll-right'); + scrollRightElement.classList.remove('opacity-30'); + scrollLeftElement.classList.remove('opacity-30'); + + const isAtMaxScroll = element.scrollLeft >= element.scrollWidth - element.clientWidth; + if (isAtMaxScroll) scrollRightElement.classList.add('opacity-30'); + if (element.scrollLeft === 0) scrollLeftElement.classList.add('opacity-30'); + } + + mouseSliderX(toSlide, speed = 1) { + if ('ontouchstart' in document.documentElement) { + return; + } + toSlide.classList.add('overflow-x-hidden'); + let isDown = false; + let startX; + let scrollLeft; + toSlide.addEventListener('mousedown', (e) => { + isDown = true; + startX = e.pageX - toSlide.offsetLeft; + scrollLeft = toSlide.scrollLeft; + }); + toSlide.addEventListener('mouseleave', () => { + isDown = false; + }); + toSlide.addEventListener('mouseup', () => { + isDown = false; + }); + toSlide.addEventListener('mousemove', (e) => { + if (!isDown) return; + e.preventDefault(); + const x = e.pageX - toSlide.offsetLeft; + const walk = (x - startX) * speed; + toSlide.scrollLeft = scrollLeft - walk; + }); + } +} diff --git a/packages/skeleton/config/routes/dev/framework.yaml b/packages/skeleton/config/routes/dev/framework.yaml index bcbbf13d0..daa49354c 100755 --- a/packages/skeleton/config/routes/dev/framework.yaml +++ b/packages/skeleton/config/routes/dev/framework.yaml @@ -1,3 +1,3 @@ -_errors: - resource: '@FrameworkBundle/Resources/config/routing/errors.xml' - prefix: /_error +# _errors: +# resource: '@FrameworkBundle/Resources/config/routing/errors.xml' +# prefix: /_error