@ribajs/bs4
Advanced tools
Comparing version 1.9.0-alpha.0 to 1.9.0-alpha.1
{ | ||
"name": "@ribajs/bs4", | ||
"description": "Bootstrap 4 module for Riba.js", | ||
"version": "1.9.0-alpha.0", | ||
"version": "1.9.0-alpha.1", | ||
"author": "Pascal Garber <pascal@artandcode.studio>", | ||
@@ -45,33 +45,41 @@ "contributors": [], | ||
"devDependencies": { | ||
"@babel/cli": "^7.8.4", | ||
"@babel/core": "^7.9.0", | ||
"@babel/plugin-proposal-class-properties": "^7.8.3", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.9.5", | ||
"@babel/plugin-proposal-optional-chaining": "^7.9.0", | ||
"@babel/plugin-syntax-export-default-from": "^7.8.3", | ||
"@babel/preset-env": "^7.9.5", | ||
"@babel/preset-typescript": "^7.9.0", | ||
"@babel/runtime-corejs3": "^7.9.2", | ||
"@ribajs/tsconfig": "1.9.0-alpha.0", | ||
"@babel/cli": "^7.10.4", | ||
"@babel/core": "^7.10.4", | ||
"@babel/plugin-proposal-class-properties": "^7.10.4", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.10.4", | ||
"@babel/plugin-proposal-optional-chaining": "^7.10.4", | ||
"@babel/plugin-syntax-export-default-from": "^7.10.4", | ||
"@babel/plugin-transform-runtime": "^7.10.4", | ||
"@babel/preset-env": "^7.10.4", | ||
"@babel/preset-typescript": "^7.10.4", | ||
"@babel/runtime": "^7.10.4", | ||
"@babel/runtime-corejs3": "^7.10.4", | ||
"@ribajs/eslint-config": "1.9.0-alpha.1", | ||
"@ribajs/tsconfig": "1.9.0-alpha.1", | ||
"@ribajs/types": "1.8.3", | ||
"@types/jest": "^25.2.1", | ||
"@typescript-eslint/eslint-plugin": "^2.29.0", | ||
"@typescript-eslint/parser": "^2.29.0", | ||
"@types/jest": "^26.0.4", | ||
"@typescript-eslint/eslint-plugin": "^3.6.0", | ||
"@typescript-eslint/parser": "^3.6.0", | ||
"@yarnpkg/pnpify": "^2.1.0", | ||
"babel-jest": "^26.1.0", | ||
"babel-loader": "^8.1.0", | ||
"babel-plugin-array-includes": "^2.0.3", | ||
"core-js": "^3.6.5", | ||
"eslint": "^6.8.0", | ||
"jest": "^25.4.0", | ||
"eslint": "^7.4.0", | ||
"eslint-config-prettier": "^6.11.0", | ||
"eslint-plugin-prettier": "^3.1.4", | ||
"jest": "^26.1.0", | ||
"jest-extended": "^0.11.5", | ||
"ts-jest": "^25.4.0", | ||
"typescript": "^3.8.3", | ||
"webpack": "^5.0.0-beta.15", | ||
"webpack-cli": "^3.3.11" | ||
"prettier": "^2.0.5", | ||
"ts-jest": "^26.1.1", | ||
"typescript": "^3.9.6", | ||
"webpack": "^5.0.0-beta.22", | ||
"webpack-cli": "^3.3.12" | ||
}, | ||
"dependencies": { | ||
"@ribajs/cache": "1.9.0-alpha.0", | ||
"@ribajs/core": "1.9.0-alpha.0", | ||
"@ribajs/extras": "1.9.0-alpha.0", | ||
"@ribajs/utils": "1.9.0-alpha.0", | ||
"bootstrap": "^4.4.1", | ||
"@ribajs/cache": "1.9.0-alpha.1", | ||
"@ribajs/core": "1.9.0-alpha.1", | ||
"@ribajs/extras": "1.9.0-alpha.1", | ||
"@ribajs/utils": "1.9.0-alpha.1", | ||
"bootstrap": "^4.5.0", | ||
"popper.js": "^1.16.1" | ||
@@ -78,0 +86,0 @@ }, |
@@ -1,4 +0,4 @@ | ||
import { Binder, EventDispatcher } from '@ribajs/core'; | ||
import { CollapseService } from '../services/collapse.service'; | ||
import { onRoute } from '@ribajs/utils/src/url'; | ||
import { Binder, EventDispatcher } from "@ribajs/core"; | ||
import { CollapseService } from "../services/collapse.service"; | ||
import { onRoute } from "@ribajs/utils/src/url"; | ||
@@ -11,6 +11,6 @@ /** | ||
export const collapseOnUrlBinder: Binder<string> = { | ||
name: 'bs4-collapse-on-url', | ||
name: "bs4-collapse-on-url", | ||
routine(el: HTMLElement, url: string) { | ||
const collapseService = new CollapseService(this.el, [], {toggle: false}); | ||
const dispatcher = new EventDispatcher('main'); | ||
const collapseService = new CollapseService(this.el, [], { toggle: false }); | ||
const dispatcher = new EventDispatcher("main"); | ||
@@ -26,4 +26,4 @@ const checkURL = (urlToCheck?: string) => { | ||
dispatcher.on('newPageReady', () => checkURL(url)); | ||
dispatcher.on("newPageReady", () => checkURL(url)); | ||
}, | ||
}; |
@@ -1,4 +0,4 @@ | ||
import { Binder } from '@ribajs/core'; | ||
import { Binder } from "@ribajs/core"; | ||
// import { CollapseService } from '../services/collapse.service'; | ||
import { CollapseService } from '../services/collapse.service'; | ||
import { CollapseService } from "../services/collapse.service"; | ||
@@ -9,8 +9,9 @@ /** | ||
export const collapseBinder: Binder<string> = { | ||
name: 'bs4-collapse', | ||
name: "bs4-collapse", | ||
bind() { | ||
console.warn('bs4-collapse is deprecated, use bs4-toggle-collapse-on-click instead.'); | ||
console.warn( | ||
"bs4-collapse is deprecated, use bs4-toggle-collapse-on-click instead." | ||
); | ||
}, | ||
routine(el: HTMLElement, targetSelector: string) { | ||
const targets = document.querySelectorAll<HTMLElement>(targetSelector); | ||
@@ -21,6 +22,8 @@ | ||
targets.forEach((target) => { | ||
collapseServices.push(new CollapseService(target, [el], {toggle: false })); | ||
collapseServices.push( | ||
new CollapseService(target, [el], { toggle: false }) | ||
); | ||
}); | ||
el.addEventListener('click', (event) => { | ||
el.addEventListener("click", (event) => { | ||
event.preventDefault(); | ||
@@ -27,0 +30,0 @@ collapseServices.forEach((collapseService) => { |
@@ -1,3 +0,3 @@ | ||
import { Binder } from '@ribajs/core'; | ||
import { DropdownService } from '../services/dropdown.service'; | ||
import { Binder } from "@ribajs/core"; | ||
import { DropdownService } from "../services/dropdown.service"; | ||
@@ -9,9 +9,9 @@ /** | ||
export const dropdownBinder: Binder<string> = { | ||
name: 'bs4-dropdown', | ||
name: "bs4-dropdown", | ||
routine(el: HTMLElement, option: any = {}) { | ||
let toggler: HTMLButtonElement; | ||
if (el.classList.contains('dropdown-toggle')) { | ||
if (el.classList.contains("dropdown-toggle")) { | ||
toggler = el as HTMLButtonElement; | ||
} else { | ||
toggler = el.querySelector('.dropdown-toggle') as HTMLButtonElement; | ||
toggler = el.querySelector(".dropdown-toggle") as HTMLButtonElement; | ||
} | ||
@@ -25,3 +25,3 @@ | ||
toggler.addEventListener('click', () => { | ||
toggler.addEventListener("click", () => { | ||
dropdownService.toggle(); | ||
@@ -28,0 +28,0 @@ }); |
@@ -1,4 +0,4 @@ | ||
import { Binder, EventDispatcher } from '@ribajs/core'; | ||
import { CollapseService } from '../services/collapse.service'; | ||
import { onRoute } from '@ribajs/utils/src/url'; | ||
import { Binder, EventDispatcher } from "@ribajs/core"; | ||
import { CollapseService } from "../services/collapse.service"; | ||
import { onRoute } from "@ribajs/utils/src/url"; | ||
@@ -11,6 +11,6 @@ /** | ||
export const expanOnUrlBinder: Binder<string> = { | ||
name: 'bs4-expan-on-url', | ||
name: "bs4-expan-on-url", | ||
routine(el: HTMLElement, url: string) { | ||
const collapseService = new CollapseService(el, [], {toggle: false}); | ||
const dispatcher = new EventDispatcher('main'); | ||
const collapseService = new CollapseService(el, [], { toggle: false }); | ||
const dispatcher = new EventDispatcher("main"); | ||
@@ -26,3 +26,3 @@ const checkURL = (urlToCheck?: string) => { | ||
dispatcher.on('newPageReady', () => checkURL(url)); | ||
dispatcher.on("newPageReady", () => checkURL(url)); | ||
@@ -29,0 +29,0 @@ checkURL(url); |
@@ -1,3 +0,3 @@ | ||
import { Binder } from '@ribajs/core'; | ||
import { debounce } from '@ribajs/utils/src/control'; | ||
import { Binder } from "@ribajs/core"; | ||
import { debounce } from "@ribajs/utils/src/control"; | ||
@@ -9,3 +9,3 @@ /** | ||
export const scrollspyClassBinder: Binder<string> = { | ||
name: 'bs4-scrollspy-*', | ||
name: "bs4-scrollspy-*", | ||
bind(el: HTMLElement) { | ||
@@ -18,3 +18,3 @@ this.customData = {}; | ||
*/ | ||
this.customData.isInViewport = (elem: Element ): boolean => { | ||
this.customData.isInViewport = (elem: Element): boolean => { | ||
if (!elem) { | ||
@@ -27,3 +27,4 @@ return false; | ||
return ( | ||
distance.top + distance.height >= this.customData.offsetBottom && distance.bottom - distance.height <= this.customData.offsetTop | ||
distance.top + distance.height >= this.customData.offsetBottom && | ||
distance.bottom - distance.height <= this.customData.offsetTop | ||
); | ||
@@ -50,3 +51,3 @@ }; | ||
el.classList.add(className); | ||
if ((el as HTMLInputElement).type === 'radio') { | ||
if ((el as HTMLInputElement).type === "radio") { | ||
(el as HTMLInputElement).checked = true; | ||
@@ -56,3 +57,3 @@ } | ||
el.classList.remove(className); | ||
if ((el as HTMLInputElement).type === 'radio') { | ||
if ((el as HTMLInputElement).type === "radio") { | ||
(el as HTMLInputElement).checked = false; | ||
@@ -62,7 +63,11 @@ } | ||
}; | ||
window.addEventListener('scroll', debounce(this.customData.onScroll.bind(this)), { passive: true }); | ||
window.addEventListener( | ||
"scroll", | ||
debounce(this.customData.onScroll.bind(this)), | ||
{ passive: true } | ||
); | ||
this.customData.onScroll(); | ||
}, | ||
routine(el: HTMLElement, targetSelector: string) { | ||
const nativeIDTargetSelector = targetSelector.replace('#', ''); | ||
const nativeIDTargetSelector = targetSelector.replace("#", ""); | ||
this.customData.target = document.getElementById(nativeIDTargetSelector); | ||
@@ -72,4 +77,7 @@ this.customData.className = this.args[0] as string; | ||
unbind() { | ||
window.removeEventListener('scroll', debounce(this.customData.onScroll.bind(this))); | ||
window.removeEventListener( | ||
"scroll", | ||
debounce(this.customData.onScroll.bind(this)) | ||
); | ||
}, | ||
}; |
@@ -1,6 +0,5 @@ | ||
import { Binder } from '@ribajs/core'; | ||
import { Binder } from "@ribajs/core"; | ||
// import { CollapseService } from '../services/collapse.service'; | ||
import { CollapseService } from '../services/collapse.service'; | ||
import { CollapseService } from "../services/collapse.service"; | ||
export interface Bs4CollapseOnEventBinder extends Binder<boolean> { | ||
@@ -13,6 +12,6 @@ onEvent: (event: Event) => void; | ||
/** | ||
* | ||
* | ||
*/ | ||
export const toggleCollapseOnEventBinder: Binder<string> = { | ||
name: 'bs4-toggle-collapse-on-*', | ||
name: "bs4-toggle-collapse-on-*", | ||
collapseServices: [] as CollapseService[], | ||
@@ -37,3 +36,2 @@ targets: null, | ||
routine(el: HTMLElement, targetSelector: string) { | ||
if (this.args === null) { | ||
@@ -48,7 +46,11 @@ throw new Error("args is null"); | ||
if (self.targets.length <= 0) { | ||
console.warn(`[toggleCollapseOnEventBinder] No element with selector "${targetSelector}" found.`); | ||
console.warn( | ||
`[toggleCollapseOnEventBinder] No element with selector "${targetSelector}" found.` | ||
); | ||
} | ||
self.targets.forEach((target) => { | ||
self.collapseServices.push(new CollapseService(target, [el], {toggle: false })); | ||
self.collapseServices.push( | ||
new CollapseService(target, [el], { toggle: false }) | ||
); | ||
}); | ||
@@ -55,0 +57,0 @@ |
@@ -1,2 +0,2 @@ | ||
import Popper from 'popper.js'; // /dist/umd/popper | ||
import Popper from "popper.js"; // /dist/umd/popper | ||
@@ -8,14 +8,14 @@ /** | ||
*/ | ||
import { Binder } from '@ribajs/core'; | ||
import { Binder } from "@ribajs/core"; | ||
const template = document.createElement('div'); | ||
template.classList.add('tooltip'); | ||
template.setAttribute('role', 'tooltip'); | ||
const template = document.createElement("div"); | ||
template.classList.add("tooltip"); | ||
template.setAttribute("role", "tooltip"); | ||
const arrow = document.createElement('div'); | ||
arrow.classList.add('arrow'); | ||
const arrow = document.createElement("div"); | ||
arrow.classList.add("arrow"); | ||
template.appendChild(arrow); | ||
const inner = document.createElement('div'); | ||
inner.classList.add('tooltip-inner'); | ||
const inner = document.createElement("div"); | ||
inner.classList.add("tooltip-inner"); | ||
template.appendChild(inner); | ||
@@ -27,3 +27,3 @@ | ||
export const tooltipBinder: Binder<string> = { | ||
name: 'bs4-tooltip', | ||
name: "bs4-tooltip", | ||
block: false, | ||
@@ -34,3 +34,8 @@ bind(el: HTMLUnknownElement) { | ||
this.customData.show = () => { | ||
const placement = (this.el.dataset.placement || 'top') as 'auto' | 'top' | 'right' | 'bottom' | 'left'; | ||
const placement = (this.el.dataset.placement || "top") as | ||
| "auto" | ||
| "top" | ||
| "right" | ||
| "bottom" | ||
| "left"; | ||
const offset = 0; | ||
@@ -44,9 +49,9 @@ this.customData.popper = new Popper(el, this.customData.tip, { | ||
flip: { | ||
behavior: 'flip', | ||
behavior: "flip", | ||
}, | ||
arrow: { | ||
element: '.arrow', | ||
element: ".arrow", | ||
}, | ||
preventOverflow: { | ||
boundariesElement: 'scrollParent', | ||
boundariesElement: "scrollParent", | ||
}, | ||
@@ -56,7 +61,7 @@ }, | ||
document.body.appendChild(this.customData.tip); | ||
this.customData.tip.classList.add('show'); | ||
this.customData.tip.classList.add('bs-tooltip-' + placement); | ||
this.customData.tip.classList.add("show"); | ||
this.customData.tip.classList.add("bs-tooltip-" + placement); | ||
}; | ||
this.customData.hide = () => { | ||
this.customData.tip.classList.remove('show'); | ||
this.customData.tip.classList.remove("show"); | ||
if (this.customData.popper) { | ||
@@ -66,8 +71,10 @@ this.customData.popper.destroy(); | ||
}; | ||
el.addEventListener('mouseenter', this.customData.show); | ||
el.addEventListener('mouseleave', this.customData.hide); | ||
el.addEventListener("mouseenter", this.customData.show); | ||
el.addEventListener("mouseleave", this.customData.hide); | ||
}, | ||
routine(el: HTMLElement, text: string) { | ||
const innerEl = this.customData.tip.querySelector('.tooltip-inner') as HTMLDivElement; | ||
const innerEl = this.customData.tip.querySelector( | ||
".tooltip-inner" | ||
) as HTMLDivElement; | ||
innerEl.innerHTML = text; | ||
@@ -78,5 +85,5 @@ }, | ||
this.customData.hide(); | ||
this.el.removeEventListener('mouseenter', this.customData.show); | ||
this.el.removeEventListener('mouseleave', this.customData.hide); | ||
this.el.removeEventListener("mouseenter", this.customData.show); | ||
this.el.removeEventListener("mouseleave", this.customData.hide); | ||
}, | ||
}; |
@@ -1,10 +0,11 @@ | ||
export { collapseOnUrlBinder } from './bs4-collapse-on-url.binder'; | ||
export { collapseBinder } from './bs4-collapse.binder'; | ||
export { toggleCollapseOnEventBinder } from './bs4-toggle-collapse-on-event.binder'; | ||
export { dropdownBinder } from './bs4-dropdown.binder'; | ||
export { expanOnUrlBinder } from './bs4-expan-on-url.binder'; | ||
export { scrollspyClassBinder } from './bs4-scrollspy-class.binder'; | ||
export { tooltipBinder } from './bs4-tooltip.binder'; | ||
export { scrollToOnEventBinder } from './scroll-to-on-event.binder'; | ||
export { toggleAttributeBinder } from './toggle-attribute.binder'; | ||
export { toggleClassBinder } from './toggle-class.binder'; | ||
export { collapseOnUrlBinder } from "./bs4-collapse-on-url.binder"; | ||
export { collapseBinder } from "./bs4-collapse.binder"; | ||
export { toggleCollapseOnEventBinder } from "./bs4-toggle-collapse-on-event.binder"; | ||
export { dropdownBinder } from "./bs4-dropdown.binder"; | ||
export { expanOnUrlBinder } from "./bs4-expan-on-url.binder"; | ||
export { showToastOnEventBinder } from "./bs4-show-toast-on.binder"; | ||
export { scrollspyClassBinder } from "./bs4-scrollspy-class.binder"; | ||
export { tooltipBinder } from "./bs4-tooltip.binder"; | ||
export { scrollToOnEventBinder } from "./scroll-to-on-event.binder"; | ||
export { toggleAttributeBinder } from "./toggle-attribute.binder"; | ||
export { toggleClassBinder } from "./toggle-class.binder"; |
@@ -1,6 +0,6 @@ | ||
import { Binder } from '@ribajs/core'; | ||
import { scrollTo } from '@ribajs/utils/src/dom'; | ||
import { Binder } from "@ribajs/core"; | ||
import { scrollTo } from "@ribajs/utils/src/dom"; | ||
export const scrollToOnEventBinder: Binder<string> = { | ||
name: 'scroll-to-on-*', | ||
name: "scroll-to-on-*", | ||
bind(el: HTMLUnknownElement) { | ||
@@ -10,3 +10,5 @@ this.customData = {}; | ||
const offset = Number(el.dataset.offset || 0); | ||
const scrollElement = el.dataset.scrollElement ? document.querySelector(el.dataset.scrollElement) : window; | ||
const scrollElement = el.dataset.scrollElement | ||
? document.querySelector(el.dataset.scrollElement) | ||
: window; | ||
scrollTo(this.customData.target, offset, scrollElement); | ||
@@ -20,3 +22,3 @@ event.preventDefault(); | ||
if (this.args === null) { | ||
throw new Error('args is null'); | ||
throw new Error("args is null"); | ||
} | ||
@@ -23,0 +25,0 @@ const eventName = this.args[0] as string; |
@@ -1,6 +0,6 @@ | ||
import { Binder, EventDispatcher } from '@ribajs/core'; | ||
import { Binder, EventDispatcher } from "@ribajs/core"; | ||
export interface Bs4ToggleAttribute extends Binder<boolean> { | ||
toggleButtonEvents: EventDispatcher | null; | ||
state: 'removed' | 'added'; | ||
state: "removed" | "added"; | ||
triggerState: () => void; | ||
@@ -13,9 +13,7 @@ onToggle: () => void; | ||
import { | ||
TOGGLE_BUTTON, TOGGLE_ATTRIBUTE, | ||
} from '../constants'; | ||
import { TOGGLE_BUTTON, TOGGLE_ATTRIBUTE } from "../constants"; | ||
/** | ||
* Adds / removes the attribute on click on the bs4-toggle-button with the same id | ||
* E.g. with this binder you can toggle a hidden attribute to show / hide the element | ||
* E.g. with this binder you can toggle a hidden attribute to show / hide the element | ||
* Events | ||
@@ -26,8 +24,11 @@ * * `off` | ||
export const toggleAttributeBinder: Binder<string> = { | ||
name: 'bs4-toggle-attribute-*', | ||
name: "bs4-toggle-attribute-*", | ||
toggleButtonEvents: null, | ||
state: 'off', | ||
state: "off", | ||
triggerState() { | ||
const self = (this.binder || this) as Bs4ToggleAttribute; | ||
self.toggleButtonEvents?.trigger(TOGGLE_BUTTON.eventNames.state, self.state); | ||
self.toggleButtonEvents?.trigger( | ||
TOGGLE_BUTTON.eventNames.state, | ||
self.state | ||
); | ||
}, | ||
@@ -41,3 +42,3 @@ onToggle() { | ||
const self = (this.binder || this) as Bs4ToggleAttribute; | ||
if (self.state === 'removed') { | ||
if (self.state === "removed") { | ||
self.add.bind(this)(el); | ||
@@ -52,4 +53,8 @@ } else { | ||
el.removeAttribute(attributeName); | ||
self.state = 'removed' | ||
el.dispatchEvent(new CustomEvent(TOGGLE_ATTRIBUTE.elEventNames.removed, {detail: {attributeName}})); | ||
self.state = "removed"; | ||
el.dispatchEvent( | ||
new CustomEvent(TOGGLE_ATTRIBUTE.elEventNames.removed, { | ||
detail: { attributeName }, | ||
}) | ||
); | ||
self.triggerState(); | ||
@@ -60,6 +65,10 @@ }, | ||
const attributeName = this.args[0] as string; | ||
el.setAttribute(attributeName, attributeName); | ||
self.state = 'added'; | ||
el.dispatchEvent(new CustomEvent(TOGGLE_ATTRIBUTE.elEventNames.added, {detail: {attributeName}})); | ||
self.state = "added"; | ||
el.dispatchEvent( | ||
new CustomEvent(TOGGLE_ATTRIBUTE.elEventNames.added, { | ||
detail: { attributeName }, | ||
}) | ||
); | ||
self.triggerState(); | ||
@@ -70,3 +79,3 @@ }, | ||
const attributeName = this.args[0] as string; | ||
self.state = el.hasAttribute(attributeName) ? 'added' : 'removed' | ||
self.state = el.hasAttribute(attributeName) ? "added" : "removed"; | ||
}, | ||
@@ -76,4 +85,10 @@ | ||
const self = (this.binder || this) as Bs4ToggleAttribute; | ||
self.toggleButtonEvents?.off(TOGGLE_BUTTON.eventNames.toggle, self.onToggle.bind(this)); | ||
self.toggleButtonEvents?.off(TOGGLE_BUTTON.eventNames.init, self.triggerState.bind(this)); | ||
self.toggleButtonEvents?.off( | ||
TOGGLE_BUTTON.eventNames.toggle, | ||
self.onToggle.bind(this) | ||
); | ||
self.toggleButtonEvents?.off( | ||
TOGGLE_BUTTON.eventNames.init, | ||
self.triggerState.bind(this) | ||
); | ||
}, | ||
@@ -86,14 +101,27 @@ | ||
if (oldId && toggleButton) { | ||
toggleButton.off(TOGGLE_BUTTON.eventNames.toggle, self.onToggle.bind(this)); | ||
toggleButton.off(TOGGLE_BUTTON.eventNames.init, self.triggerState.bind(this)); | ||
toggleButton.off( | ||
TOGGLE_BUTTON.eventNames.toggle, | ||
self.onToggle.bind(this) | ||
); | ||
toggleButton.off( | ||
TOGGLE_BUTTON.eventNames.init, | ||
self.triggerState.bind(this) | ||
); | ||
} | ||
if(!self.toggleButtonEvents) { | ||
self.toggleButtonEvents = new EventDispatcher(TOGGLE_BUTTON.nsPrefix + newId); | ||
if (!self.toggleButtonEvents) { | ||
self.toggleButtonEvents = new EventDispatcher( | ||
TOGGLE_BUTTON.nsPrefix + newId | ||
); | ||
toggleButton = self.toggleButtonEvents as EventDispatcher; | ||
toggleButton.on(TOGGLE_BUTTON.eventNames.toggle, self.onToggle.bind(this)); | ||
toggleButton.on(TOGGLE_BUTTON.eventNames.init, self.triggerState.bind(this)); | ||
toggleButton.on( | ||
TOGGLE_BUTTON.eventNames.toggle, | ||
self.onToggle.bind(this) | ||
); | ||
toggleButton.on( | ||
TOGGLE_BUTTON.eventNames.init, | ||
self.triggerState.bind(this) | ||
); | ||
} | ||
}, | ||
}; |
@@ -1,6 +0,6 @@ | ||
import { Binder, EventDispatcher } from '@ribajs/core'; | ||
import { Binder, EventDispatcher } from "@ribajs/core"; | ||
export interface Bs4ToggleClass extends Binder<boolean> { | ||
toggleButtonEvents: EventDispatcher | null; | ||
state: 'removed' | 'added'; | ||
state: "removed" | "added"; | ||
triggerState: () => void; | ||
@@ -13,5 +13,3 @@ onToggle: () => void; | ||
import { | ||
TOGGLE_BUTTON, TOGGLE_CLASS, | ||
} from '../constants'; | ||
import { TOGGLE_BUTTON, TOGGLE_CLASS } from "../constants"; | ||
@@ -26,8 +24,11 @@ /** | ||
export const toggleClassBinder: Binder<string> = { | ||
name: 'bs4-toggle-class-*', | ||
name: "bs4-toggle-class-*", | ||
toggleButtonEvents: null, | ||
state: 'off', | ||
state: "off", | ||
triggerState() { | ||
const self = (this.binder || this) as Bs4ToggleClass; | ||
self.toggleButtonEvents?.trigger(TOGGLE_BUTTON.eventNames.state, self.state); | ||
self.toggleButtonEvents?.trigger( | ||
TOGGLE_BUTTON.eventNames.state, | ||
self.state | ||
); | ||
}, | ||
@@ -41,3 +42,3 @@ onToggle() { | ||
const self = (this.binder || this) as Bs4ToggleClass; | ||
if (self.state === 'removed') { | ||
if (self.state === "removed") { | ||
self.add.bind(this)(el); | ||
@@ -52,4 +53,8 @@ } else { | ||
el.classList.remove(className); | ||
self.state = 'removed' | ||
el.dispatchEvent(new CustomEvent(TOGGLE_CLASS.elEventNames.removed, {detail: {className}})); | ||
self.state = "removed"; | ||
el.dispatchEvent( | ||
new CustomEvent(TOGGLE_CLASS.elEventNames.removed, { | ||
detail: { className }, | ||
}) | ||
); | ||
self.triggerState(); | ||
@@ -60,6 +65,10 @@ }, | ||
const className = this.args[0] as string; | ||
el.classList.add(className, className); | ||
self.state = 'added'; | ||
el.dispatchEvent(new CustomEvent(TOGGLE_CLASS.elEventNames.added, {detail: {className}})); | ||
self.state = "added"; | ||
el.dispatchEvent( | ||
new CustomEvent(TOGGLE_CLASS.elEventNames.added, { | ||
detail: { className }, | ||
}) | ||
); | ||
self.triggerState(); | ||
@@ -70,3 +79,3 @@ }, | ||
const className = this.args[0] as string; | ||
self.state = el.classList.contains(className) ? 'added' : 'removed' | ||
self.state = el.classList.contains(className) ? "added" : "removed"; | ||
}, | ||
@@ -76,4 +85,10 @@ | ||
const self = (this.binder || this) as Bs4ToggleClass; | ||
self.toggleButtonEvents?.off(TOGGLE_BUTTON.eventNames.toggle, self.onToggle.bind(this)); | ||
self.toggleButtonEvents?.off(TOGGLE_BUTTON.eventNames.init, self.triggerState.bind(this)); | ||
self.toggleButtonEvents?.off( | ||
TOGGLE_BUTTON.eventNames.toggle, | ||
self.onToggle.bind(this) | ||
); | ||
self.toggleButtonEvents?.off( | ||
TOGGLE_BUTTON.eventNames.init, | ||
self.triggerState.bind(this) | ||
); | ||
}, | ||
@@ -86,14 +101,27 @@ | ||
if (oldId && toggleButton) { | ||
toggleButton.off(TOGGLE_BUTTON.eventNames.toggle, self.onToggle.bind(this)); | ||
toggleButton.off(TOGGLE_BUTTON.eventNames.init, self.triggerState.bind(this)); | ||
toggleButton.off( | ||
TOGGLE_BUTTON.eventNames.toggle, | ||
self.onToggle.bind(this) | ||
); | ||
toggleButton.off( | ||
TOGGLE_BUTTON.eventNames.init, | ||
self.triggerState.bind(this) | ||
); | ||
} | ||
if(!self.toggleButtonEvents) { | ||
self.toggleButtonEvents = new EventDispatcher(TOGGLE_BUTTON.nsPrefix + newId); | ||
if (!self.toggleButtonEvents) { | ||
self.toggleButtonEvents = new EventDispatcher( | ||
TOGGLE_BUTTON.nsPrefix + newId | ||
); | ||
toggleButton = self.toggleButtonEvents as EventDispatcher; | ||
toggleButton.on(TOGGLE_BUTTON.eventNames.toggle, self.onToggle.bind(this)); | ||
toggleButton.on(TOGGLE_BUTTON.eventNames.init, self.triggerState.bind(this)); | ||
toggleButton.on( | ||
TOGGLE_BUTTON.eventNames.toggle, | ||
self.onToggle.bind(this) | ||
); | ||
toggleButton.on( | ||
TOGGLE_BUTTON.eventNames.init, | ||
self.triggerState.bind(this) | ||
); | ||
} | ||
}, | ||
}; |
@@ -0,8 +1,7 @@ | ||
import { RibaModule } from "@ribajs/core"; | ||
import { RibaModule } from '@ribajs/core'; | ||
import * as binders from './binders'; | ||
import * as components from './components'; | ||
import * as binders from "./binders"; | ||
import * as components from "./components"; | ||
// import * as formatters from './formatters/bs4.formatters'; | ||
import * as services from './services'; | ||
import * as services from "./services"; | ||
export const bs4Module: RibaModule = { | ||
@@ -9,0 +8,0 @@ binders, |
@@ -0,9 +1,11 @@ | ||
import { handleizeFormatter } from "@ribajs/core"; | ||
import { | ||
handleizeFormatter, | ||
} from '@ribajs/core'; | ||
import { CollapseService, EVENT_HIDE, EVENT_SHOW } from '../../services/collapse.service'; | ||
CollapseService, | ||
EVENT_HIDE, | ||
EVENT_SHOW, | ||
} from "../../services/collapse.service"; | ||
import { TemplatesComponent } from '../templates/templates.component'; | ||
import { TemplatesComponent } from "../templates/templates.component"; | ||
import template from './bs4-accordion.component.html'; | ||
import template from "./bs4-accordion.component.html"; | ||
@@ -14,3 +16,11 @@ interface AccordionItem { | ||
show: boolean; | ||
iconDirection: 'left' | 'left-up' | 'up' | 'up-right' | 'right' | 'right-down' | 'down' | 'down-left'; | ||
iconDirection: | ||
| "left" | ||
| "left-up" | ||
| "up" | ||
| "up-right" | ||
| "right" | ||
| "right-down" | ||
| "down" | ||
| "down-left"; | ||
} | ||
@@ -20,13 +30,13 @@ | ||
items: AccordionItem[]; | ||
toggle: Bs4AccordionComponent['toggle']; | ||
show: Bs4AccordionComponent['show']; | ||
hide: Bs4AccordionComponent['hide']; | ||
toggle: Bs4AccordionComponent["toggle"]; | ||
show: Bs4AccordionComponent["show"]; | ||
hide: Bs4AccordionComponent["hide"]; | ||
collapseIconSrc?: string; | ||
collapseIconSize: number; | ||
showOnlyOne: boolean; | ||
} | ||
export class Bs4AccordionComponent extends TemplatesComponent { | ||
public static tagName = "bs4-accordion"; | ||
public static tagName = 'bs4-accordion'; | ||
protected autobind = true; | ||
@@ -36,11 +46,11 @@ | ||
{ | ||
name: 'title', | ||
name: "title", | ||
required: true, | ||
}, | ||
{ | ||
name: 'show', | ||
name: "show", | ||
required: false, | ||
}, | ||
{ | ||
name: 'icon-direction', | ||
name: "icon-direction", | ||
required: false, | ||
@@ -53,3 +63,3 @@ }, | ||
static get observedAttributes() { | ||
return ['collapse-icon-src', 'collapse-icon-size']; | ||
return ["collapse-icon-src", "collapse-icon-size", "show-only-one"]; | ||
} | ||
@@ -63,2 +73,3 @@ | ||
collapseIconSize: 16, | ||
showOnlyOne: true, | ||
}; | ||
@@ -71,6 +82,8 @@ | ||
public hide(item: AccordionItem, index: number) { | ||
const target = this.el.querySelector<HTMLElement>(`[data-index="${index}"]`); | ||
const target = this.el.querySelector<HTMLElement>( | ||
`[data-index="${index}"]` | ||
); | ||
if (target) { | ||
this.initItemEventListeners(item, target); | ||
new CollapseService(target, [this.el], {toggle: false}).hide(); | ||
new CollapseService(target, [this.el], { toggle: false }).hide(); | ||
} | ||
@@ -80,7 +93,13 @@ } | ||
public show(item: AccordionItem, index: number) { | ||
const target = this.el.querySelector<HTMLElement>(`[data-index="${index}"]`); | ||
const others = Array.from(this.el.querySelectorAll<HTMLElement>(`[data-index]:not([data-index="${index}"])`)); | ||
if (others) { | ||
const target = this.el.querySelector<HTMLElement>( | ||
`[data-index="${index}"]` | ||
); | ||
const others = Array.from( | ||
this.el.querySelectorAll<HTMLElement>( | ||
`[data-index]:not([data-index="${index}"])` | ||
) | ||
); | ||
if (others && this.scope.showOnlyOne) { | ||
for (const other of others) { | ||
new CollapseService(other, [], {toggle: false}).hide(); | ||
new CollapseService(other, [], { toggle: false }).hide(); | ||
} | ||
@@ -90,3 +109,3 @@ } | ||
this.initItemEventListeners(item, target); | ||
new CollapseService(target, [], {toggle: false}).show(); | ||
new CollapseService(target, [], { toggle: false }).show(); | ||
} | ||
@@ -96,7 +115,13 @@ } | ||
public toggle(item: AccordionItem, index: number) { | ||
const target = this.el.querySelector<HTMLElement>(`[data-index="${index}"]`); | ||
const others = Array.from(this.el.querySelectorAll<HTMLElement>(`[data-index]:not([data-index="${index}"])`)); | ||
if (others) { | ||
const target = this.el.querySelector<HTMLElement>( | ||
`[data-index="${index}"]` | ||
); | ||
const others = Array.from( | ||
this.el.querySelectorAll<HTMLElement>( | ||
`[data-index]:not([data-index="${index}"])` | ||
) | ||
); | ||
if (others && this.scope.showOnlyOne) { | ||
for (const other of others) { | ||
new CollapseService(other, [], {toggle: false}).hide(); | ||
new CollapseService(other, [], { toggle: false }).hide(); | ||
} | ||
@@ -106,3 +131,3 @@ } | ||
this.initItemEventListeners(item, target); | ||
new CollapseService(target, [], {toggle: false}).toggle(); | ||
new CollapseService(target, [], { toggle: false }).toggle(); | ||
} | ||
@@ -112,6 +137,20 @@ } | ||
protected initItemEventListeners(item: AccordionItem, element: HTMLElement) { | ||
element.removeEventListener(EVENT_HIDE, this.onHide.bind(this, element, item)); | ||
element.removeEventListener(EVENT_SHOW, this.onShow.bind(this, element, item)); | ||
element.addEventListener(EVENT_HIDE, this.onHide.bind(this, element, item), { once: true }); | ||
element.addEventListener(EVENT_SHOW, this.onShow.bind(this, element, item), { once: true }); | ||
element.removeEventListener( | ||
EVENT_HIDE, | ||
this.onHide.bind(this, element, item) | ||
); | ||
element.removeEventListener( | ||
EVENT_SHOW, | ||
this.onShow.bind(this, element, item) | ||
); | ||
element.addEventListener( | ||
EVENT_HIDE, | ||
this.onHide.bind(this, element, item), | ||
{ once: true } | ||
); | ||
element.addEventListener( | ||
EVENT_SHOW, | ||
this.onShow.bind(this, element, item), | ||
{ once: true } | ||
); | ||
} | ||
@@ -125,3 +164,3 @@ | ||
item.show = true; | ||
item.iconDirection = 'up'; | ||
item.iconDirection = "up"; | ||
const firstContentChild = this.getContentChildByIndex(); | ||
@@ -135,3 +174,3 @@ if (firstContentChild) { | ||
item.show = false; | ||
item.iconDirection = 'down'; | ||
item.iconDirection = "down"; | ||
const firstContentChild = this.getContentChildByIndex(); | ||
@@ -144,5 +183,7 @@ if (firstContentChild) { | ||
protected transformTemplateAttributes(attributes: any) { | ||
attributes.handle = attributes.handle || handleizeFormatter.read(attributes.title); | ||
attributes.handle = | ||
attributes.handle || handleizeFormatter.read(attributes.title); | ||
attributes.show = !!attributes.show; | ||
attributes.iconDirection = attributes.iconDirection || attributes.show ? 'up' : 'down'; | ||
attributes.iconDirection = | ||
attributes.iconDirection || attributes.show ? "up" : "down"; | ||
@@ -155,9 +196,14 @@ return attributes; | ||
* Se also bsf-tabs | ||
* @param element | ||
* @param visibile | ||
* @param element | ||
* @param visibile | ||
*/ | ||
protected triggerVisibilityChangedForElement(element: Element, visibile: boolean) { | ||
protected triggerVisibilityChangedForElement( | ||
element: Element, | ||
visibile: boolean | ||
) { | ||
setTimeout(() => { | ||
// Use this event to update any custom element when it becomes visibile | ||
element.dispatchEvent(new CustomEvent('visibility-changed', {detail: {visibile}})); | ||
element.dispatchEvent( | ||
new CustomEvent("visibility-changed", { detail: { visibile } }) | ||
); | ||
}, 200); | ||
@@ -172,4 +218,3 @@ } | ||
protected async init(observedAttributes: string[]) { | ||
return super.init(observedAttributes) | ||
.then((view) => { | ||
return super.init(observedAttributes).then((view) => { | ||
return view; | ||
@@ -191,4 +236,14 @@ }); | ||
protected parsedAttributeChangedCallback(attributeName: string, oldValue: any, newValue: any, namespace: string | null) { | ||
super.parsedAttributeChangedCallback(attributeName, oldValue, newValue, namespace); | ||
protected parsedAttributeChangedCallback( | ||
attributeName: string, | ||
oldValue: any, | ||
newValue: any, | ||
namespace: string | null | ||
) { | ||
super.parsedAttributeChangedCallback( | ||
attributeName, | ||
oldValue, | ||
newValue, | ||
namespace | ||
); | ||
} | ||
@@ -195,0 +250,0 @@ |
@@ -1,22 +0,19 @@ | ||
import { | ||
Component, | ||
} from '@ribajs/core'; | ||
import { Component } from "@ribajs/core"; | ||
interface Scope { | ||
animationClass: string; | ||
onClick: Bs4ButtonComponent['onClick']; | ||
onClick: Bs4ButtonComponent["onClick"]; | ||
} | ||
export class Bs4ButtonComponent extends Component { | ||
public static tagName = "bs4-button"; | ||
public static tagName = 'bs4-button'; | ||
protected autobind = true; | ||
static get observedAttributes() { | ||
return ['animation-class']; | ||
return ["animation-class"]; | ||
} | ||
protected scope: Scope = { | ||
animationClass: 'btn-animation-start', | ||
animationClass: "btn-animation-start", | ||
onClick: this.onClick, | ||
@@ -58,9 +55,17 @@ }; | ||
protected async init(observedAttributes: string[]) { | ||
return super.init(observedAttributes) | ||
.then((view) => { | ||
this.el.addEventListener('webkitAnimationStart' as 'animationstart', this.onStartAnimation.bind(this)); | ||
this.el.addEventListener('animationstart', this.onStartAnimation.bind(this)); | ||
this.el.addEventListener('webkitAnimationEnd' as 'animationend', this.onEndAnimation.bind(this)); | ||
this.el.addEventListener('animationend', this.onEndAnimation.bind(this)); | ||
this.el.addEventListener('click', this.onClick.bind(this)); | ||
return super.init(observedAttributes).then((view) => { | ||
this.el.addEventListener( | ||
"webkitAnimationStart" as "animationstart", | ||
this.onStartAnimation.bind(this) | ||
); | ||
this.el.addEventListener( | ||
"animationstart", | ||
this.onStartAnimation.bind(this) | ||
); | ||
this.el.addEventListener( | ||
"webkitAnimationEnd" as "animationend", | ||
this.onEndAnimation.bind(this) | ||
); | ||
this.el.addEventListener("animationend", this.onEndAnimation.bind(this)); | ||
this.el.addEventListener("click", this.onClick.bind(this)); | ||
return view; | ||
@@ -84,4 +89,14 @@ }); | ||
protected parsedAttributeChangedCallback(attributeName: string, oldValue: any, newValue: any, namespace: string | null) { | ||
super.parsedAttributeChangedCallback(attributeName, oldValue, newValue, namespace); | ||
protected parsedAttributeChangedCallback( | ||
attributeName: string, | ||
oldValue: any, | ||
newValue: any, | ||
namespace: string | null | ||
) { | ||
super.parsedAttributeChangedCallback( | ||
attributeName, | ||
oldValue, | ||
newValue, | ||
namespace | ||
); | ||
} | ||
@@ -92,7 +107,16 @@ | ||
super.disconnectedCallback(); | ||
this.el.removeEventListener('webkitAnimationStart' as 'animationstart', this.onStartAnimation.bind(this)); | ||
this.el.removeEventListener('animationstart', this.onStartAnimation.bind(this)); | ||
this.el.removeEventListener('webkitAnimationEnd' as 'animationend', this.onEndAnimation.bind(this)); | ||
this.el.removeEventListener('animationend', this.onEndAnimation.bind(this)); | ||
this.el.removeEventListener('click', this.onClick.bind(this)); | ||
this.el.removeEventListener( | ||
"webkitAnimationStart" as "animationstart", | ||
this.onStartAnimation.bind(this) | ||
); | ||
this.el.removeEventListener( | ||
"animationstart", | ||
this.onStartAnimation.bind(this) | ||
); | ||
this.el.removeEventListener( | ||
"webkitAnimationEnd" as "animationend", | ||
this.onEndAnimation.bind(this) | ||
); | ||
this.el.removeEventListener("animationend", this.onEndAnimation.bind(this)); | ||
this.el.removeEventListener("click", this.onClick.bind(this)); | ||
} | ||
@@ -99,0 +123,0 @@ |
@@ -1,31 +0,39 @@ | ||
import { Component } from '@ribajs/core'; | ||
import CarouselService from '../../services/carousel.service'; | ||
import { CarouselOption } from '../../interfaces' | ||
import { Component } from "@ribajs/core"; | ||
import CarouselService from "../../services/carousel.service"; | ||
import { CarouselOption } from "../../interfaces"; | ||
export interface Scope { | ||
// Properties | ||
interval: CarouselOption['interval']; | ||
keyboard: CarouselOption['keyboard']; | ||
slide: CarouselOption['slide']; | ||
pauseOn: CarouselOption['pause']; | ||
wrap: CarouselOption['wrap']; | ||
touch: CarouselOption['touch']; | ||
ride: CarouselOption['ride']; // TODO | ||
interval: CarouselOption["interval"]; | ||
keyboard: CarouselOption["keyboard"]; | ||
slide: CarouselOption["slide"]; | ||
pauseOn: CarouselOption["pause"]; | ||
wrap: CarouselOption["wrap"]; | ||
touch: CarouselOption["touch"]; | ||
ride: CarouselOption["ride"]; // TODO | ||
fade: boolean; | ||
// Methods | ||
next: Bs4CarouselComponent['next']; | ||
nextWhenVisible: Bs4CarouselComponent['nextWhenVisible']; | ||
prev: Bs4CarouselComponent['prev']; | ||
pause: Bs4CarouselComponent['pause']; | ||
cycle: Bs4CarouselComponent['cycle']; | ||
to: Bs4CarouselComponent['to']; | ||
dispose: Bs4CarouselComponent['dispose']; | ||
next: Bs4CarouselComponent["next"]; | ||
nextWhenVisible: Bs4CarouselComponent["nextWhenVisible"]; | ||
prev: Bs4CarouselComponent["prev"]; | ||
pause: Bs4CarouselComponent["pause"]; | ||
cycle: Bs4CarouselComponent["cycle"]; | ||
to: Bs4CarouselComponent["to"]; | ||
dispose: Bs4CarouselComponent["dispose"]; | ||
} | ||
export class Bs4CarouselComponent extends Component { | ||
public static tagName = "bs4-carousel"; | ||
public static tagName = 'bs4-carousel'; | ||
static get observedAttributes() { | ||
return ['interval', 'keyboard', 'slide', 'pauseOn', 'wrap', 'touch', 'ride', 'fade']; | ||
return [ | ||
"interval", | ||
"keyboard", | ||
"slide", | ||
"pauseOn", | ||
"wrap", | ||
"touch", | ||
"ride", | ||
"fade", | ||
]; | ||
} | ||
@@ -67,3 +75,3 @@ | ||
await super.beforeBind(); | ||
this.el.classList.add('carousel', 'slide'); | ||
this.el.classList.add("carousel", "slide"); | ||
} | ||
@@ -79,6 +87,6 @@ | ||
wrap: this.scope.wrap, | ||
touch: this.scope.touch, | ||
touch: this.scope.touch, | ||
}); | ||
if (this.scope.fade) { | ||
this.el.classList.add('carousel-fade'); | ||
this.el.classList.add("carousel-fade"); | ||
} | ||
@@ -131,3 +139,8 @@ // TODO make this configurateable? | ||
public attributeChangedCallback(name: string, oldValue: any, newValue: any, namespace: string | null) { | ||
public attributeChangedCallback( | ||
name: string, | ||
oldValue: any, | ||
newValue: any, | ||
namespace: string | null | ||
) { | ||
super.attributeChangedCallback(name, oldValue, newValue, namespace); | ||
@@ -134,0 +147,0 @@ } |
@@ -1,4 +0,4 @@ | ||
import { Component } from '@ribajs/core'; | ||
import { Component } from "@ribajs/core"; | ||
import template from './bs4-contents.component.html'; | ||
import template from "./bs4-contents.component.html"; | ||
@@ -44,5 +44,4 @@ export interface Anchor { | ||
export class Bs4ContentsComponent extends Component { | ||
public static tagName = "bs4-contents"; | ||
public static tagName = 'bs4-contents'; | ||
protected autobind = true; | ||
@@ -53,3 +52,10 @@ | ||
static get observedAttributes() { | ||
return ['headers-start', 'headers-depth', 'find-header-id-depth', 'header-parent-selector', 'scroll-offset', 'scroll-element']; | ||
return [ | ||
"headers-start", | ||
"headers-depth", | ||
"find-header-id-depth", | ||
"header-parent-selector", | ||
"scroll-offset", | ||
"scroll-element", | ||
]; | ||
} | ||
@@ -75,3 +81,6 @@ | ||
protected getIdFromElementOrParent(element: HTMLElement, depth = 1): string | null { | ||
protected getIdFromElementOrParent( | ||
element: HTMLElement, | ||
depth = 1 | ||
): string | null { | ||
if (element.id) { | ||
@@ -88,4 +97,11 @@ return element.id; | ||
protected pushHeaders(wrapperElement: Element, headersStart: number, headersDepth: number, pushTo: Anchor[]) { | ||
const headerElements = wrapperElement.querySelectorAll('h' + headersStart) as NodeListOf<HTMLHeadingElement>; | ||
protected pushHeaders( | ||
wrapperElement: Element, | ||
headersStart: number, | ||
headersDepth: number, | ||
pushTo: Anchor[] | ||
) { | ||
const headerElements = wrapperElement.querySelectorAll( | ||
"h" + headersStart | ||
) as NodeListOf<HTMLHeadingElement>; | ||
headerElements.forEach((headerElement) => { | ||
@@ -98,3 +114,3 @@ const id = this.getIdFromElementOrParent(headerElement); | ||
element: headerElement, | ||
href: '#' + id, | ||
href: "#" + id, | ||
title: headerElement.innerHTML, | ||
@@ -104,3 +120,8 @@ childs: [], | ||
if (headerElement.parentElement && headersDepth >= headersStart + 1) { | ||
this.pushHeaders(headerElement.parentElement, headersStart + 1, headersDepth, pushTo[pushTo.length - 1].childs); | ||
this.pushHeaders( | ||
headerElement.parentElement, | ||
headersStart + 1, | ||
headersDepth, | ||
pushTo[pushTo.length - 1].childs | ||
); | ||
} | ||
@@ -116,10 +137,20 @@ }); | ||
await super.afterBind(); | ||
if (this.scope.headerParentSelector && this.scope.headersStart && this.scope.headersDepth) { | ||
this.wrapperElement = document.querySelector(this.scope.headerParentSelector) || undefined; | ||
if ( | ||
this.scope.headerParentSelector && | ||
this.scope.headersStart && | ||
this.scope.headersDepth | ||
) { | ||
this.wrapperElement = | ||
document.querySelector(this.scope.headerParentSelector) || undefined; | ||
this.scope.anchors = []; | ||
if (!this.wrapperElement) { | ||
console.error('No wrapper element found!'); | ||
console.error("No wrapper element found!"); | ||
return; | ||
} | ||
this.pushHeaders(this.wrapperElement, this.scope.headersStart, this.scope.headersDepth, this.scope.anchors); | ||
this.pushHeaders( | ||
this.wrapperElement, | ||
this.scope.headersStart, | ||
this.scope.headersDepth, | ||
this.scope.anchors | ||
); | ||
} | ||
@@ -129,7 +160,17 @@ } | ||
protected requiredAttributes() { | ||
return ['headersStart', 'headersDepth', 'headerParentSelector']; | ||
return ["headersStart", "headersDepth", "headerParentSelector"]; | ||
} | ||
protected attributeChangedCallback(attributeName: string, oldValue: any, newValue: any, namespace: string | null) { | ||
super.attributeChangedCallback(attributeName, oldValue, newValue, namespace); | ||
protected attributeChangedCallback( | ||
attributeName: string, | ||
oldValue: any, | ||
newValue: any, | ||
namespace: string | null | ||
) { | ||
super.attributeChangedCallback( | ||
attributeName, | ||
oldValue, | ||
newValue, | ||
namespace | ||
); | ||
} | ||
@@ -136,0 +177,0 @@ |
@@ -1,8 +0,7 @@ | ||
import { Component } from '@ribajs/core'; | ||
import { DropdownService } from '../../services/dropdown.service'; | ||
import { Component } from "@ribajs/core"; | ||
import { DropdownService } from "../../services/dropdown.service"; | ||
export class Bs4DropdownComponent extends Component { | ||
public static tagName = "bs4-dropdown"; | ||
public static tagName = 'bs4-dropdown'; | ||
protected scope: any = { | ||
@@ -26,3 +25,3 @@ toggle: this.toggle, | ||
if (!this.dropdownService) { | ||
throw new Error('DropdownService not ready!'); | ||
throw new Error("DropdownService not ready!"); | ||
} | ||
@@ -34,3 +33,7 @@ return this.dropdownService.toggle(); | ||
super.connectedCallback(); | ||
this.dropdownService = new DropdownService(this.el.querySelector('.dropdown-toggle') as HTMLButtonElement | HTMLAnchorElement); | ||
this.dropdownService = new DropdownService( | ||
this.el.querySelector(".dropdown-toggle") as | ||
| HTMLButtonElement | ||
| HTMLAnchorElement | ||
); | ||
this.init(Bs4DropdownComponent.observedAttributes); | ||
@@ -37,0 +40,0 @@ } |
@@ -1,9 +0,8 @@ | ||
import { Component } from '@ribajs/core'; | ||
import { Component } from "@ribajs/core"; | ||
export class Bs4IconComponent extends Component { | ||
public static tagName = "bs4-icon"; | ||
public static tagName = 'bs4-icon'; | ||
static get observedAttributes() { | ||
return ['size', 'width', 'height', 'src', 'color', 'direction']; | ||
return ["size", "width", "height", "src", "color", "direction"]; | ||
} | ||
@@ -19,44 +18,67 @@ | ||
public attributeChangedCallback(name: string, oldValue: any, newValue: any, namespace: string | null) { | ||
public attributeChangedCallback( | ||
name: string, | ||
oldValue: any, | ||
newValue: any, | ||
namespace: string | null | ||
) { | ||
// injects the changed attributes to scope | ||
super.attributeChangedCallback(name, oldValue, newValue, namespace); | ||
if (name === 'src') { | ||
if (name === "src") { | ||
if (!newValue) { | ||
console.warn('The src attribute must have a value!'); | ||
return ''; | ||
console.warn("The src attribute must have a value!", this.scope); | ||
return ""; | ||
} | ||
if (fetch) { | ||
fetch(newValue) | ||
.then((response) => { | ||
// console.debug('response.headers.get("content-type")', response.headers.get('content-type')); | ||
if (response.status !== 200) { | ||
console.error(response.statusText); | ||
return ''; | ||
} | ||
if (response.headers.get('content-type')?.indexOf('image/svg+xml') !== -1) { | ||
return response.text(); | ||
} else { | ||
console.error('[bs4-icon] Only svg\'s are supported! But content-type is ' + response.headers.get('content-type')); | ||
} | ||
return ''; | ||
}) | ||
.then((response) => { | ||
this.el.innerHTML = response; | ||
}) | ||
.catch((error) => { | ||
console.error(error); | ||
}); | ||
.then((response) => { | ||
// console.debug('response.headers.get("content-type")', response.headers.get('content-type')); | ||
if (response.status !== 200) { | ||
console.error(response.statusText); | ||
return ""; | ||
} | ||
if ( | ||
response.headers.get("content-type")?.indexOf("image/svg+xml") !== | ||
-1 | ||
) { | ||
return response.text(); | ||
} else { | ||
console.error( | ||
"[bs4-icon] Only svg's are supported! But content-type is " + | ||
response.headers.get("content-type") | ||
); | ||
} | ||
return ""; | ||
}) | ||
.then((response) => { | ||
this.el.innerHTML = response; | ||
}) | ||
.catch((error) => { | ||
console.error(error); | ||
}); | ||
} | ||
} | ||
if (name === "title") { | ||
const title = document.createElementNS( | ||
"http://www.w3.org/2000/svg", | ||
"title" | ||
); | ||
title.textContent = newValue; | ||
const svg = this.el.firstElementChild; | ||
if (svg) { | ||
svg.appendChild(title); | ||
} | ||
} | ||
if (name === 'color') { | ||
if (newValue.indexOf(',') !== -1) { | ||
newValue = newValue.split(','); | ||
if (name === "color") { | ||
if (newValue.indexOf(",") !== -1) { | ||
newValue = newValue.split(","); | ||
if (newValue.length > 0) { | ||
this.el.className = this.el.className.replace(/(^|\s)color-\S+/g, ''); | ||
this.el.className = this.el.className.replace(/(^|\s)color-\S+/g, ""); | ||
for (let i = 0; i < newValue.length; i++) { | ||
const newColor: string = newValue[i]; | ||
if (newColor.startsWith('#') || newColor.startsWith('rgb')) { | ||
if (newColor.startsWith("#") || newColor.startsWith("rgb")) { | ||
this.el.style.color = newColor; | ||
@@ -69,3 +91,3 @@ } | ||
this.el.style.color = newValue; | ||
this.el.className = this.el.className.replace(/(^|\s)color-\S+/g, ''); | ||
this.el.className = this.el.className.replace(/(^|\s)color-\S+/g, ""); | ||
this.el.classList.add(`color-${newValue}`); | ||
@@ -75,48 +97,68 @@ } | ||
if (name === 'size') { | ||
if (name === "size") { | ||
const size = newValue; | ||
this.el.style.height = size + 'px'; | ||
this.el.style.width = size + 'px'; | ||
this.el.className = this.el.className.replace(/(^|\s)size-\S+/g, ''); | ||
this.el.style.height = size + "px"; | ||
this.el.style.width = size + "px"; | ||
this.el.className = this.el.className.replace(/(^|\s)size-\S+/g, ""); | ||
this.el.classList.add(`size-${size}`); | ||
} | ||
if (name === 'width') { | ||
if (name === "width") { | ||
const width = newValue; | ||
this.el.style.width = width + 'px'; | ||
this.el.className = this.el.className.replace(/(^|\s)width-\S+/g, ''); | ||
this.el.style.width = width + "px"; | ||
this.el.className = this.el.className.replace(/(^|\s)width-\S+/g, ""); | ||
this.el.classList.add(`width-${width}`); | ||
} | ||
if (name === 'height') { | ||
if (name === "height") { | ||
const height = newValue; | ||
this.el.style.height = height + 'px'; | ||
this.el.className = this.el.className.replace(/(^|\s)height-\S+/g, ''); | ||
this.el.style.height = height + "px"; | ||
this.el.className = this.el.className.replace(/(^|\s)height-\S+/g, ""); | ||
this.el.classList.add(`height-${height}`); | ||
} | ||
if (name === 'direction') { | ||
if (name === "direction") { | ||
const direction = newValue; | ||
let classString = `direction-${direction}`; | ||
if (direction === 'left' ) { | ||
classString += ' rotate-270'; | ||
} else if ( direction === 'left-top' || direction === 'left-up' || direction === 'top-left' || direction === 'up-left' ) { | ||
classString += ' rotate-315' ; | ||
} else if ( direction === 'top' || direction === 'up' ) { | ||
classString += ' rotate-0'; | ||
} else if ( direction === 'top-right' || direction === 'up-right' || direction === 'right-top' || direction === 'right-up') { | ||
classString += ' rotate-45'; | ||
} else if ( direction === 'right' ) { | ||
classString += ' rotate-90'; | ||
} else if ( direction === 'right-bottom' || direction === 'right-down' || direction === 'bottom-right' || direction === 'down-right' ) { | ||
classString += ' rotate-135'; | ||
} else if ( direction === 'bottom' || direction === 'down' ) { | ||
classString += ' rotate-180'; | ||
} else if ( direction === 'left-bottom' || direction === 'left-down' || direction === 'bottom-left' || direction === 'down-left' ) { | ||
classString += ' rotate-225'; | ||
if (direction === "left") { | ||
classString += " rotate-270"; | ||
} else if ( | ||
direction === "left-top" || | ||
direction === "left-up" || | ||
direction === "top-left" || | ||
direction === "up-left" | ||
) { | ||
classString += " rotate-315"; | ||
} else if (direction === "top" || direction === "up") { | ||
classString += " rotate-0"; | ||
} else if ( | ||
direction === "top-right" || | ||
direction === "up-right" || | ||
direction === "right-top" || | ||
direction === "right-up" | ||
) { | ||
classString += " rotate-45"; | ||
} else if (direction === "right") { | ||
classString += " rotate-90"; | ||
} else if ( | ||
direction === "right-bottom" || | ||
direction === "right-down" || | ||
direction === "bottom-right" || | ||
direction === "down-right" | ||
) { | ||
classString += " rotate-135"; | ||
} else if (direction === "bottom" || direction === "down") { | ||
classString += " rotate-180"; | ||
} else if ( | ||
direction === "left-bottom" || | ||
direction === "left-down" || | ||
direction === "bottom-left" || | ||
direction === "down-left" | ||
) { | ||
classString += " rotate-225"; | ||
} | ||
this.el.className = this.el.className.replace(/(^|\s)direction-\S+/g, ''); | ||
this.el.className = this.el.className.replace(/(^|\s)rotate-\S+/g, ''); | ||
this.el.className += ' ' + classString; | ||
this.el.className = this.el.className.replace(/(^|\s)direction-\S+/g, ""); | ||
this.el.className = this.el.className.replace(/(^|\s)rotate-\S+/g, ""); | ||
this.el.className += " " + classString; | ||
} | ||
@@ -127,10 +169,15 @@ } | ||
super.connectedCallback(); | ||
this.el.setAttribute('aria-hidden', 'true'); | ||
this.el.setAttribute('role', 'img'); | ||
this.el.classList.add('iconset'); | ||
this.el.setAttribute("aria-hidden", "true"); | ||
this.el.setAttribute("role", "img"); | ||
this.el.classList.add("iconset"); | ||
this.init(Bs4IconComponent.observedAttributes); | ||
// set default values | ||
if (!this.scope.direction) { | ||
this.scope.direction = 'up'; | ||
this.attributeChangedCallback('direction', null, this.scope.direction, null); | ||
this.scope.direction = "up"; | ||
this.attributeChangedCallback( | ||
"direction", | ||
null, | ||
this.scope.direction, | ||
null | ||
); | ||
} | ||
@@ -137,0 +184,0 @@ } |
@@ -1,8 +0,12 @@ | ||
import { Component, EventDispatcher } from '@ribajs/core'; | ||
import { CollapseService, EVENT_SHOWN, EVENT_HIDDEN, CLASS_NAME_COLLAPSED } from '../../services/collapse.service'; | ||
import { Component, EventDispatcher } from "@ribajs/core"; | ||
import { | ||
CollapseService, | ||
EVENT_SHOWN, | ||
EVENT_HIDDEN, | ||
CLASS_NAME_COLLAPSED, | ||
} from "../../services/collapse.service"; | ||
export class Bs4NavbarComponent extends Component { | ||
public static tagName = "bs4-navbar"; | ||
public static tagName = 'bs4-navbar'; | ||
protected scope: any = { | ||
@@ -13,3 +17,3 @@ toggle: this.toggle, | ||
isCollapsed: true, | ||
collapseSelector: '.navbar-collapse' | ||
collapseSelector: ".navbar-collapse", | ||
}; | ||
@@ -19,6 +23,6 @@ | ||
protected collapseServices: CollapseService[] = []; | ||
protected router?: EventDispatcher; | ||
protected routerEvents?: EventDispatcher; | ||
static get observedAttributes() { | ||
return ['collapse-selector']; | ||
return ["collapse-selector"]; | ||
} | ||
@@ -35,9 +39,7 @@ | ||
public toggle(event?: Event) { | ||
for (const collapseService of this.collapseServices) { | ||
collapseService.toggle(); | ||
} | ||
if (event) { | ||
@@ -71,4 +73,4 @@ event.preventDefault(); | ||
super.connectedCallback(); | ||
this.router = new EventDispatcher('main'); | ||
this.router.on('newPageReady', this.onNewPageReady.bind(this)); | ||
this.routerEvents = new EventDispatcher("main"); | ||
this.routerEvents.on("newPageReady", this.onNewPageReady.bind(this)); | ||
@@ -86,3 +88,4 @@ this.setCollapseElement(); | ||
this.collapseElements = this.el.querySelectorAll<HTMLElement>(this.scope.collapseSelector) || []; | ||
this.collapseElements = | ||
this.el.querySelectorAll<HTMLElement>(this.scope.collapseSelector) || []; | ||
@@ -94,3 +97,5 @@ // Add new event listeners | ||
for (const collapseElement of Array.from(this.collapseElements)) { | ||
this.collapseServices.push(new CollapseService(collapseElement, [this.el], {toggle: false})); | ||
this.collapseServices.push( | ||
new CollapseService(collapseElement, [this.el], { toggle: false }) | ||
); | ||
} | ||
@@ -100,3 +105,2 @@ } | ||
this.hide(); | ||
} | ||
@@ -107,4 +111,10 @@ | ||
this.collapseElements.forEach((collapseElement: HTMLElement) => { | ||
collapseElement.addEventListener(EVENT_SHOWN, this.onStateChange.bind(this)); | ||
collapseElement.addEventListener(EVENT_HIDDEN, this.onStateChange.bind(this)); | ||
collapseElement.addEventListener( | ||
EVENT_SHOWN, | ||
this.onStateChange.bind(this) | ||
); | ||
collapseElement.addEventListener( | ||
EVENT_HIDDEN, | ||
this.onStateChange.bind(this) | ||
); | ||
}); | ||
@@ -117,4 +127,10 @@ } | ||
this.collapseElements.forEach((collapseElement: HTMLElement) => { | ||
collapseElement.removeEventListener(EVENT_SHOWN, this.onStateChange.bind(this)); | ||
collapseElement.removeEventListener(EVENT_HIDDEN, this.onStateChange.bind(this)); | ||
collapseElement.removeEventListener( | ||
EVENT_SHOWN, | ||
this.onStateChange.bind(this) | ||
); | ||
collapseElement.removeEventListener( | ||
EVENT_HIDDEN, | ||
this.onStateChange.bind(this) | ||
); | ||
}); | ||
@@ -127,4 +143,4 @@ } | ||
this.removeCollapseEventListeners(); | ||
if (this.router) { | ||
this.router.off('newPageReady', this.onNewPageReady); | ||
if (this.routerEvents) { | ||
this.routerEvents.off("newPageReady", this.onNewPageReady); | ||
} | ||
@@ -134,3 +150,2 @@ } | ||
protected onStateChange() { | ||
this.scope.isCollapsed = !!this.collapseServices[0]?.isCollapsed(); | ||
@@ -140,6 +155,6 @@ | ||
this.el.classList.add(CLASS_NAME_COLLAPSED); | ||
this.el.setAttribute('aria-expanded', 'false'); | ||
this.el.setAttribute("aria-expanded", "false"); | ||
} else { | ||
this.el.classList.remove(CLASS_NAME_COLLAPSED); | ||
this.el.setAttribute('aria-expanded', 'true'); | ||
this.el.setAttribute("aria-expanded", "true"); | ||
} | ||
@@ -152,5 +167,15 @@ } | ||
protected parsedAttributeChangedCallback(attributeName: string | string[], oldValue: any, newValue: any, namespace: string | null) { | ||
super.parsedAttributeChangedCallback(attributeName, oldValue, newValue, namespace); | ||
if (attributeName === 'collapseSelector') { | ||
protected parsedAttributeChangedCallback( | ||
attributeName: string | string[], | ||
oldValue: any, | ||
newValue: any, | ||
namespace: string | null | ||
) { | ||
super.parsedAttributeChangedCallback( | ||
attributeName, | ||
oldValue, | ||
newValue, | ||
namespace | ||
); | ||
if (attributeName === "collapseSelector") { | ||
this.setCollapseElement(); | ||
@@ -157,0 +182,0 @@ } |
@@ -1,4 +0,7 @@ | ||
import { Bs4ContentsComponent, Scope as Bs4ContentsComponentScope } from '../bs4-contents/bs4-contents.component'; | ||
import { | ||
Bs4ContentsComponent, | ||
Scope as Bs4ContentsComponentScope, | ||
} from "../bs4-contents/bs4-contents.component"; | ||
import template from './bs4-scrollspy.component.html'; | ||
import template from "./bs4-scrollspy.component.html"; | ||
@@ -24,5 +27,4 @@ export interface Anchor { | ||
export class Bs4ScrollspyComponent extends Bs4ContentsComponent { | ||
public static tagName = "bs4-scrollspy"; | ||
public static tagName = 'bs4-scrollspy'; | ||
protected autobind = true; | ||
@@ -33,3 +35,11 @@ | ||
static get observedAttributes() { | ||
return ['headers-start', 'headers-depth', 'find-header-id-depth', 'header-parent-selector', 'offset', 'offset-bottom', 'scroll-offset']; | ||
return [ | ||
"headers-start", | ||
"headers-depth", | ||
"find-header-id-depth", | ||
"header-parent-selector", | ||
"offset", | ||
"offset-bottom", | ||
"scroll-offset", | ||
]; | ||
} | ||
@@ -58,3 +68,3 @@ | ||
protected requiredAttributes() { | ||
return ['headersStart', 'headersDepth', 'headerParentSelector']; | ||
return ["headersStart", "headersDepth", "headerParentSelector"]; | ||
} | ||
@@ -61,0 +71,0 @@ |
import { Component } from "@ribajs/core"; | ||
import { getUrl } from '@ribajs/utils/src/url'; | ||
import { getUrl } from "@ribajs/utils/src/url"; | ||
import template from "./bs4-share.component.html"; | ||
@@ -16,3 +16,3 @@ import labelTemplate from "./bs4-share.label.html"; | ||
labelTemplate: string; | ||
/** true if the browser runs on Android */ | ||
@@ -27,3 +27,3 @@ isAndroid: boolean; | ||
dropdownId: string; | ||
/** | ||
/** | ||
* Object with share urls like whatsapp, telegram, instagram etc used if the native share is noit available | ||
@@ -34,2 +34,4 @@ * Only used if the browser has not an native share support like on android and iOS | ||
dropdownDirection: "up" | "down" | "right" | "left"; | ||
// Methods | ||
@@ -49,3 +51,3 @@ shareOnService: Bs4ShareComponent["shareOnService"]; | ||
interface Navigator { | ||
share: (data: NavigatorShareParam) => Promise<any>; | ||
share: (data?: ShareData) => Promise<void>; | ||
} | ||
@@ -67,4 +69,14 @@ } | ||
public _debug = false; | ||
static get observedAttributes() { | ||
return ["type", "title", "text", "url", "media-url", "label"]; | ||
return [ | ||
"type", | ||
"title", | ||
"text", | ||
"url", | ||
"media-url", | ||
"label", | ||
"dropdown-direction", | ||
]; | ||
} | ||
@@ -82,8 +94,3 @@ | ||
this.scope = this.getScopeDefaults(); | ||
// this._debug = true; | ||
this.debug('constructor', this.scope); | ||
this.init(Bs4ShareComponent.observedAttributes); | ||
this.addEventListeners(); | ||
this.debug("constructor", this.scope); | ||
Bs4ShareComponent.count++; | ||
@@ -100,6 +107,7 @@ } | ||
urlTemplate: "https://www.facebook.com/sharer/sharer.php?u={{url}}", | ||
mediaUrlTemplate: "https://www.facebook.com/sharer/sharer.php?u={{media_url}}", | ||
type: 'popup', | ||
mediaUrlTemplate: | ||
"https://www.facebook.com/sharer/sharer.php?u={{media_url}}", | ||
type: "popup", | ||
url: "", | ||
availableFor: ['page', 'image', 'video'], | ||
availableFor: ["page", "image", "video"], | ||
}, | ||
@@ -113,3 +121,3 @@ { | ||
url: "", | ||
availableFor: ['page', 'image', 'video'], | ||
availableFor: ["page", "image", "video"], | ||
}, | ||
@@ -122,6 +130,6 @@ { | ||
"?url={{url}}&media={{media_url}}&description={{text}}", | ||
type: 'popup', | ||
type: "popup", | ||
url: "", | ||
availableFor: ['image', 'video'], | ||
availableFor: ["image", "video"], | ||
}, | ||
@@ -133,5 +141,5 @@ { | ||
mediaUrlTemplate: `https://api.whatsapp.com/send?text={{text}}${newLine}${newLine}{{media_url}}${newLine}({{url}})`, | ||
type: 'popup', | ||
type: "popup", | ||
url: "", | ||
availableFor: ['page', 'image', 'video'], | ||
availableFor: ["page", "image", "video"], | ||
}, | ||
@@ -143,5 +151,5 @@ { | ||
mediaUrlTemplate: `https://telegram.me/share/url?url={{media_url}}&text={{text}}${newLine}({{url}})`, | ||
type: 'popup', | ||
type: "popup", | ||
url: "", | ||
availableFor: ['page', 'image', 'video'], | ||
availableFor: ["page", "image", "video"], | ||
}, | ||
@@ -153,5 +161,5 @@ { | ||
mediaUrlTemplate: `mailto:?subject={{title}}&body={{text}}${newLine}${newLine}{{media_url}}${newLine}({{url}})`, | ||
type: 'href', | ||
type: "href", | ||
url: "", | ||
availableFor: ['page', 'image', 'video'], | ||
availableFor: ["page", "image", "video"], | ||
}, | ||
@@ -171,5 +179,5 @@ // { | ||
urlTemplate: "{{raw_media_url}}", | ||
type: 'download', | ||
type: "download", | ||
url: "", | ||
availableFor: ['image', 'video'], | ||
availableFor: ["image", "video"], | ||
}, | ||
@@ -194,3 +202,3 @@ ]; | ||
const scope: Scope = { | ||
type: 'page', | ||
type: "page", | ||
title: document.title, | ||
@@ -207,9 +215,10 @@ text: "Look at this! 👀🤩", | ||
shareItems: this.getDefaultShareServices(), | ||
dropdownDirection: "down", | ||
// Methods | ||
share: this.share, | ||
shareOnService: this.shareOnService, | ||
} | ||
}; | ||
// on those two support "mobile deep links", so HTTP based fallback for all others. | ||
scope.isDesktop = !scope.isIos && !scope.isAndroid; | ||
scope.isDesktop = !scope.isIos && !scope.isAndroid; | ||
@@ -227,2 +236,8 @@ return scope; | ||
protected connectedCallback() { | ||
super.connectedCallback(); | ||
this.init(Bs4ShareComponent.observedAttributes); | ||
this.addEventListeners(); | ||
} | ||
protected disconnectedCallback() { | ||
@@ -234,13 +249,13 @@ super.disconnectedCallback(); | ||
protected addEventListeners() { | ||
this.el.addEventListener('open', this.onExternalOpenEvent.bind(this)); | ||
this.el.addEventListener('close', this.onExternalCloseEvent.bind(this)); | ||
this.el.addEventListener("open", this.onExternalOpenEvent.bind(this)); | ||
this.el.addEventListener("close", this.onExternalCloseEvent.bind(this)); | ||
} | ||
protected removeEventListeners() { | ||
this.el.removeEventListener('open', this.onExternalOpenEvent.bind(this)); | ||
this.el.removeEventListener('close', this.onExternalOpenEvent.bind(this)); | ||
this.el.removeEventListener("open", this.onExternalOpenEvent.bind(this)); | ||
this.el.removeEventListener("close", this.onExternalOpenEvent.bind(this)); | ||
} | ||
protected getURLForShare() { | ||
if (this.scope.type === 'page' && this.scope.url) { | ||
if (this.scope.type === "page" && this.scope.url) { | ||
return getUrl(this.scope.url); | ||
@@ -252,3 +267,3 @@ } | ||
protected getMediaUrlForShare() { | ||
if (this.scope.type !== 'page' && this.scope.url) { | ||
if (this.scope.type !== "page" && this.scope.url) { | ||
return getUrl(this.scope.url); | ||
@@ -265,3 +280,3 @@ } | ||
* Currently only used for email | ||
* @param appendUrl | ||
* @param appendUrl | ||
*/ | ||
@@ -279,4 +294,4 @@ protected getTitleForShare() { | ||
let urlTemplate = shareItem.urlTemplate; | ||
if (this.scope.type !== 'page' && shareItem.mediaUrlTemplate) { | ||
if (this.scope.type !== "page" && shareItem.mediaUrlTemplate) { | ||
urlTemplate = shareItem.mediaUrlTemplate; | ||
@@ -286,4 +301,4 @@ } | ||
const shareURL = urlTemplate | ||
.replace("{{url}}", encodeURIComponent(url)) | ||
.replace("{{url}}", encodeURIComponent(url)) | ||
.replace("{{url}}", encodeURIComponent(url)) | ||
.replace("{{media_url}}", encodeURIComponent(mediaUrl)) | ||
@@ -297,3 +312,2 @@ .replace("{{raw_media_url}}", mediaUrl) | ||
} | ||
} | ||
@@ -306,3 +320,6 @@ | ||
if (!dropDownButtonElement) { | ||
console.warn('Element with selector ".dropdown-toggle-share" not found!', this.el); | ||
console.warn( | ||
'Element with selector ".dropdown-toggle-share" not found!', | ||
this.el | ||
); | ||
return; | ||
@@ -315,13 +332,9 @@ } | ||
* New browser popup with the external site (e.g. Facebook) on you want to share your url | ||
* @param binding | ||
* @param event | ||
* @param controller | ||
* @param el | ||
* @param binding | ||
* @param event | ||
* @param controller | ||
* @param el | ||
*/ | ||
public shareOnService( | ||
event: Event, | ||
controller: any, | ||
el: HTMLAnchorElement | ||
) { | ||
console.debug('Open popup'); | ||
public shareOnService(event: Event, controller: any, el: HTMLAnchorElement) { | ||
this.debug("Open popup"); | ||
@@ -336,3 +349,6 @@ this.dropdown?.close(); | ||
// We use the default browser anchor href logic for download and href | ||
if (el.hasAttribute("type") && el.getAttribute("type") === "download" || el.getAttribute("type") === "href") { | ||
if ( | ||
(el.hasAttribute("type") && el.getAttribute("type") === "download") || | ||
el.getAttribute("type") === "href" | ||
) { | ||
return true; | ||
@@ -344,3 +360,3 @@ } | ||
// console.debug('Open popup'); | ||
// this.debug('Open popup'); | ||
@@ -359,3 +375,3 @@ window.open( | ||
public async share(event: Event): Promise<any> { | ||
console.debug('share', this.scope); | ||
this.debug("share", this.scope); | ||
event.preventDefault(); | ||
@@ -373,3 +389,3 @@ event.stopPropagation(); | ||
// TODO show flash message | ||
// console.debug(error.message); | ||
// this.debug(error.message); | ||
return; | ||
@@ -387,3 +403,3 @@ } | ||
await super.beforeBind(); | ||
// console.debug('beforeBind'); | ||
// this.debug('beforeBind'); | ||
} | ||
@@ -394,3 +410,3 @@ | ||
this.initDropdown(); | ||
// console.debug('afterBind', this.scope); | ||
// this.debug('afterBind', this.scope); | ||
} | ||
@@ -403,6 +419,7 @@ | ||
protected template() { | ||
this.debug("template", this.el, this.el.hasChildNodes()); | ||
if (this.el && this.el.hasChildNodes()) { | ||
// If a child is set, this is a custom label template | ||
this.scope.labelTemplate = this.el.innerHTML; | ||
// console.debug('Custom label template: ', this.el.innerHTML); | ||
this.debug("Custom label template: ", this.scope.labelTemplate); | ||
} | ||
@@ -409,0 +426,0 @@ return template; |
@@ -1,8 +0,10 @@ | ||
import { | ||
Component, | ||
EventDispatcher, | ||
} from '@ribajs/core'; | ||
import { getViewportDimensions } from '@ribajs/utils/src/dom'; | ||
import { Component, EventDispatcher } from "@ribajs/core"; | ||
import { getViewportDimensions } from "@ribajs/utils/src/dom"; | ||
type State = 'overlay-left' | 'overlay-right' | 'side-left' | 'side-right' | 'hidden'; | ||
type State = | ||
| "overlay-left" | ||
| "overlay-right" | ||
| "side-left" | ||
| "side-right" | ||
| "hidden"; | ||
@@ -31,3 +33,3 @@ interface Scope { | ||
*/ | ||
position: 'left' | 'right'; | ||
position: "left" | "right"; | ||
/** | ||
@@ -62,17 +64,16 @@ * Auto show the sidebar if the viewport width is wider than this value | ||
*/ | ||
hide: Bs4SidebarComponent['hide']; | ||
hide: Bs4SidebarComponent["hide"]; | ||
/** | ||
* Shows / opens the sidebar | ||
*/ | ||
show: Bs4SidebarComponent['show']; | ||
show: Bs4SidebarComponent["show"]; | ||
/** | ||
* Toggles (closes or opens) the sidebar | ||
*/ | ||
toggle: Bs4SidebarComponent['toggle']; | ||
toggle: Bs4SidebarComponent["toggle"]; | ||
} | ||
export class Bs4SidebarComponent extends Component { | ||
public static tagName = "bs4-sidebar"; | ||
public static tagName = 'bs4-sidebar'; | ||
protected style?: CSSStyleDeclaration; | ||
@@ -84,12 +85,12 @@ | ||
return [ | ||
'id', | ||
'container-selector', | ||
'position', | ||
'width', | ||
'auto-show-on-wider-than', | ||
'auto-hide-on-slimmer-than', | ||
'force-hide-on-location-pathnames', | ||
'force-show-on-location-pathnames', | ||
'overlay-on-slimmer-than', | ||
'watch-new-page-ready-event', | ||
"id", | ||
"container-selector", | ||
"position", | ||
"width", | ||
"auto-show-on-wider-than", | ||
"auto-hide-on-slimmer-than", | ||
"force-hide-on-location-pathnames", | ||
"force-show-on-location-pathnames", | ||
"overlay-on-slimmer-than", | ||
"watch-new-page-ready-event", | ||
]; | ||
@@ -100,14 +101,13 @@ } | ||
protected routerEvents = new EventDispatcher('main'); | ||
protected routerEvents = new EventDispatcher("main"); | ||
protected scope: Scope = { | ||
// template properties | ||
containerSelector: undefined, | ||
state: 'hidden', | ||
state: "hidden", | ||
id: undefined, | ||
width: '250px', | ||
width: "250px", | ||
// Options | ||
position: 'left', | ||
position: "left", | ||
autoShowOnWiderThan: 1199, | ||
@@ -139,3 +139,3 @@ autoHideOnSlimmerThan: 1200, | ||
public hide() { | ||
this.scope.state = 'hidden'; | ||
this.scope.state = "hidden"; | ||
this.onStateChange(); | ||
@@ -147,5 +147,5 @@ } | ||
if (vw < this.scope.overlayOnSlimmerThan) { | ||
this.scope.state = 'overlay-' + this.scope.position as State; | ||
this.scope.state = ("overlay-" + this.scope.position) as State; | ||
} else { | ||
this.scope.state = 'side-' + this.scope.position as State; | ||
this.scope.state = ("side-" + this.scope.position) as State; | ||
} | ||
@@ -156,3 +156,3 @@ this.onStateChange(); | ||
public toggle() { | ||
if (this.scope.state === 'hidden') { | ||
if (this.scope.state === "hidden") { | ||
this.show(); | ||
@@ -168,3 +168,7 @@ } else { | ||
this.style = window.getComputedStyle(this.el); | ||
window.addEventListener('resize', this.onEnviromentChanges.bind(this), false); | ||
window.addEventListener( | ||
"resize", | ||
this.onEnviromentChanges.bind(this), | ||
false | ||
); | ||
// inital | ||
@@ -180,8 +184,10 @@ this.onEnviromentChanges(); | ||
if (this.toggleButtonEvents) { | ||
this.toggleButtonEvents.off('toggle', this.onToggle.bind(this)); | ||
this.toggleButtonEvents.off('init', this.triggerState.bind(this)); | ||
this.toggleButtonEvents.off("toggle", this.onToggle.bind(this)); | ||
this.toggleButtonEvents.off("init", this.triggerState.bind(this)); | ||
} | ||
this.toggleButtonEvents = new EventDispatcher('bs4-toggle-button:' + this.scope.id); | ||
this.toggleButtonEvents.on('toggle', this.onToggle.bind(this)); | ||
this.toggleButtonEvents.on('init', this.triggerState.bind(this)); | ||
this.toggleButtonEvents = new EventDispatcher( | ||
"bs4-toggle-button:" + this.scope.id | ||
); | ||
this.toggleButtonEvents.on("toggle", this.onToggle.bind(this)); | ||
this.toggleButtonEvents.on("init", this.triggerState.bind(this)); | ||
} | ||
@@ -191,3 +197,3 @@ | ||
if (this.scope.watchNewPageReadyEvent) { | ||
this.routerEvents.on('newPageReady', this.onEnviromentChanges.bind(this)); | ||
this.routerEvents.on("newPageReady", this.onEnviromentChanges.bind(this)); | ||
} | ||
@@ -198,18 +204,27 @@ } | ||
this.setContainersStyle(); | ||
const translateX = this.scope.position === 'left' ? '-100%' : '100%'; | ||
this.el.setAttribute('style', `transform:translateX(${translateX});width:${this.scope.width};`); | ||
const translateX = this.scope.position === "left" ? "-100%" : "100%"; | ||
this.el.setAttribute( | ||
"style", | ||
`transform:translateX(${translateX});width:${this.scope.width};` | ||
); | ||
} | ||
protected onSide(directon: State) { | ||
this.setContainersStyle(undefined, '', directon); | ||
this.el.setAttribute('style', `transform:translateX(0);width:${this.scope.width};`); | ||
this.setContainersStyle(undefined, "", directon); | ||
this.el.setAttribute( | ||
"style", | ||
`transform:translateX(0);width:${this.scope.width};` | ||
); | ||
} | ||
protected onOverlay(directon: State) { | ||
this.setContainersStyle(undefined, '', directon); | ||
this.el.setAttribute('style', `transform:translateX(0);width:${this.scope.width};`); | ||
this.setContainersStyle(undefined, "", directon); | ||
this.el.setAttribute( | ||
"style", | ||
`transform:translateX(0);width:${this.scope.width};` | ||
); | ||
} | ||
protected triggerState() { | ||
this.toggleButtonEvents?.trigger('state', this.scope.state); | ||
this.toggleButtonEvents?.trigger("state", this.scope.state); | ||
} | ||
@@ -219,10 +234,10 @@ | ||
switch (this.scope.state) { | ||
case 'side-left': | ||
case 'side-right': | ||
case "side-left": | ||
case "side-right": | ||
this.onSide(this.scope.state); | ||
break; | ||
case 'overlay-left': | ||
case 'overlay-right': | ||
this.onOverlay(this.scope.state); | ||
break; | ||
case "overlay-left": | ||
case "overlay-right": | ||
this.onOverlay(this.scope.state); | ||
break; | ||
default: | ||
@@ -233,3 +248,3 @@ this.onHidden(); | ||
if (this.toggleButtonEvents) { | ||
this.toggleButtonEvents.trigger('toggled', this.scope.state); | ||
this.toggleButtonEvents.trigger("toggled", this.scope.state); | ||
} | ||
@@ -239,17 +254,27 @@ } | ||
protected get width() { | ||
return this.el.offsetWidth ? this.el.offsetWidth + 'px' : this.scope.width; | ||
return this.el.offsetWidth ? this.el.offsetWidth + "px" : this.scope.width; | ||
} | ||
protected setStateByEnviroment() { | ||
if (this.scope.forceHideOnLocationPathnames.includes(window.location.pathname)) { | ||
if ( | ||
this.scope.forceHideOnLocationPathnames.includes(window.location.pathname) | ||
) { | ||
return this.hide(); | ||
} | ||
if (this.scope.forceShowOnLocationPathnames.includes(window.location.pathname)) { | ||
if ( | ||
this.scope.forceShowOnLocationPathnames.includes(window.location.pathname) | ||
) { | ||
return this.show(); | ||
} | ||
const vw = getViewportDimensions().w; | ||
if (this.scope.autoHideOnSlimmerThan > -1 && vw < this.scope.autoHideOnSlimmerThan) { | ||
if ( | ||
this.scope.autoHideOnSlimmerThan > -1 && | ||
vw < this.scope.autoHideOnSlimmerThan | ||
) { | ||
return this.hide(); | ||
} | ||
if (this.scope.autoShowOnWiderThan > -1 && vw > this.scope.autoShowOnWiderThan) { | ||
if ( | ||
this.scope.autoShowOnWiderThan > -1 && | ||
vw > this.scope.autoShowOnWiderThan | ||
) { | ||
return this.show(); | ||
@@ -267,3 +292,7 @@ } | ||
protected getContainers() { | ||
return this.scope.containerSelector ? document.querySelectorAll<HTMLUnknownElement>(this.scope.containerSelector) : undefined; | ||
return this.scope.containerSelector | ||
? document.querySelectorAll<HTMLUnknownElement>( | ||
this.scope.containerSelector | ||
) | ||
: undefined; | ||
} | ||
@@ -276,3 +305,7 @@ | ||
protected setContainersStyle(containers?: NodeListOf<HTMLUnknownElement>, style?: string, move?: State) { | ||
protected setContainersStyle( | ||
containers?: NodeListOf<HTMLUnknownElement>, | ||
style?: string, | ||
move?: State | ||
) { | ||
if (!containers) { | ||
@@ -295,3 +328,7 @@ containers = this.getContainers(); | ||
*/ | ||
protected setContainerStyle(container: HTMLUnknownElement, style = '', move?: State) { | ||
protected setContainerStyle( | ||
container: HTMLUnknownElement, | ||
style = "", | ||
move?: State | ||
) { | ||
if (move) { | ||
@@ -301,19 +338,19 @@ const width = this.width; | ||
switch (move) { | ||
case 'side-left': | ||
case "side-left": | ||
switch (conStyle.position) { | ||
case 'fixed': | ||
style += 'left:' + width; | ||
case "fixed": | ||
style += "left:" + width; | ||
break; | ||
default: | ||
style += 'margin-left:' + width; | ||
style += "margin-left:" + width; | ||
break; | ||
} | ||
break; | ||
case 'side-right': | ||
case "side-right": | ||
switch (conStyle.position) { | ||
case 'fixed': | ||
style += 'right:' + width; | ||
case "fixed": | ||
style += "right:" + width; | ||
break; | ||
default: | ||
style += 'margin-right:' + width; | ||
style += "margin-right:" + width; | ||
break; | ||
@@ -326,3 +363,6 @@ } | ||
} | ||
return container.setAttribute('style', `transition:${this.style ? this.style.transition : ''};${style}`); | ||
return container.setAttribute( | ||
"style", | ||
`transition:${this.style ? this.style.transition : ""};${style}` | ||
); | ||
} | ||
@@ -342,11 +382,21 @@ | ||
protected requiredAttributes() { | ||
return ['id']; | ||
return ["id"]; | ||
} | ||
protected parsedAttributeChangedCallback(attributeName: string, oldValue: any, newValue: any, namespace: string | null) { | ||
super.parsedAttributeChangedCallback(attributeName, oldValue, newValue, namespace); | ||
if (attributeName === 'containerSelector') { | ||
protected parsedAttributeChangedCallback( | ||
attributeName: string, | ||
oldValue: any, | ||
newValue: any, | ||
namespace: string | null | ||
) { | ||
super.parsedAttributeChangedCallback( | ||
attributeName, | ||
oldValue, | ||
newValue, | ||
namespace | ||
); | ||
if (attributeName === "containerSelector") { | ||
this.initContainers(); | ||
} | ||
if (attributeName === 'id') { | ||
if (attributeName === "id") { | ||
this.initToggleButtonEventDispatcher(); | ||
@@ -359,7 +409,11 @@ } | ||
super.disconnectedCallback(); | ||
this.toggleButtonEvents?.off('init', this.triggerState.bind(this)); | ||
this.toggleButtonEvents?.off('toggle', this.onToggle.bind(this)); | ||
this.toggleButtonEvents?.off('init', this.triggerState.bind(this)); | ||
this.routerEvents.off('newPageReady', this.onEnviromentChanges.bind(this)); | ||
window.removeEventListener('resize', this.onEnviromentChanges.bind(this), false); | ||
this.toggleButtonEvents?.off("init", this.triggerState.bind(this)); | ||
this.toggleButtonEvents?.off("toggle", this.onToggle.bind(this)); | ||
this.toggleButtonEvents?.off("init", this.triggerState.bind(this)); | ||
this.routerEvents.off("newPageReady", this.onEnviromentChanges.bind(this)); | ||
window.removeEventListener( | ||
"resize", | ||
this.onEnviromentChanges.bind(this), | ||
false | ||
); | ||
} | ||
@@ -369,3 +423,5 @@ | ||
if (!this.el.hasChildNodes()) { | ||
console.warn('No child elements found, this component as no template so you need to define your own as child of this component.'); | ||
console.warn( | ||
"No child elements found, this component as no template so you need to define your own as child of this component." | ||
); | ||
} | ||
@@ -372,0 +428,0 @@ return null; |
@@ -1,22 +0,45 @@ | ||
import { TemplatesComponent } from '../templates/templates.component'; | ||
import { TemplatesComponent } from "../templates/templates.component"; | ||
import { EventDispatcher } from "@ribajs/core"; | ||
import { clone, camelCase } from '@ribajs/utils/src/type'; | ||
import { clone, camelCase } from "@ribajs/utils/src/type"; | ||
import { Dragscroll, DragscrollOptions, Autoscroll, AutoscrollOptions, Utils as ExtraUtils, ScrollPosition, ScrollEventsService } from '@ribajs/extras'; | ||
import { | ||
Dragscroll, | ||
DragscrollOptions, | ||
Autoscroll, | ||
AutoscrollOptions, | ||
Utils as ExtraUtils, | ||
ScrollPosition, | ||
ScrollEventsService, | ||
} from "@ribajs/extras"; | ||
import templateSlides from './bs4-slideshow-slides.component.html'; | ||
import templateSlides from "./bs4-slideshow-slides.component.html"; | ||
import templateControls from './bs4-slideshow-controls.component.html'; | ||
import templateControls from "./bs4-slideshow-controls.component.html"; | ||
import templateIndicators from './bs4-slideshow-indicators.component.html'; | ||
import templateIndicators from "./bs4-slideshow-indicators.component.html"; | ||
const SLIDESHOW_INNER_SELECTOR = '.slideshow-inner'; | ||
const SLIDESHOW_INNER_SELECTOR = ".slideshow-inner"; | ||
const SLIDES_SELECTOR = `${SLIDESHOW_INNER_SELECTOR} > .slide`; | ||
export type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; | ||
export type Breakpoint = "xs" | "sm" | "md" | "lg" | "xl"; | ||
export type ControlsPosition = 'insite-middle' | 'insite-bottom' | 'insite-top' | 'outsite-middle' | 'outsite-bottom' | 'outsite-top'; | ||
export type ControlsPosition = | ||
| "insite-middle" | ||
| "insite-bottom" | ||
| "insite-top" | ||
| "outsite-middle" | ||
| "outsite-bottom" | ||
| "outsite-top"; | ||
export type IndicatorsPosition = 'insite-bottom' | 'insite-top' | 'insite-right' | 'insite-left' | 'outsite-bottom' | 'outsite-top' | 'outsite-right' | 'outsite-left'; | ||
export type IndicatorsPosition = | ||
| "insite-bottom" | ||
| "insite-top" | ||
| "insite-right" | ||
| "insite-left" | ||
| "outsite-bottom" | ||
| "outsite-top" | ||
| "outsite-right" | ||
| "outsite-left"; | ||
@@ -44,3 +67,3 @@ export interface Position extends DOMRect { | ||
export interface Options { | ||
/** Show controls */ | ||
/** Show controls */ | ||
controls: boolean; | ||
@@ -76,3 +99,3 @@ /** Position of the controls */ | ||
/** Slide angle, can be vertical or horizontal */ | ||
angle: 'vertical' | 'horizontal'; | ||
angle: "vertical" | "horizontal"; | ||
/** Pause on autoplay (with interval) */ | ||
@@ -90,5 +113,5 @@ pause: boolean; | ||
export interface Scope extends Options { | ||
next: Bs4SlideshowComponent['next']; | ||
prev: Bs4SlideshowComponent['prev']; | ||
goTo: Bs4SlideshowComponent['goTo']; | ||
next: Bs4SlideshowComponent["next"]; | ||
prev: Bs4SlideshowComponent["prev"]; | ||
goTo: Bs4SlideshowComponent["goTo"]; | ||
controlsPositionClass: string; | ||
@@ -100,3 +123,2 @@ indicatorsPositionClass: string; | ||
export class Bs4SlideshowComponent extends TemplatesComponent { | ||
protected get slideshowInner() { | ||
@@ -107,3 +129,5 @@ if (!this._slideshowInner) { | ||
if (!this._slideshowInner) { | ||
throw new Error(`Child element with selecto ${SLIDESHOW_INNER_SELECTOR} not found!`); | ||
throw new Error( | ||
`Child element with selecto ${SLIDESHOW_INNER_SELECTOR} not found!` | ||
); | ||
} | ||
@@ -118,3 +142,5 @@ return this._slideshowInner; | ||
if (!this._slideElements) { | ||
throw new Error(`Child element with selecto ${SLIDES_SELECTOR} not found!`); | ||
throw new Error( | ||
`Child element with selecto ${SLIDES_SELECTOR} not found!` | ||
); | ||
} | ||
@@ -126,3 +152,5 @@ return this._slideElements; | ||
if (!this._controlsElements) { | ||
this._controlsElements = this.el.querySelectorAll('.slideshow-control-prev, .slideshow-control-next'); | ||
this._controlsElements = this.el.querySelectorAll( | ||
".slideshow-control-prev, .slideshow-control-next" | ||
); | ||
} | ||
@@ -134,3 +162,3 @@ return this._controlsElements; | ||
if (!this._indicatorsElement) { | ||
this._indicatorsElement = this.el.querySelector('.slideshow-indicators'); | ||
this._indicatorsElement = this.el.querySelector(".slideshow-indicators"); | ||
} | ||
@@ -142,132 +170,132 @@ return this._indicatorsElement; | ||
return [ | ||
'min-width', | ||
'slides-to-show', | ||
'slides-to-scroll', | ||
'controls', | ||
'controls-position', | ||
'draggable', | ||
'autoplay', | ||
'autoplay-interval', | ||
'autoplay-velocity', | ||
'control-prev-icon-src', | ||
'control-next-icon-src', | ||
'indicator-inactive-icon-src', | ||
'indicator-active-icon-src', | ||
'angle', | ||
'set-active-slide', | ||
'pause-on-hover', | ||
'sticky', | ||
'indicators', | ||
'indicators-position', | ||
'pause', | ||
"min-width", | ||
"slides-to-show", | ||
"slides-to-scroll", | ||
"controls", | ||
"controls-position", | ||
"draggable", | ||
"autoplay", | ||
"autoplay-interval", | ||
"autoplay-velocity", | ||
"control-prev-icon-src", | ||
"control-next-icon-src", | ||
"indicator-inactive-icon-src", | ||
"indicator-active-icon-src", | ||
"angle", | ||
"set-active-slide", | ||
"pause-on-hover", | ||
"sticky", | ||
"indicators", | ||
"indicators-position", | ||
"pause", | ||
'sm-min-width', | ||
'sm-slides-to-show', | ||
'sm-slides-to-scroll', | ||
'sm-controls', | ||
'sm-controls-position', | ||
'sm-draggable', | ||
'sm-autoplay', | ||
'sm-autoplay-interval', | ||
'sm-autoplay-velocity', | ||
'sm-control-prev-icon-src', | ||
'sm-control-next-icon-src', | ||
'sm-indicator-inactive-icon-src', | ||
'sm-indicator-active-icon-src', | ||
'sm-angle', | ||
'sm-set-active-slide', | ||
'sm-pause-on-hover', | ||
'sm-sticky', | ||
'sm-indicators', | ||
'sm-indicators-position', | ||
'sm-pause', | ||
"sm-min-width", | ||
"sm-slides-to-show", | ||
"sm-slides-to-scroll", | ||
"sm-controls", | ||
"sm-controls-position", | ||
"sm-draggable", | ||
"sm-autoplay", | ||
"sm-autoplay-interval", | ||
"sm-autoplay-velocity", | ||
"sm-control-prev-icon-src", | ||
"sm-control-next-icon-src", | ||
"sm-indicator-inactive-icon-src", | ||
"sm-indicator-active-icon-src", | ||
"sm-angle", | ||
"sm-set-active-slide", | ||
"sm-pause-on-hover", | ||
"sm-sticky", | ||
"sm-indicators", | ||
"sm-indicators-position", | ||
"sm-pause", | ||
'md-min-width', | ||
'md-slides-to-show', | ||
'md-slides-to-scroll', | ||
'md-controls', | ||
'md-controls-position', | ||
'md-draggable', | ||
'md-autoplay', | ||
'md-autoplay-interval', | ||
'md-autoplay-velocity', | ||
'md-control-prev-icon-src', | ||
'md-control-next-icon-src', | ||
'md-indicator-inactive-icon-src', | ||
'md-indicator-active-icon-src', | ||
'md-angle', | ||
'md-set-active-slide', | ||
'md-pause-on-hover', | ||
'md-sticky', | ||
'md-indicators', | ||
'sm-indicators-position', | ||
'md-pause', | ||
"md-min-width", | ||
"md-slides-to-show", | ||
"md-slides-to-scroll", | ||
"md-controls", | ||
"md-controls-position", | ||
"md-draggable", | ||
"md-autoplay", | ||
"md-autoplay-interval", | ||
"md-autoplay-velocity", | ||
"md-control-prev-icon-src", | ||
"md-control-next-icon-src", | ||
"md-indicator-inactive-icon-src", | ||
"md-indicator-active-icon-src", | ||
"md-angle", | ||
"md-set-active-slide", | ||
"md-pause-on-hover", | ||
"md-sticky", | ||
"md-indicators", | ||
"sm-indicators-position", | ||
"md-pause", | ||
'lg-min-width', | ||
'lg-slides-to-show', | ||
'lg-slides-to-scroll', | ||
'lg-controls', | ||
'lg-controls-position', | ||
'lg-draggable', | ||
'lg-autoplay', | ||
'lg-autoplay-interval', | ||
'lg-autoplay-velocity', | ||
'lg-control-prev-icon-src', | ||
'lg-control-next-icon-src', | ||
'lg-indicator-inactive-icon-src', | ||
'lg-indicator-active-icon-src', | ||
'lg-angle', | ||
'lg-set-active-slide', | ||
'lg-pause-on-hover', | ||
'lg-sticky', | ||
'lg-indicators', | ||
'lg-indicators-position', | ||
'lg-pause', | ||
"lg-min-width", | ||
"lg-slides-to-show", | ||
"lg-slides-to-scroll", | ||
"lg-controls", | ||
"lg-controls-position", | ||
"lg-draggable", | ||
"lg-autoplay", | ||
"lg-autoplay-interval", | ||
"lg-autoplay-velocity", | ||
"lg-control-prev-icon-src", | ||
"lg-control-next-icon-src", | ||
"lg-indicator-inactive-icon-src", | ||
"lg-indicator-active-icon-src", | ||
"lg-angle", | ||
"lg-set-active-slide", | ||
"lg-pause-on-hover", | ||
"lg-sticky", | ||
"lg-indicators", | ||
"lg-indicators-position", | ||
"lg-pause", | ||
'xl-min-width', | ||
'xl-slides-to-show', | ||
'xl-slides-to-scroll', | ||
'xl-controls', | ||
'xl-controls-position', | ||
'xl-draggable', | ||
'xl-autoplay', | ||
'xl-autoplay-interval', | ||
'xl-autoplay-velocity', | ||
'xl-control-prev-icon-src', | ||
'xl-control-next-icon-src', | ||
'xl-indicator-inactive-icon-src', | ||
'xl-indicator-active-icon-src', | ||
'xl-angle', | ||
'xl-set-active-slide', | ||
'xl-pause-on-hover', | ||
'xl-sticky', | ||
'xl-indicators', | ||
'xl-indicators-position', | ||
'xl-pause', | ||
"xl-min-width", | ||
"xl-slides-to-show", | ||
"xl-slides-to-scroll", | ||
"xl-controls", | ||
"xl-controls-position", | ||
"xl-draggable", | ||
"xl-autoplay", | ||
"xl-autoplay-interval", | ||
"xl-autoplay-velocity", | ||
"xl-control-prev-icon-src", | ||
"xl-control-next-icon-src", | ||
"xl-indicator-inactive-icon-src", | ||
"xl-indicator-active-icon-src", | ||
"xl-angle", | ||
"xl-set-active-slide", | ||
"xl-pause-on-hover", | ||
"xl-sticky", | ||
"xl-indicators", | ||
"xl-indicators-position", | ||
"xl-pause", | ||
]; | ||
} | ||
public static tagName = 'bs4-slideshow'; | ||
public static tagName = "bs4-slideshow"; | ||
protected templateAttributes = [ | ||
{ | ||
name: 'class', | ||
name: "class", | ||
required: false, | ||
}, | ||
{ | ||
name: 'handle', | ||
name: "handle", | ||
required: false, | ||
}, | ||
{ | ||
name: 'type', | ||
name: "type", | ||
required: true, | ||
}, | ||
{ | ||
name: 'active', | ||
type: 'boolean', | ||
name: "active", | ||
type: "boolean", | ||
required: false, | ||
}, | ||
{ | ||
name: 'index', | ||
type: 'number', | ||
name: "index", | ||
type: "number", | ||
required: false, | ||
@@ -302,7 +330,9 @@ }, | ||
protected resumeTimer: number | null = null; | ||
protected routerEvents?: EventDispatcher; | ||
/** | ||
* Current breakpoint | ||
*/ | ||
protected breakpoint: Breakpoint = 'xs'; | ||
protected breakpoint: Breakpoint = "xs"; | ||
@@ -319,7 +349,7 @@ protected scope: Scope = { | ||
controls: true, | ||
controlsPosition: 'insite-middle', | ||
controlsPosition: "insite-middle", | ||
pauseOnHover: true, | ||
sticky: false, | ||
indicators: true, | ||
indicatorsPosition: 'insite-bottom', | ||
indicatorsPosition: "insite-bottom", | ||
pause: false, | ||
@@ -330,7 +360,7 @@ draggable: true, | ||
autoplayVelocity: 0.8, | ||
controlPrevIconSrc: '', | ||
controlNextIconSrc: '', | ||
indicatorActiveIconSrc: '', | ||
indicatorInactiveIconSrc: '', | ||
angle: 'horizontal', | ||
controlPrevIconSrc: "", | ||
controlNextIconSrc: "", | ||
indicatorActiveIconSrc: "", | ||
indicatorInactiveIconSrc: "", | ||
angle: "horizontal", | ||
@@ -355,4 +385,4 @@ // Responsive options | ||
// Classes | ||
controlsPositionClass: '', | ||
indicatorsPositionClass: '', | ||
controlsPositionClass: "", | ||
indicatorsPositionClass: "", | ||
}; | ||
@@ -380,3 +410,3 @@ | ||
* Go to slide by index | ||
* @param index | ||
* @param index | ||
*/ | ||
@@ -389,7 +419,10 @@ public goTo(index: number) { | ||
if (!this.scope.items[index]) { | ||
console.error(`Slide with index "${index}" not found!`, this.scope.items[index]); | ||
console.error( | ||
`Slide with index "${index}" not found!`, | ||
this.scope.items[index] | ||
); | ||
return; | ||
} | ||
if (this.scope.angle === 'vertical') { | ||
if (this.scope.angle === "vertical") { | ||
// Check if we do not need to slide | ||
@@ -400,3 +433,5 @@ if (this.scope.items[index].position.centerY === 0) { | ||
} | ||
top = this.slideshowInner.scrollTop + this.scope.items[index].position.centerY; | ||
top = | ||
this.slideshowInner.scrollTop + | ||
this.scope.items[index].position.centerY; | ||
} else { | ||
@@ -408,3 +443,5 @@ // Check if we do not need to slide | ||
} | ||
left = this.slideshowInner.scrollLeft + this.scope.items[index].position.centerX; | ||
left = | ||
this.slideshowInner.scrollLeft + | ||
this.scope.items[index].position.centerX; | ||
} | ||
@@ -415,5 +452,5 @@ | ||
// if is is window to scroll | ||
if (typeof(this.slideshowInner.scroll) === 'function') { | ||
if (typeof this.slideshowInner.scroll === "function") { | ||
this.slideshowInner.scroll({ | ||
behavior: 'smooth', | ||
behavior: "smooth", | ||
left, | ||
@@ -423,3 +460,3 @@ top, | ||
} else { | ||
if (this.scope.angle === 'vertical') { | ||
if (this.scope.angle === "vertical") { | ||
this.slideshowInner.scrollTop = top; | ||
@@ -433,40 +470,134 @@ } else { | ||
protected setOptions(dest: ResponsiveOptions | Options, source: ResponsiveOptions | Options) { | ||
dest.slidesToScroll = typeof(source.slidesToScroll) !== 'undefined' ? clone(false, source.slidesToScroll) : dest.slidesToScroll; | ||
dest.controls = typeof(source.controls) !== 'undefined' ? clone(false, source.controls) : dest.controls; | ||
dest.controlsPosition = typeof(source.controlsPosition) !== 'undefined' ? clone(false, source.controlsPosition) : dest.controlsPosition; | ||
dest.draggable = typeof(source.draggable) !== 'undefined' ? clone(false, source.draggable) : dest.draggable; | ||
dest.autoplay = typeof(source.autoplay) !== 'undefined' ? clone(false, source.autoplay) : dest.autoplay; | ||
dest.autoplayInterval = typeof(source.autoplayInterval) !== 'undefined' ? clone(false, source.autoplayInterval) : dest.autoplayInterval; | ||
dest.autoplayVelocity = typeof(source.autoplayVelocity) !== 'undefined' ? clone(false, source.autoplayVelocity) : dest.autoplayVelocity; | ||
dest.controlPrevIconSrc = typeof(source.controlPrevIconSrc) !== 'undefined' ? clone(false, source.controlPrevIconSrc) : dest.controlPrevIconSrc; | ||
dest.controlNextIconSrc = typeof(source.controlNextIconSrc) !== 'undefined' ? clone(false, source.controlNextIconSrc) : dest.controlNextIconSrc; | ||
dest.indicatorActiveIconSrc = typeof(source.indicatorActiveIconSrc) !== 'undefined' ? clone(false, source.indicatorActiveIconSrc) : dest.indicatorActiveIconSrc; | ||
dest.indicatorInactiveIconSrc = typeof(source.indicatorInactiveIconSrc) !== 'undefined' ? clone(false, source.indicatorInactiveIconSrc) : dest.indicatorInactiveIconSrc; | ||
dest.angle = typeof(source.angle) !== 'undefined' ? clone(false, source.angle) : dest.angle; | ||
dest.pauseOnHover = typeof(source.pauseOnHover) !== 'undefined' ? clone(false, source.pauseOnHover) : dest.pauseOnHover; | ||
dest.sticky = typeof(source.sticky) !== 'undefined' ? clone(false, source.sticky) : dest.sticky; | ||
dest.indicators = typeof(source.indicators) !== 'undefined' ? clone(false, source.indicators) : dest.indicators; | ||
dest.indicatorsPosition = typeof(source.indicatorsPosition) !== 'undefined' ? clone(false, source.indicatorsPosition) : dest.indicatorsPosition; | ||
dest.pause = typeof(source.pause) !== 'undefined' ? clone(false, source.pause) : dest.pause; | ||
protected setOptions( | ||
dest: ResponsiveOptions | Options, | ||
source: ResponsiveOptions | Options | ||
) { | ||
dest.slidesToScroll = | ||
typeof source.slidesToScroll !== "undefined" | ||
? clone(false, source.slidesToScroll) | ||
: dest.slidesToScroll; | ||
dest.controls = | ||
typeof source.controls !== "undefined" | ||
? clone(false, source.controls) | ||
: dest.controls; | ||
dest.controlsPosition = | ||
typeof source.controlsPosition !== "undefined" | ||
? clone(false, source.controlsPosition) | ||
: dest.controlsPosition; | ||
dest.draggable = | ||
typeof source.draggable !== "undefined" | ||
? clone(false, source.draggable) | ||
: dest.draggable; | ||
dest.autoplay = | ||
typeof source.autoplay !== "undefined" | ||
? clone(false, source.autoplay) | ||
: dest.autoplay; | ||
dest.autoplayInterval = | ||
typeof source.autoplayInterval !== "undefined" | ||
? clone(false, source.autoplayInterval) | ||
: dest.autoplayInterval; | ||
dest.autoplayVelocity = | ||
typeof source.autoplayVelocity !== "undefined" | ||
? clone(false, source.autoplayVelocity) | ||
: dest.autoplayVelocity; | ||
dest.controlPrevIconSrc = | ||
typeof source.controlPrevIconSrc !== "undefined" | ||
? clone(false, source.controlPrevIconSrc) | ||
: dest.controlPrevIconSrc; | ||
dest.controlNextIconSrc = | ||
typeof source.controlNextIconSrc !== "undefined" | ||
? clone(false, source.controlNextIconSrc) | ||
: dest.controlNextIconSrc; | ||
dest.indicatorActiveIconSrc = | ||
typeof source.indicatorActiveIconSrc !== "undefined" | ||
? clone(false, source.indicatorActiveIconSrc) | ||
: dest.indicatorActiveIconSrc; | ||
dest.indicatorInactiveIconSrc = | ||
typeof source.indicatorInactiveIconSrc !== "undefined" | ||
? clone(false, source.indicatorInactiveIconSrc) | ||
: dest.indicatorInactiveIconSrc; | ||
dest.angle = | ||
typeof source.angle !== "undefined" | ||
? clone(false, source.angle) | ||
: dest.angle; | ||
dest.pauseOnHover = | ||
typeof source.pauseOnHover !== "undefined" | ||
? clone(false, source.pauseOnHover) | ||
: dest.pauseOnHover; | ||
dest.sticky = | ||
typeof source.sticky !== "undefined" | ||
? clone(false, source.sticky) | ||
: dest.sticky; | ||
dest.indicators = | ||
typeof source.indicators !== "undefined" | ||
? clone(false, source.indicators) | ||
: dest.indicators; | ||
dest.indicatorsPosition = | ||
typeof source.indicatorsPosition !== "undefined" | ||
? clone(false, source.indicatorsPosition) | ||
: dest.indicatorsPosition; | ||
dest.pause = | ||
typeof source.pause !== "undefined" | ||
? clone(false, source.pause) | ||
: dest.pause; | ||
} | ||
protected setOptionsIfUndefined(dest: ResponsiveOptions | Options, source: ResponsiveOptions | Options) { | ||
dest.slidesToScroll = typeof(dest.slidesToScroll) === 'undefined' ? source.slidesToScroll : dest.slidesToScroll; | ||
dest.controls = typeof(dest.controls) === 'undefined' ? source.controls : dest.controls; | ||
dest.controlsPosition = typeof(dest.controlsPosition) === 'undefined' ? source.controlsPosition : dest.controlsPosition; | ||
dest.draggable = typeof(dest.draggable) === 'undefined' ? source.draggable : dest.draggable; | ||
dest.autoplay = typeof(dest.autoplay) === 'undefined' ? source.autoplay : dest.autoplay; | ||
dest.autoplayInterval = typeof(dest.autoplayInterval) === 'undefined' ? source.autoplayInterval : dest.autoplayInterval; | ||
dest.autoplayVelocity = typeof(dest.autoplayVelocity) === 'undefined' ? source.autoplayVelocity : dest.autoplayVelocity; | ||
dest.controlPrevIconSrc = typeof(dest.controlPrevIconSrc) === 'undefined' ? source.controlPrevIconSrc : dest.controlPrevIconSrc; | ||
dest.controlNextIconSrc = typeof(dest.controlNextIconSrc) === 'undefined' ? source.controlNextIconSrc : dest.controlNextIconSrc; | ||
dest.indicatorActiveIconSrc = typeof(dest.indicatorActiveIconSrc) === 'undefined' ? source.indicatorActiveIconSrc : dest.indicatorActiveIconSrc; | ||
dest.indicatorInactiveIconSrc = typeof(dest.indicatorInactiveIconSrc) === 'undefined' ? source.indicatorInactiveIconSrc : dest.indicatorInactiveIconSrc; | ||
dest.angle = typeof(dest.angle) === 'undefined' ? source.angle : dest.angle; | ||
dest.pauseOnHover = typeof(dest.pauseOnHover) === 'undefined' ? source.pauseOnHover : dest.pauseOnHover; | ||
dest.sticky = typeof(dest.sticky) === 'undefined' ? source.sticky : dest.sticky; | ||
dest.indicators = typeof(dest.indicators) === 'undefined' ? source.indicators : dest.indicators; | ||
dest.indicatorsPosition = typeof(dest.indicatorsPosition) === 'undefined' ? source.indicatorsPosition : dest.indicatorsPosition; | ||
dest.pause = typeof(dest.pause) === 'undefined' ? source.pause : dest.pause; | ||
protected setOptionsIfUndefined( | ||
dest: ResponsiveOptions | Options, | ||
source: ResponsiveOptions | Options | ||
) { | ||
dest.slidesToScroll = | ||
typeof dest.slidesToScroll === "undefined" | ||
? source.slidesToScroll | ||
: dest.slidesToScroll; | ||
dest.controls = | ||
typeof dest.controls === "undefined" ? source.controls : dest.controls; | ||
dest.controlsPosition = | ||
typeof dest.controlsPosition === "undefined" | ||
? source.controlsPosition | ||
: dest.controlsPosition; | ||
dest.draggable = | ||
typeof dest.draggable === "undefined" ? source.draggable : dest.draggable; | ||
dest.autoplay = | ||
typeof dest.autoplay === "undefined" ? source.autoplay : dest.autoplay; | ||
dest.autoplayInterval = | ||
typeof dest.autoplayInterval === "undefined" | ||
? source.autoplayInterval | ||
: dest.autoplayInterval; | ||
dest.autoplayVelocity = | ||
typeof dest.autoplayVelocity === "undefined" | ||
? source.autoplayVelocity | ||
: dest.autoplayVelocity; | ||
dest.controlPrevIconSrc = | ||
typeof dest.controlPrevIconSrc === "undefined" | ||
? source.controlPrevIconSrc | ||
: dest.controlPrevIconSrc; | ||
dest.controlNextIconSrc = | ||
typeof dest.controlNextIconSrc === "undefined" | ||
? source.controlNextIconSrc | ||
: dest.controlNextIconSrc; | ||
dest.indicatorActiveIconSrc = | ||
typeof dest.indicatorActiveIconSrc === "undefined" | ||
? source.indicatorActiveIconSrc | ||
: dest.indicatorActiveIconSrc; | ||
dest.indicatorInactiveIconSrc = | ||
typeof dest.indicatorInactiveIconSrc === "undefined" | ||
? source.indicatorInactiveIconSrc | ||
: dest.indicatorInactiveIconSrc; | ||
dest.angle = typeof dest.angle === "undefined" ? source.angle : dest.angle; | ||
dest.pauseOnHover = | ||
typeof dest.pauseOnHover === "undefined" | ||
? source.pauseOnHover | ||
: dest.pauseOnHover; | ||
dest.sticky = | ||
typeof dest.sticky === "undefined" ? source.sticky : dest.sticky; | ||
dest.indicators = | ||
typeof dest.indicators === "undefined" | ||
? source.indicators | ||
: dest.indicators; | ||
dest.indicatorsPosition = | ||
typeof dest.indicatorsPosition === "undefined" | ||
? source.indicatorsPosition | ||
: dest.indicatorsPosition; | ||
dest.pause = typeof dest.pause === "undefined" ? source.pause : dest.pause; | ||
} | ||
@@ -485,9 +616,18 @@ | ||
protected setControlsOptions() { | ||
const xsControlsPosition = this.scope.xs.controlsPosition?.split( | ||
"-" | ||
) as ControlsPosition[]; | ||
const smControlsPosition = this.scope.sm.controlsPosition?.split( | ||
"-" | ||
) as ControlsPosition[]; | ||
const mdControlsPosition = this.scope.md.controlsPosition?.split( | ||
"-" | ||
) as ControlsPosition[]; | ||
const lgControlsPosition = this.scope.lg.controlsPosition?.split( | ||
"-" | ||
) as ControlsPosition[]; | ||
const xlControlsPosition = this.scope.xl.controlsPosition?.split( | ||
"-" | ||
) as ControlsPosition[]; | ||
const xsControlsPosition = this.scope.xs.controlsPosition?.split('-') as ControlsPosition[]; | ||
const smControlsPosition = this.scope.sm.controlsPosition?.split('-') as ControlsPosition[]; | ||
const mdControlsPosition = this.scope.md.controlsPosition?.split('-') as ControlsPosition[]; | ||
const lgControlsPosition = this.scope.lg.controlsPosition?.split('-') as ControlsPosition[]; | ||
const xlControlsPosition = this.scope.xl.controlsPosition?.split('-') as ControlsPosition[]; | ||
this.scope.controlsPositionClass = `control-${xsControlsPosition[0]} control-${xsControlsPosition[1]} control-sm-${smControlsPosition[0]} control-sm-${smControlsPosition[1]} control-md-${mdControlsPosition[0]} control-md-${mdControlsPosition[1]} control-lg-${lgControlsPosition[0]} control-lg-${lgControlsPosition[1]} control-xl-${xlControlsPosition[0]} control-xl-${xlControlsPosition[1]}`; | ||
@@ -497,9 +637,18 @@ } | ||
protected setIndicatorsOptions() { | ||
const xsIndicatorsPosition = this.scope.xs.indicatorsPosition?.split( | ||
"-" | ||
) as IndicatorsPosition[]; | ||
const smIndicatorsPosition = this.scope.sm.indicatorsPosition?.split( | ||
"-" | ||
) as IndicatorsPosition[]; | ||
const mdIndicatorsPosition = this.scope.md.indicatorsPosition?.split( | ||
"-" | ||
) as IndicatorsPosition[]; | ||
const lgIndicatorsPosition = this.scope.lg.indicatorsPosition?.split( | ||
"-" | ||
) as IndicatorsPosition[]; | ||
const xlIndicatorsPosition = this.scope.xl.indicatorsPosition?.split( | ||
"-" | ||
) as IndicatorsPosition[]; | ||
const xsIndicatorsPosition = this.scope.xs.indicatorsPosition?.split('-') as IndicatorsPosition[]; | ||
const smIndicatorsPosition = this.scope.sm.indicatorsPosition?.split('-') as IndicatorsPosition[]; | ||
const mdIndicatorsPosition = this.scope.md.indicatorsPosition?.split('-') as IndicatorsPosition[]; | ||
const lgIndicatorsPosition = this.scope.lg.indicatorsPosition?.split('-') as IndicatorsPosition[]; | ||
const xlIndicatorsPosition = this.scope.xl.indicatorsPosition?.split('-') as IndicatorsPosition[]; | ||
this.scope.indicatorsPositionClass = `indicators-${xsIndicatorsPosition[0]} indicators-${xsIndicatorsPosition[1]} indicators-sm-${smIndicatorsPosition[0]} indicators-sm-${smIndicatorsPosition[1]} indicators-md-${mdIndicatorsPosition[0]} indicators-md-${mdIndicatorsPosition[1]} indicators-lg-${lgIndicatorsPosition[0]} indicators-lg-${lgIndicatorsPosition[1]} indicators-xl-${xlIndicatorsPosition[0]} indicators-xl-${xlIndicatorsPosition[1]}`; | ||
@@ -513,18 +662,18 @@ } | ||
if (size >= this.scope.xs.minWidth && size < this.scope.sm.minWidth) { | ||
return 'xs'; | ||
return "xs"; | ||
} | ||
// SM | ||
if (size >= this.scope.sm.minWidth && size < this.scope.md.minWidth) { | ||
return 'sm'; | ||
return "sm"; | ||
} | ||
// MD | ||
if (size >= this.scope.md.minWidth && size < this.scope.lg.minWidth) { | ||
return 'md'; | ||
return "md"; | ||
} | ||
// LG | ||
if (size >= this.scope.lg.minWidth && size < this.scope.xl.minWidth) { | ||
return 'lg'; | ||
return "lg"; | ||
} | ||
// XL | ||
return 'xl'; | ||
return "xl"; | ||
} | ||
@@ -552,3 +701,3 @@ | ||
protected onResize() { | ||
protected onViewChanges() { | ||
const newBreakpoint = this.getBreakpoint(); | ||
@@ -625,28 +774,69 @@ if (newBreakpoint !== this.breakpoint) { | ||
protected addEventListeners() { | ||
window.addEventListener('resize', this.onResize.bind(this), {passive: true}); | ||
if (!this.routerEvents) { | ||
this.routerEvents = new EventDispatcher("main"); | ||
} | ||
this.routerEvents.on("newPageReady", this.onBreakpointChanges.bind(this)); | ||
window.addEventListener("resize", this.onViewChanges.bind(this), { | ||
passive: true, | ||
}); | ||
// Custom event triggered by some parent components when this component changes his visibility, e.g. triggered in the bs4-tabs component | ||
this.el.addEventListener('visibility-changed' as any, this.onVisibilityChanged.bind(this)); | ||
this.el.addEventListener( | ||
"visibility-changed" as any, | ||
this.onVisibilityChanged.bind(this) | ||
); | ||
this.slideshowInner.addEventListener('scroll', this.onScroll.bind(this), { passive: true}); | ||
this.slideshowInner.addEventListener('scrollended', this.onScrollend.bind(this), {passive: true}); | ||
this.slideshowInner.addEventListener("scroll", this.onScroll.bind(this), { | ||
passive: true, | ||
}); | ||
this.slideshowInner.addEventListener( | ||
"scrollended", | ||
this.onScrollend.bind(this), | ||
{ passive: true } | ||
); | ||
this.el.addEventListener('mouseenter', this.onMouseIn.bind(this), {passive: true}); | ||
this.el.addEventListener('mouseover', this.onMouseIn.bind(this), {passive: true}); | ||
this.el.addEventListener('focusin', this.onMouseIn.bind(this), {passive: true}); | ||
this.el.addEventListener('touchstart', this.onMouseIn.bind(this), {passive: true}); | ||
this.el.addEventListener("mouseenter", this.onMouseIn.bind(this), { | ||
passive: true, | ||
}); | ||
this.el.addEventListener("mouseover", this.onMouseIn.bind(this), { | ||
passive: true, | ||
}); | ||
this.el.addEventListener("focusin", this.onMouseIn.bind(this), { | ||
passive: true, | ||
}); | ||
this.el.addEventListener("touchstart", this.onMouseIn.bind(this), { | ||
passive: true, | ||
}); | ||
this.el.addEventListener('mouseout', this.onMouseOut.bind(this), {passive: true}); | ||
this.el.addEventListener('mouseleave', this.onMouseOut.bind(this), {passive: true}); | ||
this.el.addEventListener('focusout', this.onMouseOut.bind(this), {passive: true}); | ||
this.el.addEventListener("mouseout", this.onMouseOut.bind(this), { | ||
passive: true, | ||
}); | ||
this.el.addEventListener("mouseleave", this.onMouseOut.bind(this), { | ||
passive: true, | ||
}); | ||
this.el.addEventListener("focusout", this.onMouseOut.bind(this), { | ||
passive: true, | ||
}); | ||
this.el.addEventListener('mouseup', this.onMouseUp.bind(this), {passive: true}); | ||
this.el.addEventListener('touchend', this.onMouseUp.bind(this), {passive: true}); | ||
this.el.addEventListener('scroll', this.onMouseUp.bind(this), {passive: true}); | ||
this.el.addEventListener('scrollend', this.onMouseUp.bind(this), {passive: true}); | ||
this.el.addEventListener("mouseup", this.onMouseUp.bind(this), { | ||
passive: true, | ||
}); | ||
this.el.addEventListener("touchend", this.onMouseUp.bind(this), { | ||
passive: true, | ||
}); | ||
this.el.addEventListener("scroll", this.onMouseUp.bind(this), { | ||
passive: true, | ||
}); | ||
this.el.addEventListener("scrollend", this.onMouseUp.bind(this), { | ||
passive: true, | ||
}); | ||
// See ScrollEventsService for this event | ||
this.el.addEventListener('scrollended', this.onMouseUp.bind(this), {passive: true}); | ||
this.el.addEventListener("scrollended", this.onMouseUp.bind(this), { | ||
passive: true, | ||
}); | ||
// inital | ||
this.onResize(); | ||
this.onViewChanges(); | ||
// this.onScroll(); | ||
@@ -657,17 +847,23 @@ this.onScrollend(); | ||
protected removeEventListeners() { | ||
window.removeEventListener('resize', this.onResize.bind(this)); | ||
window.removeEventListener("resize", this.onViewChanges.bind(this)); | ||
this.el.removeEventListener('visibility-changed' as any, this.onVisibilityChanged.bind(this)); | ||
this.el.removeEventListener( | ||
"visibility-changed" as any, | ||
this.onVisibilityChanged.bind(this) | ||
); | ||
this.slideshowInner.removeEventListener('scroll', this.onScroll.bind(this)); | ||
this.slideshowInner.removeEventListener('scrollended', this.onScrollend.bind(this)); | ||
this.slideshowInner.removeEventListener("scroll", this.onScroll.bind(this)); | ||
this.slideshowInner.removeEventListener( | ||
"scrollended", | ||
this.onScrollend.bind(this) | ||
); | ||
this.el.removeEventListener('mouseenter', this.onMouseIn.bind(this)); | ||
this.el.removeEventListener('mouseover', this.onMouseIn.bind(this)); | ||
this.el.removeEventListener('focusin', this.onMouseIn.bind(this)); | ||
this.el.removeEventListener('touchstart', this.onMouseIn.bind(this)); | ||
this.el.removeEventListener("mouseenter", this.onMouseIn.bind(this)); | ||
this.el.removeEventListener("mouseover", this.onMouseIn.bind(this)); | ||
this.el.removeEventListener("focusin", this.onMouseIn.bind(this)); | ||
this.el.removeEventListener("touchstart", this.onMouseIn.bind(this)); | ||
this.el.removeEventListener('mouseout', this.onMouseOut.bind(this)); | ||
this.el.removeEventListener('mouseleave', this.onMouseOut.bind(this)); | ||
this.el.removeEventListener('focusout', this.onMouseOut.bind(this)); | ||
this.el.removeEventListener("mouseout", this.onMouseOut.bind(this)); | ||
this.el.removeEventListener("mouseleave", this.onMouseOut.bind(this)); | ||
this.el.removeEventListener("focusout", this.onMouseOut.bind(this)); | ||
} | ||
@@ -683,3 +879,3 @@ | ||
this.initResponsiveOptions(); | ||
this.removeEventListeners(); | ||
// this.removeEventListeners(); | ||
this.addEventListeners(); | ||
@@ -689,7 +885,5 @@ } | ||
protected initSlideshowInner() { | ||
this.initSlideshowInnerSlides(); | ||
this.scrollEventsService = new ScrollEventsService(this.slideshowInner); | ||
} | ||
@@ -699,4 +893,7 @@ | ||
if (!this.dragscrollService) { | ||
const dragscrollOptions: DragscrollOptions = {detectGlobalMove: true}; | ||
this.dragscrollService = new Dragscroll(this.slideshowInner, dragscrollOptions); | ||
const dragscrollOptions: DragscrollOptions = { detectGlobalMove: true }; | ||
this.dragscrollService = new Dragscroll( | ||
this.slideshowInner, | ||
dragscrollOptions | ||
); | ||
} | ||
@@ -706,3 +903,3 @@ } | ||
protected disableDesktopDragscroll() { | ||
if (this.dragscrollService ) { | ||
if (this.dragscrollService) { | ||
this.dragscrollService.destroy(); | ||
@@ -720,3 +917,6 @@ this.dragscrollService = undefined; | ||
}; | ||
this.continuousAutoplayService = new Autoscroll(this.slideshowInner, autoscrollOptions); | ||
this.continuousAutoplayService = new Autoscroll( | ||
this.slideshowInner, | ||
autoscrollOptions | ||
); | ||
} | ||
@@ -728,3 +928,6 @@ // on continuous autoplay the scrollended event is never triggered, so call this method all `intervalsTimeMs` milliseconds as a WORKAROUND | ||
// console.debug('intervalsTimeMs', intervalsTimeMs); | ||
this.continuousAutoplayIntervalIndex = window.setInterval(this.onScrollend.bind(this), intervalsTimeMs); | ||
this.continuousAutoplayIntervalIndex = window.setInterval( | ||
this.onScrollend.bind(this), | ||
intervalsTimeMs | ||
); | ||
} | ||
@@ -761,3 +964,2 @@ } | ||
protected disableAutoplay() { | ||
@@ -779,3 +981,3 @@ this.disableIntervalAutoplay(); | ||
if (!this.slideElements) { | ||
throw new Error('No slides found!'); | ||
throw new Error("No slides found!"); | ||
} | ||
@@ -787,3 +989,2 @@ | ||
} | ||
} | ||
@@ -795,4 +996,4 @@ | ||
attributes.index = index; | ||
attributes.class = attributes.class || ''; | ||
attributes.class += ' slide'; | ||
attributes.class = attributes.class || ""; | ||
attributes.class += " slide"; | ||
return attributes; | ||
@@ -809,9 +1010,9 @@ } | ||
if (attributes.type) { | ||
if (attributes.type === 'slide') { | ||
this.scope.items.push({...attributes, content}); | ||
if (attributes.type === "slide") { | ||
this.scope.items.push({ ...attributes, content }); | ||
} | ||
if (attributes.type === 'controls') { | ||
if (attributes.type === "controls") { | ||
this.templateControls = content; | ||
} | ||
if (attributes.type === 'indicators') { | ||
if (attributes.type === "indicators") { | ||
this.templateIndicators = content; | ||
@@ -831,4 +1032,7 @@ } | ||
this.slideElements.forEach((slideElement, index) => { | ||
const handle = slideElement.getAttribute('handle') || slideElement.getAttribute('id') || index.toString(); | ||
slideElement.setAttribute('index', index.toString()); | ||
const handle = | ||
slideElement.getAttribute("handle") || | ||
slideElement.getAttribute("id") || | ||
index.toString(); | ||
slideElement.setAttribute("index", index.toString()); | ||
const attributes = { | ||
@@ -839,3 +1043,7 @@ handle, | ||
index, | ||
position: {...slideElement.getBoundingClientRect(), centerY: 0, centerX: 0}, | ||
position: { | ||
...slideElement.getBoundingClientRect(), | ||
centerY: 0, | ||
centerX: 0, | ||
}, | ||
}; | ||
@@ -866,7 +1074,15 @@ this.scope.items.push(attributes); | ||
} | ||
let nearZero = Math.abs(this.scope.angle === 'vertical' ? this.scope.items[0].position.centerY : this.scope.items[0].position.centerX); | ||
let nearZero = Math.abs( | ||
this.scope.angle === "vertical" | ||
? this.scope.items[0].position.centerY | ||
: this.scope.items[0].position.centerX | ||
); | ||
let minIndex = 0; | ||
for (let i = 1; i < this.scope.items.length; i++) { | ||
const position = Math.abs(this.scope.angle === 'vertical' ? this.scope.items[i].position.centerY : this.scope.items[i].position.centerX); | ||
const position = Math.abs( | ||
this.scope.angle === "vertical" | ||
? this.scope.items[i].position.centerY | ||
: this.scope.items[i].position.centerX | ||
); | ||
nearZero = this.getCurrentClosestNumber(0, position, nearZero); | ||
@@ -889,4 +1105,7 @@ if (nearZero === position) { | ||
} | ||
if (this.slideElements[index] && this.slideElements[index].classList.remove) { | ||
this.slideElements[index].classList.remove('active'); | ||
if ( | ||
this.slideElements[index] && | ||
this.slideElements[index].classList.remove | ||
) { | ||
this.slideElements[index].classList.remove("active"); | ||
} | ||
@@ -905,3 +1124,3 @@ } | ||
if (this.slideElements && this.slideElements[index].classList.add) { | ||
this.slideElements[index].classList.add('active'); | ||
this.slideElements[index].classList.add("active"); | ||
} | ||
@@ -915,4 +1134,12 @@ return index; | ||
} | ||
const maxScrollTo = this.scope.angle === 'vertical' ? this.getScrollPosition().maxY : this.getScrollPosition().maxX; | ||
const scrollTo = this.scope.angle === 'vertical' ? this.slideshowInner.scrollTop + this.scope.items[index].position.centerY : this.slideshowInner.scrollLeft + this.scope.items[index].position.centerX; | ||
const maxScrollTo = | ||
this.scope.angle === "vertical" | ||
? this.getScrollPosition().maxY | ||
: this.getScrollPosition().maxX; | ||
const scrollTo = | ||
this.scope.angle === "vertical" | ||
? this.slideshowInner.scrollTop + | ||
this.scope.items[index].position.centerY | ||
: this.slideshowInner.scrollLeft + | ||
this.scope.items[index].position.centerX; | ||
return scrollTo <= maxScrollTo && scrollTo >= 0; | ||
@@ -947,3 +1174,3 @@ } | ||
if (prevIndex < 0) { | ||
prevIndex = (this.slideElements.length - 1) + (prevIndex + 1); | ||
prevIndex = this.slideElements.length - 1 + (prevIndex + 1); | ||
} | ||
@@ -962,3 +1189,5 @@ | ||
if (this.scope.items.length !== this.slideElements?.length) { | ||
console.warn(`The slide objects must be the same size as the slide elements! ${this.scope.items.length} !== ${this.slideElements?.length}`); | ||
console.warn( | ||
`The slide objects must be the same size as the slide elements! ${this.scope.items.length} !== ${this.slideElements?.length}` | ||
); | ||
return; | ||
@@ -986,5 +1215,5 @@ } | ||
// 0 if element is in the middle / center | ||
centerY: (rect.y + (rect.height / 2)) - mainBoundingClient.height / 2, | ||
centerY: rect.y + rect.height / 2 - mainBoundingClient.height / 2, | ||
// 0 if element is in the middle / center | ||
centerX: (rect.x + (rect.width / 2)) - mainBoundingClient.width / 2, | ||
centerX: rect.x + rect.width / 2 - mainBoundingClient.width / 2, | ||
}; | ||
@@ -1006,9 +1235,16 @@ } | ||
*/ | ||
protected attributeChangedCallback(attributeName: string, oldValue: any, newValue: any, namespace: string | null) { | ||
protected attributeChangedCallback( | ||
attributeName: string, | ||
oldValue: any, | ||
newValue: any, | ||
namespace: string | null | ||
) { | ||
let optionForSize: Breakpoint = "xs"; | ||
let optionForSize: Breakpoint = 'xs'; | ||
let responsiveScope: ResponsiveOptions | Options = this.scope; | ||
if (this.observedAttributesToCheck && this.observedAttributesToCheck[attributeName]) { | ||
if ( | ||
this.observedAttributesToCheck && | ||
this.observedAttributesToCheck[attributeName] | ||
) { | ||
this.observedAttributesToCheck[attributeName].initialized = true; | ||
@@ -1019,16 +1255,16 @@ } | ||
if (attributeName.startsWith('sm-')) { | ||
optionForSize = 'sm'; | ||
if (attributeName.startsWith("sm-")) { | ||
optionForSize = "sm"; | ||
responsiveScope = this.scope.sm; | ||
attributeName = attributeName.slice(3); | ||
} else if (attributeName.startsWith('md-')) { | ||
optionForSize = 'md'; | ||
} else if (attributeName.startsWith("md-")) { | ||
optionForSize = "md"; | ||
responsiveScope = this.scope.md; | ||
attributeName = attributeName.slice(3); | ||
} else if (attributeName.startsWith('lg-')) { | ||
optionForSize = 'lg'; | ||
} else if (attributeName.startsWith("lg-")) { | ||
optionForSize = "lg"; | ||
responsiveScope = this.scope.lg; | ||
attributeName = attributeName.slice(3); | ||
} else if (attributeName.startsWith('xl-')) { | ||
optionForSize = 'xl'; | ||
} else if (attributeName.startsWith("xl-")) { | ||
optionForSize = "xl"; | ||
responsiveScope = this.scope.xl; | ||
@@ -1038,6 +1274,4 @@ attributeName = attributeName.slice(3); | ||
const parsedAttributeName = camelCase(attributeName); | ||
if (responsiveScope && (responsiveScope as any)[parsedAttributeName]) { | ||
@@ -1051,3 +1285,8 @@ oldValue = (responsiveScope as any)[parsedAttributeName]; | ||
// call custom attribute changed callback with parsed values | ||
this.parsedAttributeChangedCallback(optionForSize + parsedAttributeName, oldValue, newValue, namespace); | ||
this.parsedAttributeChangedCallback( | ||
optionForSize + parsedAttributeName, | ||
oldValue, | ||
newValue, | ||
namespace | ||
); | ||
@@ -1064,4 +1303,14 @@ this.bindIfReady(); | ||
*/ | ||
protected parsedAttributeChangedCallback(attributeName: string, oldValue: any, newValue: any, namespace: string | null) { | ||
return super.parsedAttributeChangedCallback(attributeName, oldValue, newValue, namespace); | ||
protected parsedAttributeChangedCallback( | ||
attributeName: string, | ||
oldValue: any, | ||
newValue: any, | ||
namespace: string | null | ||
) { | ||
return super.parsedAttributeChangedCallback( | ||
attributeName, | ||
oldValue, | ||
newValue, | ||
namespace | ||
); | ||
} | ||
@@ -1068,0 +1317,0 @@ |
@@ -1,6 +0,6 @@ | ||
import { handleizeFormatter } from '@ribajs/core'; | ||
import templateHorizontal from './bs4-tabs-horizontal.component.html'; | ||
import templateVertical from './bs4-tabs-vertical.component.html'; | ||
import { handleizeFormatter } from "@ribajs/core"; | ||
import templateHorizontal from "./bs4-tabs-horizontal.component.html"; | ||
import templateVertical from "./bs4-tabs-vertical.component.html"; | ||
import { TemplatesComponent } from '../templates/templates.component'; | ||
import { TemplatesComponent } from "../templates/templates.component"; | ||
@@ -18,32 +18,31 @@ export interface Tab { | ||
items: Tab[]; | ||
activate: Bs4TabsComponent['activate']; | ||
deactivate: Bs4TabsComponent['activate']; | ||
deactivateAll: Bs4TabsComponent['deactivateAll']; | ||
activate: Bs4TabsComponent["activate"]; | ||
deactivate: Bs4TabsComponent["activate"]; | ||
deactivateAll: Bs4TabsComponent["deactivateAll"]; | ||
optionTabsAutoHeight: boolean; | ||
optionTabsAngle: 'vertical' | 'horizontal'; | ||
optionTabsAngle: "vertical" | "horizontal"; | ||
} | ||
export class Bs4TabsComponent extends TemplatesComponent { | ||
public static tagName = "bs4-tabs"; | ||
public static tagName = 'bs4-tabs'; | ||
protected templateAttributes = [ | ||
{ | ||
name: 'title', | ||
name: "title", | ||
required: true, | ||
}, | ||
{ | ||
name: 'handle', | ||
name: "handle", | ||
required: false, | ||
}, | ||
{ | ||
name: 'type', | ||
name: "type", | ||
required: false, | ||
}, | ||
{ | ||
name: 'active', | ||
name: "active", | ||
required: false, | ||
}, | ||
{ | ||
name: 'index', | ||
name: "index", | ||
required: false, | ||
@@ -57,5 +56,5 @@ }, | ||
deactivate: this.deactivate, | ||
deactivateAll:this.deactivateAll, | ||
deactivateAll: this.deactivateAll, | ||
optionTabsAutoHeight: false, | ||
optionTabsAngle: 'horizontal', | ||
optionTabsAngle: "horizontal", | ||
}; | ||
@@ -69,24 +68,64 @@ | ||
return [ | ||
'option-tabs-auto-height', | ||
'option-tabs-angle', | ||
'tab-0-title', 'tab-0-content', 'tab-0-handle', | ||
'tab-1-title', 'tab-1-content', 'tab-1-handle', | ||
'tab-2-title', 'tab-2-content', 'tab-2-handle', | ||
'tab-3-title', 'tab-3-content', 'tab-3-handle', | ||
'tab-4-title', 'tab-4-content', 'tab-4-handle', | ||
'tab-5-title', 'tab-5-content', 'tab-5-handle', | ||
'tab-6-title', 'tab-6-content', 'tab-6-handle', | ||
'tab-7-title', 'tab-7-content', 'tab-7-handle', | ||
'tab-8-title', 'tab-8-content', 'tab-8-handle', | ||
'tab-9-title', 'tab-9-content', 'tab-9-handle', | ||
'tab-10-title', 'tab-10-content', 'tab-10-handle', | ||
'tab-11-title', 'tab-11-content', 'tab-11-handle', | ||
'tab-12-title', 'tab-12-content', 'tab-12-handle', | ||
'tab-13-title', 'tab-13-content', 'tab-13-handle', | ||
'tab-14-title', 'tab-14-content', 'tab-14-handle', | ||
'tab-15-title', 'tab-15-content', 'tab-15-handle', | ||
'tab-16-title', 'tab-16-content', 'tab-16-handle', | ||
'tab-17-title', 'tab-17-content', 'tab-17-handle', | ||
'tab-18-title', 'tab-18-content', 'tab-18-handle', | ||
'tab-19-title', 'tab-19-content', 'tab-19-handle', | ||
"option-tabs-auto-height", | ||
"option-tabs-angle", | ||
"tab-0-title", | ||
"tab-0-content", | ||
"tab-0-handle", | ||
"tab-1-title", | ||
"tab-1-content", | ||
"tab-1-handle", | ||
"tab-2-title", | ||
"tab-2-content", | ||
"tab-2-handle", | ||
"tab-3-title", | ||
"tab-3-content", | ||
"tab-3-handle", | ||
"tab-4-title", | ||
"tab-4-content", | ||
"tab-4-handle", | ||
"tab-5-title", | ||
"tab-5-content", | ||
"tab-5-handle", | ||
"tab-6-title", | ||
"tab-6-content", | ||
"tab-6-handle", | ||
"tab-7-title", | ||
"tab-7-content", | ||
"tab-7-handle", | ||
"tab-8-title", | ||
"tab-8-content", | ||
"tab-8-handle", | ||
"tab-9-title", | ||
"tab-9-content", | ||
"tab-9-handle", | ||
"tab-10-title", | ||
"tab-10-content", | ||
"tab-10-handle", | ||
"tab-11-title", | ||
"tab-11-content", | ||
"tab-11-handle", | ||
"tab-12-title", | ||
"tab-12-content", | ||
"tab-12-handle", | ||
"tab-13-title", | ||
"tab-13-content", | ||
"tab-13-handle", | ||
"tab-14-title", | ||
"tab-14-content", | ||
"tab-14-handle", | ||
"tab-15-title", | ||
"tab-15-content", | ||
"tab-15-handle", | ||
"tab-16-title", | ||
"tab-16-content", | ||
"tab-16-handle", | ||
"tab-17-title", | ||
"tab-17-content", | ||
"tab-17-handle", | ||
"tab-18-title", | ||
"tab-18-content", | ||
"tab-18-handle", | ||
"tab-19-title", | ||
"tab-19-content", | ||
"tab-19-handle", | ||
]; | ||
@@ -114,8 +153,8 @@ } | ||
this.tabPanes.forEach((tabPane) => { | ||
if (!(tabPane as unknown as HTMLElement).style) { | ||
if (!((tabPane as unknown) as HTMLElement).style) { | ||
return; | ||
} | ||
(tabPane as unknown as HTMLElement).style.height = 'auto'; | ||
(tabPane as unknown as HTMLElement).style.display = 'block'; | ||
const height = (tabPane as unknown as HTMLElement).offsetHeight || 0; | ||
((tabPane as unknown) as HTMLElement).style.height = "auto"; | ||
((tabPane as unknown) as HTMLElement).style.display = "block"; | ||
const height = ((tabPane as unknown) as HTMLElement).offsetHeight || 0; | ||
if (height > heigest) { | ||
@@ -126,9 +165,9 @@ heigest = height; | ||
this.tabPanes.forEach((tabPane) => { | ||
if (!(tabPane as unknown as HTMLElement).style) { | ||
if (!((tabPane as unknown) as HTMLElement).style) { | ||
return; | ||
} | ||
// Reset display style property | ||
(tabPane as unknown as HTMLElement).style.display = ''; | ||
((tabPane as unknown) as HTMLElement).style.display = ""; | ||
if (heigest > 0) { | ||
(tabPane as unknown as HTMLElement).style.height = heigest + 'px'; | ||
((tabPane as unknown) as HTMLElement).style.height = heigest + "px"; | ||
} | ||
@@ -160,3 +199,6 @@ }); | ||
if (firstTabContentChild) { | ||
this.triggerVisibilityChangedForElement(firstTabContentChild as Element, tab.active); | ||
this.triggerVisibilityChangedForElement( | ||
firstTabContentChild as Element, | ||
tab.active | ||
); | ||
} | ||
@@ -176,3 +218,7 @@ | ||
protected getTabContentChildByIndex(index: number) { | ||
return this.el.querySelector(`.tab-content .tab-pane:nth-child(${index + 1}) > *`) || undefined; | ||
return ( | ||
this.el.querySelector( | ||
`.tab-content .tab-pane:nth-child(${index + 1}) > *` | ||
) || undefined | ||
); | ||
} | ||
@@ -183,9 +229,14 @@ | ||
* E.g. this event is used the bs4-slideshow component | ||
* @param element | ||
* @param visibile | ||
* @param element | ||
* @param visibile | ||
*/ | ||
protected triggerVisibilityChangedForElement(element: Element, visibile: boolean) { | ||
protected triggerVisibilityChangedForElement( | ||
element: Element, | ||
visibile: boolean | ||
) { | ||
setTimeout(() => { | ||
// Use this event to update any custom element when it becomes visibile | ||
element.dispatchEvent(new CustomEvent('visibility-changed', {detail: {visibile}})); | ||
element.dispatchEvent( | ||
new CustomEvent("visibility-changed", { detail: { visibile } }) | ||
); | ||
}, 200); | ||
@@ -204,3 +255,3 @@ } | ||
this.tabPanes = this.el.querySelectorAll('[role="tabpanel"]'); | ||
this.scrollable = this.el.querySelector('[scrollable]'); | ||
this.scrollable = this.el.querySelector("[scrollable]"); | ||
} | ||
@@ -210,3 +261,9 @@ | ||
while (newSize > this.scope.items.length) { | ||
this.scope.items.push({handle: '', title: '', content: '', active: false, index: this.scope.items.length - 1}); | ||
this.scope.items.push({ | ||
handle: "", | ||
title: "", | ||
content: "", | ||
active: false, | ||
index: this.scope.items.length - 1, | ||
}); | ||
} | ||
@@ -222,3 +279,4 @@ } | ||
const tabScrollPosition = curTab.getBoundingClientRect(); | ||
const scrollLeftTo = this.scrollable.scrollLeft || 0 + tabScrollPosition.left; | ||
const scrollLeftTo = | ||
this.scrollable.scrollLeft || 0 + tabScrollPosition.left; | ||
// TODO animate | ||
@@ -239,11 +297,14 @@ // this.scrollable.animate({ scrollLeft: scrollLeftTo}, 'slow'); | ||
if (this.tabs) { | ||
this.tabs.forEach(((tab) => { | ||
tab.removeEventListener('shown.bs.tab', this.onTabShownEventHandler); | ||
tab.addEventListener('shown.bs.tab', this.onTabShownEventHandler); | ||
})); | ||
this.tabs.forEach((tab) => { | ||
tab.removeEventListener("shown.bs.tab", this.onTabShownEventHandler); | ||
tab.addEventListener("shown.bs.tab", this.onTabShownEventHandler); | ||
}); | ||
} | ||
if (this.scope.optionTabsAutoHeight) { | ||
window.removeEventListener('resize', this.onResizeEventHandler.bind(this)); | ||
window.addEventListener('resize', this.onResizeEventHandler.bind(this)); | ||
window.removeEventListener( | ||
"resize", | ||
this.onResizeEventHandler.bind(this) | ||
); | ||
window.addEventListener("resize", this.onResizeEventHandler.bind(this)); | ||
this.setHeight(); | ||
@@ -254,3 +315,3 @@ } | ||
protected addTabByAttribute(attributeName: string, newValue: string) { | ||
const index = Number(attributeName.replace(/[^0-9]/g, '')); | ||
const index = Number(attributeName.replace(/[^0-9]/g, "")); | ||
if (index >= this.scope.items.length) { | ||
@@ -260,10 +321,12 @@ this.resizeTabsArray(index + 1); | ||
this.scope.items[index].index = index; | ||
if (attributeName.endsWith('Content')) { | ||
if (attributeName.endsWith("Content")) { | ||
this.scope.items[index].content = newValue; | ||
} | ||
if (attributeName.endsWith('Title')) { | ||
if (attributeName.endsWith("Title")) { | ||
this.scope.items[index].title = newValue; | ||
this.scope.items[index].handle = this.scope.items[index].handle || handleizeFormatter.read(this.scope.items[index].title); | ||
this.scope.items[index].handle = | ||
this.scope.items[index].handle || | ||
handleizeFormatter.read(this.scope.items[index].title); | ||
} | ||
if (attributeName.endsWith('Handle')) { | ||
if (attributeName.endsWith("Handle")) { | ||
this.scope.items[index].handle = newValue; | ||
@@ -293,5 +356,15 @@ } | ||
protected parsedAttributeChangedCallback(attributeName: string, oldValue: any, newValue: any, namespace: string | null) { | ||
super.parsedAttributeChangedCallback(attributeName, oldValue, newValue, namespace); | ||
if (attributeName.startsWith('tab')) { | ||
protected parsedAttributeChangedCallback( | ||
attributeName: string, | ||
oldValue: any, | ||
newValue: any, | ||
namespace: string | null | ||
) { | ||
super.parsedAttributeChangedCallback( | ||
attributeName, | ||
oldValue, | ||
newValue, | ||
namespace | ||
); | ||
if (attributeName.startsWith("tab")) { | ||
this.addTabByAttribute(attributeName, newValue); | ||
@@ -314,3 +387,3 @@ this.initTabs(); | ||
if (!this.el.hasChildNodes() || this.hasOnlyTemplateChilds()) { | ||
if (this.scope.optionTabsAngle === 'horizontal') { | ||
if (this.scope.optionTabsAngle === "horizontal") { | ||
return templateHorizontal; | ||
@@ -317,0 +390,0 @@ } else { |
@@ -10,16 +10,19 @@ /** | ||
import { | ||
Component, | ||
EventDispatcher, | ||
} from '@ribajs/core'; | ||
import { Component, EventDispatcher } from "@ribajs/core"; | ||
import { | ||
TOGGLE_BUTTON, | ||
} from '../../constants'; | ||
import { TOGGLE_BUTTON } from "../../constants"; | ||
type State = 'undefined' | 'overlay-left' | 'overlay-right' | 'side-left' | 'side-right' | 'hidden' | 'added' | 'removed'; | ||
type State = | ||
| "undefined" | ||
| "overlay-left" | ||
| "overlay-right" | ||
| "side-left" | ||
| "side-right" | ||
| "hidden" | ||
| "added" | ||
| "removed"; | ||
interface Scope { | ||
targetId?: string; | ||
toggle: Bs4ToggleButtonComponent['toggle']; | ||
toggle: Bs4ToggleButtonComponent["toggle"]; | ||
state: State; | ||
@@ -33,12 +36,11 @@ isActive: boolean; | ||
export class Bs4ToggleButtonComponent extends Component { | ||
static get observedAttributes() { | ||
return ['target-id']; | ||
return ["target-id"]; | ||
} | ||
protected requiredAttributes() { | ||
return ['targetId']; | ||
return ["targetId"]; | ||
} | ||
public static tagName = 'bs4-toggle-button'; | ||
public static tagName = "bs4-toggle-button"; | ||
@@ -52,3 +54,3 @@ protected autobind = true; | ||
toggle: this.toggle, | ||
state: 'undefined', | ||
state: "undefined", | ||
isActive: true, | ||
@@ -65,3 +67,6 @@ isClosed: false, | ||
if (this.eventDispatcher) { | ||
this.eventDispatcher.trigger(TOGGLE_BUTTON.eventNames.toggle, this.scope.targetId); | ||
this.eventDispatcher.trigger( | ||
TOGGLE_BUTTON.eventNames.toggle, | ||
this.scope.targetId | ||
); | ||
} | ||
@@ -73,3 +78,6 @@ } | ||
// Trigger init to trigger there current state of all the components that are connected to this component | ||
return this.eventDispatcher?.trigger(TOGGLE_BUTTON.eventNames.init, this.scope.targetId); | ||
return this.eventDispatcher?.trigger( | ||
TOGGLE_BUTTON.eventNames.init, | ||
this.scope.targetId | ||
); | ||
} | ||
@@ -84,3 +92,3 @@ | ||
this.scope.state = state; | ||
this.scope.isActive = state !== 'hidden' && state !== 'removed'; | ||
this.scope.isActive = state !== "hidden" && state !== "removed"; | ||
this.scope.isClosed = !this.scope.isActive; | ||
@@ -91,17 +99,46 @@ } | ||
if (this.eventDispatcher) { | ||
this.eventDispatcher.off(TOGGLE_BUTTON.eventNames.toggled, this.onToggledEvent); | ||
this.eventDispatcher.off( | ||
TOGGLE_BUTTON.eventNames.toggled, | ||
this.onToggledEvent | ||
); | ||
} | ||
this.eventDispatcher = new EventDispatcher(TOGGLE_BUTTON.nsPrefix + id); | ||
this.eventDispatcher.on(TOGGLE_BUTTON.eventNames.toggled, this.onToggledEvent.bind(this)); | ||
this.eventDispatcher.on( | ||
TOGGLE_BUTTON.eventNames.toggled, | ||
this.onToggledEvent.bind(this) | ||
); | ||
// Triggered state triggered by `..trigger('init', ...` | ||
this.eventDispatcher.on(TOGGLE_BUTTON.eventNames.state, this.onToggledEvent.bind(this)); | ||
this.eventDispatcher.on( | ||
TOGGLE_BUTTON.eventNames.state, | ||
this.onToggledEvent.bind(this) | ||
); | ||
} | ||
protected attributeChangedCallback(attributeName: string, oldValue: any, newValue: any, namespace: string | null) { | ||
super.attributeChangedCallback(attributeName, oldValue, newValue, namespace); | ||
protected attributeChangedCallback( | ||
attributeName: string, | ||
oldValue: any, | ||
newValue: any, | ||
namespace: string | null | ||
) { | ||
super.attributeChangedCallback( | ||
attributeName, | ||
oldValue, | ||
newValue, | ||
namespace | ||
); | ||
} | ||
protected parsedAttributeChangedCallback(attributeName: string, oldValue: any, newValue: any, namespace: string | null) { | ||
super.parsedAttributeChangedCallback(attributeName, oldValue, newValue, namespace); | ||
if (attributeName === 'targetId' && newValue) { | ||
protected parsedAttributeChangedCallback( | ||
attributeName: string, | ||
oldValue: any, | ||
newValue: any, | ||
namespace: string | null | ||
) { | ||
super.parsedAttributeChangedCallback( | ||
attributeName, | ||
oldValue, | ||
newValue, | ||
namespace | ||
); | ||
if (attributeName === "targetId" && newValue) { | ||
this.initEventDispatcher(newValue); | ||
@@ -115,3 +152,6 @@ } | ||
if (this.eventDispatcher) { | ||
this.eventDispatcher.off(TOGGLE_BUTTON.eventNames.toggled, this.onToggledEvent); | ||
this.eventDispatcher.off( | ||
TOGGLE_BUTTON.eventNames.toggled, | ||
this.onToggledEvent | ||
); | ||
} | ||
@@ -122,3 +162,5 @@ } | ||
if (!this.el.hasChildNodes()) { | ||
console.warn('No child elements found, this component as no template so you need to define your own as child of this component.'); | ||
console.warn( | ||
"No child elements found, this component as no template so you need to define your own as child of this component." | ||
); | ||
} | ||
@@ -125,0 +167,0 @@ return null; |
@@ -1,15 +0,16 @@ | ||
export { Bs4DropdownComponent } from './bs4-dropdown/bs4-dropdown.component'; | ||
export { Bs4AccordionComponent } from './bs4-accordion/bs4-accordion.component'; | ||
export { Bs4ButtonComponent } from './bs4-button/bs4-button.component'; | ||
export { Bs4CarouselComponent } from './bs4-carousel/bs4-carousel.component'; | ||
export { Bs4ContentsComponent } from './bs4-contents/bs4-contents.component'; | ||
export { Bs4IconComponent } from './bs4-icon/bs4-icon.component'; | ||
export { Bs4ScrollspyComponent } from './bs4-scrollspy/bs4-scrollspy.component'; | ||
export { Bs4ShareComponent } from './bs4-share/bs4-share.component'; | ||
export { Bs4SidebarComponent } from './bs4-sidebar/bs4-sidebar.component'; | ||
export { Bs4SlideshowComponent } from './bs4-slideshow/bs4-slideshow.component'; | ||
export { Bs4ToggleButtonComponent } from './bs4-toggle-button/bs4-toggle-button.component'; | ||
export { Bs4NavbarComponent } from './bs4-navbar/bs4-navbar.component'; | ||
export { Bs4TabsComponent } from './bs4-tabs/bs4-tabs.component'; | ||
export { Bs4DropdownComponent } from "./bs4-dropdown/bs4-dropdown.component"; | ||
export { Bs4AccordionComponent } from "./bs4-accordion/bs4-accordion.component"; | ||
export { Bs4ButtonComponent } from "./bs4-button/bs4-button.component"; | ||
export { Bs4CarouselComponent } from "./bs4-carousel/bs4-carousel.component"; | ||
export { Bs4ContentsComponent } from "./bs4-contents/bs4-contents.component"; | ||
export { Bs4IconComponent } from "./bs4-icon/bs4-icon.component"; | ||
export { Bs4ScrollspyComponent } from "./bs4-scrollspy/bs4-scrollspy.component"; | ||
export { Bs4ShareComponent } from "./bs4-share/bs4-share.component"; | ||
export { Bs4SidebarComponent } from "./bs4-sidebar/bs4-sidebar.component"; | ||
export { Bs4SlideshowComponent } from "./bs4-slideshow/bs4-slideshow.component"; | ||
export { Bs4ToggleButtonComponent } from "./bs4-toggle-button/bs4-toggle-button.component"; | ||
export { Bs4NavbarComponent } from "./bs4-navbar/bs4-navbar.component"; | ||
export { Bs4TabsComponent } from "./bs4-tabs/bs4-tabs.component"; | ||
export { Bs4FormComponent } from "./bs4-form/bs4-form.component"; | ||
export { Bs4ToastContainerComponent } from "./bs4-toast-container/bs4-toast-container.component"; | ||
export { Bs4ToastItemComponent } from "./bs4-toast-item/bs4-toast-item.component"; |
@@ -1,9 +0,4 @@ | ||
import { | ||
Component, | ||
} from '@ribajs/core'; | ||
import { | ||
camelCase, | ||
} from '@ribajs/utils/src/type'; | ||
import { Component } from "@ribajs/core"; | ||
import { camelCase } from "@ribajs/utils/src/type"; | ||
export type AttributeType = string; // 'string' | 'number' | 'boolean'; | ||
@@ -24,3 +19,2 @@ | ||
export abstract class TemplatesComponent extends Component { | ||
protected templateAttributes: TemplateAttributes = []; | ||
@@ -48,11 +42,15 @@ | ||
*/ | ||
protected transformTemplateAttribute(name: string, value: any, type?: AttributeType) { | ||
protected transformTemplateAttribute( | ||
name: string, | ||
value: any, | ||
type?: AttributeType | ||
) { | ||
switch (type) { | ||
case 'number': | ||
case "number": | ||
value = Number(value); | ||
break; | ||
case 'boolean': | ||
value = value === 'true'; | ||
case "boolean": | ||
value = value === "true"; | ||
break; | ||
case 'string': | ||
case "string": | ||
default: | ||
@@ -77,5 +75,10 @@ break; | ||
for (const attribute of this.templateAttributes) { | ||
const attrValue = this.transformTemplateAttribute(attribute.name, tpl.getAttribute(attribute.name)); | ||
const attrValue = this.transformTemplateAttribute( | ||
attribute.name, | ||
tpl.getAttribute(attribute.name) | ||
); | ||
if (attribute.required && !attrValue) { | ||
console.error(new Error(`template "${attribute.name}" attribute is required!`)); | ||
console.error( | ||
new Error(`template "${attribute.name}" attribute is required!`) | ||
); | ||
return; | ||
@@ -91,10 +94,10 @@ } | ||
const content = tpl.innerHTML; | ||
this.scope.items.push({...attributes, content}); | ||
this.scope.items.push({ ...attributes, content }); | ||
} | ||
protected addItemsByTemplate() { | ||
const templates = this.el.querySelectorAll<HTMLTemplateElement>('template'); | ||
const templates = this.el.querySelectorAll<HTMLTemplateElement>("template"); | ||
for (let index = 0; index < templates.length; index++) { | ||
const tpl = templates[index]; | ||
this.addItemByTemplate(tpl, index); | ||
@@ -106,3 +109,3 @@ } | ||
protected removeTemplates() { | ||
const templates = this.el.querySelectorAll<HTMLTemplateElement>('template'); | ||
const templates = this.el.querySelectorAll<HTMLTemplateElement>("template"); | ||
for (let index = 0; index < templates.length; index++) { | ||
@@ -118,3 +121,5 @@ const tpl = templates[index]; | ||
const child = this.el.childNodes[index]; | ||
allAreTemplates = allAreTemplates && (child.nodeName === 'TEMPLATE' || child.nodeName === '#text'); | ||
allAreTemplates = | ||
allAreTemplates && | ||
(child.nodeName === "TEMPLATE" || child.nodeName === "#text"); | ||
} | ||
@@ -121,0 +126,0 @@ return allAreTemplates; |
// EventDispatcher events | ||
export const TOGGLE_BUTTON = { | ||
nsPrefix: 'bs4-toggle-button:', | ||
nsPrefix: "bs4-toggle-button:", | ||
eventNames: { | ||
toggle: 'toggle', | ||
toggled: 'toggled', | ||
init: 'init', | ||
state: 'state', | ||
} | ||
toggle: "toggle", | ||
toggled: "toggled", | ||
init: "init", | ||
state: "state", | ||
}, | ||
}; | ||
@@ -14,12 +14,12 @@ | ||
elEventNames: { | ||
removed: 'removed', | ||
added: 'added', | ||
} | ||
} | ||
removed: "removed", | ||
added: "added", | ||
}, | ||
}; | ||
export const TOGGLE_CLASS= { | ||
export const TOGGLE_CLASS = { | ||
elEventNames: { | ||
removed: 'removed', | ||
added: 'added', | ||
} | ||
} | ||
removed: "removed", | ||
added: "added", | ||
}, | ||
}; |
@@ -1,8 +0,8 @@ | ||
export * from './services'; | ||
export * from './binders'; | ||
export * from './components'; | ||
export * from "./services"; | ||
export * from "./binders"; | ||
export * from "./components"; | ||
// export * as formatters from './formatters/bs4.formatters'; | ||
export * from './services'; | ||
export * from "./services"; | ||
// export * from './interfaces/interfaces'; | ||
export * from './constants'; | ||
export * from './bs4.module'; | ||
export * from "./constants"; | ||
export * from "./bs4.module"; |
@@ -1,2 +0,10 @@ | ||
export type CarouselClassName = 'carousel' | 'active' | 'slide' | 'carousel-item-right' | 'carousel-item-left' | 'carousel-item-next' | 'carousel-item-prev' | 'carousel-item' | 'pointer-event'; | ||
export type CarouselClassName = | ||
| "carousel" | ||
| "active" | ||
| "slide" | ||
| "carousel-item-right" | ||
| "carousel-item-left" | ||
| "carousel-item-next" | ||
| "carousel-item-prev" | ||
| "carousel-item" | ||
| "pointer-event"; |
@@ -1,1 +0,1 @@ | ||
export type CarouselDirection = 'next' | 'prev' | 'left' | 'right'; | ||
export type CarouselDirection = "next" | "prev" | "left" | "right"; |
@@ -0,59 +1,59 @@ | ||
/** | ||
* Copy from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/bootstrap/index.d.ts | ||
*/ | ||
export interface CarouselOption { | ||
/** | ||
* Copy from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/bootstrap/index.d.ts | ||
* The amount of time to delay between automatically cycling an item. If false, carousel will not automatically cycle. | ||
* | ||
* @default 5000 | ||
*/ | ||
export interface CarouselOption { | ||
/** | ||
* The amount of time to delay between automatically cycling an item. If false, carousel will not automatically cycle. | ||
* | ||
* @default 5000 | ||
*/ | ||
interval?: false | number; | ||
defaultInterval?: false | number; | ||
interval?: false | number; | ||
defaultInterval?: false | number; | ||
/** | ||
* Whether the carousel should react to keyboard events. | ||
* | ||
* @default true | ||
*/ | ||
keyboard?: boolean; | ||
/** | ||
* Whether the carousel should react to keyboard events. | ||
* | ||
* @default true | ||
*/ | ||
keyboard?: boolean; | ||
/** | ||
* Use to easily control the position of the carousel. It accepts the keywords prev or next, which alters the slide position | ||
* relative to its current position. Alternatively, use `data-slide-to` to pass a raw slide index to the carousel. | ||
* | ||
* @default false | ||
*/ | ||
slide?: "next" | "prev" | false; | ||
/** | ||
* Use to easily control the position of the carousel. It accepts the keywords prev or next, which alters the slide position | ||
* relative to its current position. Alternatively, use `data-slide-to` to pass a raw slide index to the carousel. | ||
* | ||
* @default false | ||
*/ | ||
slide?: "next" | "prev" | false; | ||
/** | ||
* If set to "hover", pauses the cycling of the carousel on `mouseenter` and resumes the cycling of the carousel on `mouseleave`. | ||
* If set to false, hovering over the carousel won't pause it. | ||
* | ||
* On touch-enabled devices, when set to "hover", cycling will pause on `touchend` (once the user finished interacting with the carousel) | ||
* for two intervals, before automatically resuming. Note that this is in addition to the above mouse behavior. | ||
* | ||
* @default "hover" | ||
*/ | ||
pause?: "hover" | false; | ||
/** | ||
* If set to "hover", pauses the cycling of the carousel on `mouseenter` and resumes the cycling of the carousel on `mouseleave`. | ||
* If set to false, hovering over the carousel won't pause it. | ||
* | ||
* On touch-enabled devices, when set to "hover", cycling will pause on `touchend` (once the user finished interacting with the carousel) | ||
* for two intervals, before automatically resuming. Note that this is in addition to the above mouse behavior. | ||
* | ||
* @default "hover" | ||
*/ | ||
pause?: "hover" | false; | ||
/** | ||
* Whether the carousel should cycle continuously or have hard stops. | ||
* | ||
* @default true | ||
*/ | ||
wrap?: boolean; | ||
/** | ||
* Whether the carousel should cycle continuously or have hard stops. | ||
* | ||
* @default true | ||
*/ | ||
wrap?: boolean; | ||
/** | ||
* Whether the carousel should support left/right swipe interactions on touchscreen devices. | ||
* | ||
* @default true | ||
*/ | ||
touch?: boolean; | ||
/** | ||
* Whether the carousel should support left/right swipe interactions on touchscreen devices. | ||
* | ||
* @default true | ||
*/ | ||
touch?: boolean; | ||
/** | ||
* Autoplays the carousel after the user manually cycles the first item. If "carousel", autoplays the carousel on load. | ||
* | ||
* @default false | ||
*/ | ||
ride?: boolean; | ||
} | ||
/** | ||
* Autoplays the carousel after the user manually cycles the first item. If "carousel", autoplays the carousel on load. | ||
* | ||
* @default false | ||
*/ | ||
ride?: boolean; | ||
} |
@@ -1,4 +0,5 @@ | ||
export * from './carousel-class-name'; | ||
export * from './carousel-direction'; | ||
export * from './carousel-option'; | ||
export * from './share-item'; | ||
export * from "./carousel-class-name"; | ||
export * from "./carousel-direction"; | ||
export * from "./carousel-option"; | ||
export * from "./share-item"; | ||
export * from "./toast"; |
@@ -1,42 +0,42 @@ | ||
export type ShareUrlType = 'page' | 'image' | 'video'; | ||
export type ShareUrlType = "page" | "image" | "video"; | ||
export interface ShareItem { | ||
/** | ||
* An id for this share button entry. The share element associated with this entry will be classed with | ||
* 'pswp__share--' + id | ||
*/ | ||
id: string; | ||
/** | ||
* The user-visible text to display for this entry. | ||
*/ | ||
label: string; | ||
/** | ||
* The full sharing endpoint URL for this social media site (e.g. Facebook's is facebook.com/sharer/sharer.php), with URL parameters. | ||
* PhotoSwipUI_Default treats the URL specially. In the url string, any of the following text is treated specially: | ||
* '{{url}}', '{{image_url}}, '{{raw_image_url}}, '{{text}}'. PhotoSwipeUI_Default will replace each of them with the following value: | ||
* | ||
* {{url}} becomes the (URIEncoded) url to the current "Page" (as returned by getPageURLForShare). | ||
* {{image_url}} becomes the (URIEncoded) url of the selected image (as returned by getURLToShare). | ||
* {{raw_image_url}} becomes the raw url of the selected image (as returned by getURLToShare). | ||
* {{text}} becomes the (URIEncoded) share text of the selected image (as returned by getTextForShare). | ||
*/ | ||
url: string; | ||
/** | ||
* Url string with placeholders to generate the url string above | ||
*/ | ||
urlTemplate: string; | ||
/** | ||
* An id for this share button entry. The share element associated with this entry will be classed with | ||
* 'pswp__share--' + id | ||
*/ | ||
id: string; | ||
mediaUrlTemplate?: string; | ||
/** | ||
* Whether this link is a direct download button or not. | ||
*/ | ||
type?: 'download' | 'popup' | 'href'; | ||
/** | ||
* The user-visible text to display for this entry. | ||
*/ | ||
label: string; | ||
availableFor: ShareUrlType[]; | ||
/** | ||
* The full sharing endpoint URL for this social media site (e.g. Facebook's is facebook.com/sharer/sharer.php), with URL parameters. | ||
* PhotoSwipUI_Default treats the URL specially. In the url string, any of the following text is treated specially: | ||
* '{{url}}', '{{image_url}}, '{{raw_image_url}}, '{{text}}'. PhotoSwipeUI_Default will replace each of them with the following value: | ||
* | ||
* {{url}} becomes the (URIEncoded) url to the current "Page" (as returned by getPageURLForShare). | ||
* {{image_url}} becomes the (URIEncoded) url of the selected image (as returned by getURLToShare). | ||
* {{raw_image_url}} becomes the raw url of the selected image (as returned by getURLToShare). | ||
* {{text}} becomes the (URIEncoded) share text of the selected image (as returned by getTextForShare). | ||
*/ | ||
url: string; | ||
available?: boolean; | ||
} | ||
/** | ||
* Url string with placeholders to generate the url string above | ||
*/ | ||
urlTemplate: string; | ||
mediaUrlTemplate?: string; | ||
/** | ||
* Whether this link is a direct download button or not. | ||
*/ | ||
type?: "download" | "popup" | "href"; | ||
availableFor: ShareUrlType[]; | ||
available?: boolean; | ||
} |
@@ -1,4 +0,4 @@ | ||
import { CarouselOption } from '../interfaces/carousel-option' | ||
import { CarouselDirection } from '../interfaces/carousel-direction' | ||
import { CarouselClassName } from '../interfaces/carousel-class-name' | ||
import { CarouselOption } from "../interfaces/carousel-option"; | ||
import { CarouselDirection } from "../interfaces/carousel-direction"; | ||
import { CarouselClassName } from "../interfaces/carousel-class-name"; | ||
@@ -12,8 +12,5 @@ /** | ||
import { | ||
TRANSITION_END, | ||
Utils, | ||
} from './utils.service' | ||
import EventHandler from './dom/event-handler' | ||
import SelectorEngine from './dom/selector-engine' | ||
import { TRANSITION_END, Utils } from "./utils.service"; | ||
import EventHandler from "./dom/event-handler"; | ||
import SelectorEngine from "./dom/selector-engine"; | ||
@@ -26,10 +23,10 @@ /** | ||
const NAME = 'carousel' | ||
const DATA_KEY = 'bs.carousel' | ||
const EVENT_KEY = `.${DATA_KEY}` | ||
const DATA_API_KEY = '.data-api' | ||
const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key | ||
const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key | ||
const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch | ||
const SWIPE_THRESHOLD = 40 | ||
const NAME = "carousel"; | ||
const DATA_KEY = "bs.carousel"; | ||
const EVENT_KEY = `.${DATA_KEY}`; | ||
const DATA_API_KEY = ".data-api"; | ||
const ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key | ||
const ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key | ||
const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch | ||
const SWIPE_THRESHOLD = 40; | ||
@@ -40,22 +37,22 @@ const Default: CarouselOption = { | ||
slide: false, | ||
pause: 'hover', | ||
pause: "hover", | ||
wrap: true, | ||
touch: true | ||
} | ||
touch: true, | ||
}; | ||
const DefaultType = { | ||
interval: '(number|boolean)', | ||
keyboard: 'boolean', | ||
slide: '(boolean|string)', | ||
pause: '(string|boolean)', | ||
wrap: 'boolean', | ||
touch: 'boolean' | ||
} | ||
interval: "(number|boolean)", | ||
keyboard: "boolean", | ||
slide: "(boolean|string)", | ||
pause: "(string|boolean)", | ||
wrap: "boolean", | ||
touch: "boolean", | ||
}; | ||
const Direction = { | ||
NEXT: 'next' as CarouselDirection, | ||
PREV: 'prev' as CarouselDirection, | ||
LEFT: 'left' as CarouselDirection, | ||
RIGHT: 'right' as CarouselDirection, | ||
} | ||
NEXT: "next" as CarouselDirection, | ||
PREV: "prev" as CarouselDirection, | ||
LEFT: "left" as CarouselDirection, | ||
RIGHT: "right" as CarouselDirection, | ||
}; | ||
@@ -75,30 +72,30 @@ const Event = { | ||
LOAD_DATA_API: `load${EVENT_KEY}${DATA_API_KEY}`, | ||
CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}` | ||
} | ||
CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`, | ||
}; | ||
const ClassName = { | ||
CAROUSEL: 'carousel' as CarouselClassName, | ||
ACTIVE: 'active' as CarouselClassName, | ||
SLIDE: 'slide' as CarouselClassName, | ||
RIGHT: 'carousel-item-right' as CarouselClassName, | ||
LEFT: 'carousel-item-left' as CarouselClassName, | ||
NEXT: 'carousel-item-next' as CarouselClassName, | ||
PREV: 'carousel-item-prev' as CarouselClassName, | ||
ITEM: 'carousel-item' as CarouselClassName, | ||
POINTER_EVENT: 'pointer-event' as CarouselClassName, | ||
} | ||
CAROUSEL: "carousel" as CarouselClassName, | ||
ACTIVE: "active" as CarouselClassName, | ||
SLIDE: "slide" as CarouselClassName, | ||
RIGHT: "carousel-item-right" as CarouselClassName, | ||
LEFT: "carousel-item-left" as CarouselClassName, | ||
NEXT: "carousel-item-next" as CarouselClassName, | ||
PREV: "carousel-item-prev" as CarouselClassName, | ||
ITEM: "carousel-item" as CarouselClassName, | ||
POINTER_EVENT: "pointer-event" as CarouselClassName, | ||
}; | ||
const Selector = { | ||
ACTIVE: '.active', | ||
ACTIVE_ITEM: '.active.carousel-item', | ||
ITEM: '.carousel-item', | ||
ITEM_IMG: '.carousel-item img', | ||
NEXT_PREV: '.carousel-item-next, .carousel-item-prev', | ||
INDICATORS: '.carousel-indicators' | ||
} | ||
ACTIVE: ".active", | ||
ACTIVE_ITEM: ".active.carousel-item", | ||
ITEM: ".carousel-item", | ||
ITEM_IMG: ".carousel-item img", | ||
NEXT_PREV: ".carousel-item-next, .carousel-item-prev", | ||
INDICATORS: ".carousel-indicators", | ||
}; | ||
const PointerType = { | ||
TOUCH: 'touch', | ||
PEN: 'pen' | ||
} | ||
TOUCH: "touch", | ||
PEN: "pen", | ||
}; | ||
@@ -111,3 +108,2 @@ /** | ||
class CarouselService { | ||
private _items: HTMLElement[] | null = null; | ||
@@ -120,3 +116,3 @@ private _interval: number | null = null; | ||
private _config: CarouselOption; | ||
private _element: HTMLElement | ||
private _element: HTMLElement; | ||
private _indicatorsElement: HTMLElement | null; | ||
@@ -126,25 +122,31 @@ private _touchSupported: boolean; | ||
public touchTimeout: number | null = null | ||
public touchStartX = 0 | ||
public touchDeltaX = 0 | ||
public touchTimeout: number | null = null; | ||
public touchStartX = 0; | ||
public touchDeltaX = 0; | ||
constructor(element: HTMLElement, config: CarouselOption) { | ||
this._items = null | ||
this._interval = null | ||
this._activeElement = null | ||
this._isPaused = false | ||
this._isSliding = false | ||
this.touchTimeout = null | ||
this.touchStartX = 0 | ||
this.touchDeltaX = 0 | ||
this._items = null; | ||
this._interval = null; | ||
this._activeElement = null; | ||
this._isPaused = false; | ||
this._isSliding = false; | ||
this.touchTimeout = null; | ||
this.touchStartX = 0; | ||
this.touchDeltaX = 0; | ||
this._config = this._getConfig(config) | ||
this._element = element | ||
this._indicatorsElement = SelectorEngine.findOne(Selector.INDICATORS, this._element) as HTMLElement || null; | ||
this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0 | ||
this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent) | ||
this._config = this._getConfig(config); | ||
this._element = element; | ||
this._indicatorsElement = | ||
(SelectorEngine.findOne( | ||
Selector.INDICATORS, | ||
this._element | ||
) as HTMLElement) || null; | ||
this._touchSupported = | ||
"ontouchstart" in document.documentElement || | ||
navigator.maxTouchPoints > 0; | ||
this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent); | ||
console.debug('CarouselService', this); | ||
console.debug("CarouselService", this); | ||
this._addEventListeners() | ||
this._addEventListeners(); | ||
} | ||
@@ -155,3 +157,3 @@ | ||
static get Default() { | ||
return Default | ||
return Default; | ||
} | ||
@@ -163,3 +165,3 @@ | ||
if (!this._isSliding) { | ||
this._slide(Direction.NEXT) | ||
this._slide(Direction.NEXT); | ||
} | ||
@@ -172,3 +174,3 @@ } | ||
if (!document.hidden && Utils.isVisible(this._element)) { | ||
this.next() | ||
this.next(); | ||
} | ||
@@ -179,28 +181,28 @@ } | ||
if (!this._isSliding) { | ||
this._slide(Direction.PREV) | ||
this._slide(Direction.PREV); | ||
} | ||
} | ||
pause(event?: TouchEvent & MouseEvent & PointerEvent | boolean) { | ||
pause(event?: (TouchEvent & MouseEvent & PointerEvent) | boolean) { | ||
if (!event) { | ||
this._isPaused = true | ||
this._isPaused = true; | ||
} | ||
if (SelectorEngine.findOne(Selector.NEXT_PREV, this._element)) { | ||
Utils.triggerTransitionEnd(this._element) | ||
this.cycle(true) | ||
Utils.triggerTransitionEnd(this._element); | ||
this.cycle(true); | ||
} | ||
clearInterval(this._interval || undefined) | ||
this._interval = null | ||
clearInterval(this._interval || undefined); | ||
this._interval = null; | ||
} | ||
cycle(event?: Event | TouchEvent & MouseEvent & PointerEvent | boolean) { | ||
cycle(event?: Event | (TouchEvent & MouseEvent & PointerEvent) | boolean) { | ||
if (!event) { | ||
this._isPaused = false | ||
this._isPaused = false; | ||
} | ||
if (this._interval) { | ||
clearInterval(this._interval) | ||
this._interval = null | ||
clearInterval(this._interval); | ||
this._interval = null; | ||
} | ||
@@ -210,5 +212,7 @@ | ||
this._interval = setInterval( | ||
(document.visibilityState ? this.nextWhenVisible : this.next).bind(this), | ||
(document.visibilityState ? this.nextWhenVisible : this.next).bind( | ||
this | ||
), | ||
this._config.interval | ||
) | ||
); | ||
} | ||
@@ -219,30 +223,33 @@ } | ||
if (this._items === null) { | ||
throw new Error('No items found!'); | ||
throw new Error("No items found!"); | ||
} | ||
this._activeElement = SelectorEngine.findOne(Selector.ACTIVE_ITEM, this._element) as HTMLElement || null; | ||
this._activeElement = | ||
(SelectorEngine.findOne( | ||
Selector.ACTIVE_ITEM, | ||
this._element | ||
) as HTMLElement) || null; | ||
if (this._activeElement === null) { | ||
throw new Error('Active element not found!'); | ||
throw new Error("Active element not found!"); | ||
} | ||
const activeIndex = this._getItemIndex(this._activeElement) | ||
const activeIndex = this._getItemIndex(this._activeElement); | ||
if (index > this._items.length - 1 || index < 0) { | ||
return | ||
return; | ||
} | ||
if (this._isSliding) { | ||
EventHandler.one(this._element, Event.SLID, () => this.to(index)) | ||
return | ||
EventHandler.one(this._element, Event.SLID, () => this.to(index)); | ||
return; | ||
} | ||
if (activeIndex === index) { | ||
this.pause() | ||
this.cycle() | ||
return | ||
this.pause(); | ||
this.cycle(); | ||
return; | ||
} | ||
const direction: CarouselDirection = index > activeIndex ? | ||
Direction.NEXT : | ||
Direction.PREV; | ||
const direction: CarouselDirection = | ||
index > activeIndex ? Direction.NEXT : Direction.PREV; | ||
this._slide(direction, this._items[index]) | ||
this._slide(direction, this._items[index]); | ||
} | ||
@@ -252,3 +259,2 @@ | ||
// EventHandler.off(this._element, EVENT_KEY) | ||
// this._items = null | ||
@@ -269,22 +275,22 @@ // this._config = null | ||
...Default, | ||
...config | ||
} as CarouselOption | ||
Utils.typeCheckConfig(NAME, config, DefaultType) | ||
return config | ||
...config, | ||
} as CarouselOption; | ||
Utils.typeCheckConfig(NAME, config, DefaultType); | ||
return config; | ||
} | ||
_handleSwipe() { | ||
const absDeltax = Math.abs(this.touchDeltaX) | ||
const absDeltax = Math.abs(this.touchDeltaX); | ||
if (absDeltax <= SWIPE_THRESHOLD) { | ||
return | ||
return; | ||
} | ||
const direction = absDeltax / this.touchDeltaX | ||
const direction = absDeltax / this.touchDeltaX; | ||
this.touchDeltaX = 0 | ||
this.touchDeltaX = 0; | ||
// swipe left | ||
if (direction > 0) { | ||
this.prev() | ||
this.prev(); | ||
} | ||
@@ -294,3 +300,3 @@ | ||
if (direction < 0) { | ||
this.next() | ||
this.next(); | ||
} | ||
@@ -301,15 +307,22 @@ } | ||
if (this._config.keyboard) { | ||
EventHandler | ||
.on<KeyboardEvent>(this._element, Event.KEYDOWN, (event) => this._keydown(event)) | ||
EventHandler.on<KeyboardEvent>(this._element, Event.KEYDOWN, (event) => | ||
this._keydown(event) | ||
); | ||
} | ||
if (this._config.pause === 'hover') { | ||
EventHandler | ||
.on(this._element, Event.MOUSEENTER, (event: TouchEvent & MouseEvent & PointerEvent) => this.pause(event)) | ||
EventHandler | ||
.on(this._element, Event.MOUSELEAVE, (event: TouchEvent & MouseEvent & PointerEvent) => this.cycle(event)) | ||
if (this._config.pause === "hover") { | ||
EventHandler.on( | ||
this._element, | ||
Event.MOUSEENTER, | ||
(event: TouchEvent & MouseEvent & PointerEvent) => this.pause(event) | ||
); | ||
EventHandler.on( | ||
this._element, | ||
Event.MOUSELEAVE, | ||
(event: TouchEvent & MouseEvent & PointerEvent) => this.cycle(event) | ||
); | ||
} | ||
if (this._config.touch && this._touchSupported) { | ||
this._addTouchEventListeners() | ||
this._addTouchEventListeners(); | ||
} | ||
@@ -320,8 +333,11 @@ } | ||
const start = (event: TouchEvent & MouseEvent & PointerEvent) => { | ||
if (this._pointerEvent && PointerType[event.pointerType.toUpperCase() as 'TOUCH' | 'PEN' ]) { | ||
this.touchStartX = event.clientX | ||
if ( | ||
this._pointerEvent && | ||
PointerType[event.pointerType.toUpperCase() as "TOUCH" | "PEN"] | ||
) { | ||
this.touchStartX = event.clientX; | ||
} else if (!this._pointerEvent) { | ||
this.touchStartX = event.touches[0].clientX | ||
this.touchStartX = event.touches[0].clientX; | ||
} | ||
} | ||
}; | ||
@@ -331,15 +347,18 @@ const move = (event: TouchEvent & MouseEvent & PointerEvent) => { | ||
if (event.touches && event.touches.length > 1) { | ||
this.touchDeltaX = 0 | ||
this.touchDeltaX = 0; | ||
} else { | ||
this.touchDeltaX = event.touches[0].clientX - this.touchStartX | ||
this.touchDeltaX = event.touches[0].clientX - this.touchStartX; | ||
} | ||
} | ||
}; | ||
const end = (event: TouchEvent & MouseEvent & PointerEvent) => { | ||
if (this._pointerEvent && PointerType[event.pointerType.toUpperCase() as 'TOUCH' | 'PEN']) { | ||
this.touchDeltaX = event.clientX - this.touchStartX | ||
if ( | ||
this._pointerEvent && | ||
PointerType[event.pointerType.toUpperCase() as "TOUCH" | "PEN"] | ||
) { | ||
this.touchDeltaX = event.clientX - this.touchStartX; | ||
} | ||
this._handleSwipe() | ||
if (this._config.pause === 'hover') { | ||
this._handleSwipe(); | ||
if (this._config.pause === "hover") { | ||
// If it's a touch-enabled device, mouseenter/leave are fired as | ||
@@ -353,24 +372,54 @@ // part of the mouse compatibility events on first tap - the carousel | ||
this.pause() | ||
this.pause(); | ||
if (this.touchTimeout) { | ||
clearTimeout(this.touchTimeout) | ||
clearTimeout(this.touchTimeout); | ||
} | ||
this.touchTimeout = setTimeout((event: TouchEvent & MouseEvent & PointerEvent) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + (this._config.interval || 0)) | ||
this.touchTimeout = setTimeout( | ||
(event: TouchEvent & MouseEvent & PointerEvent) => this.cycle(event), | ||
TOUCHEVENT_COMPAT_WAIT + (this._config.interval || 0) | ||
); | ||
} | ||
} | ||
}; | ||
Utils.makeArray(SelectorEngine.find(Selector.ITEM_IMG, this._element)).forEach(itemImg => { | ||
EventHandler.on(itemImg, Event.DRAG_START, (event: TouchEvent & MouseEvent & PointerEvent) => event.preventDefault()) | ||
}) | ||
Utils.makeArray( | ||
SelectorEngine.find(Selector.ITEM_IMG, this._element) | ||
).forEach((itemImg) => { | ||
EventHandler.on( | ||
itemImg, | ||
Event.DRAG_START, | ||
(event: TouchEvent & MouseEvent & PointerEvent) => | ||
event.preventDefault() | ||
); | ||
}); | ||
if (this._pointerEvent) { | ||
EventHandler.on(this._element, Event.POINTERDOWN, (event: TouchEvent & MouseEvent & PointerEvent) => start(event)) | ||
EventHandler.on(this._element, Event.POINTERUP, (event: TouchEvent & MouseEvent & PointerEvent) => end(event)) | ||
EventHandler.on( | ||
this._element, | ||
Event.POINTERDOWN, | ||
(event: TouchEvent & MouseEvent & PointerEvent) => start(event) | ||
); | ||
EventHandler.on( | ||
this._element, | ||
Event.POINTERUP, | ||
(event: TouchEvent & MouseEvent & PointerEvent) => end(event) | ||
); | ||
this._element.classList.add(ClassName.POINTER_EVENT) | ||
this._element.classList.add(ClassName.POINTER_EVENT); | ||
} else { | ||
EventHandler.on(this._element, Event.TOUCHSTART, (event: TouchEvent & MouseEvent & PointerEvent) => start(event)) | ||
EventHandler.on(this._element, Event.TOUCHMOVE, (event: TouchEvent & MouseEvent & PointerEvent) => move(event)) | ||
EventHandler.on(this._element, Event.TOUCHEND, (event: TouchEvent & MouseEvent & PointerEvent) => end(event)) | ||
EventHandler.on( | ||
this._element, | ||
Event.TOUCHSTART, | ||
(event: TouchEvent & MouseEvent & PointerEvent) => start(event) | ||
); | ||
EventHandler.on( | ||
this._element, | ||
Event.TOUCHMOVE, | ||
(event: TouchEvent & MouseEvent & PointerEvent) => move(event) | ||
); | ||
EventHandler.on( | ||
this._element, | ||
Event.TOUCHEND, | ||
(event: TouchEvent & MouseEvent & PointerEvent) => end(event) | ||
); | ||
} | ||
@@ -380,4 +429,7 @@ } | ||
_keydown(event: KeyboardEvent) { | ||
if ((event.target as any)?.tagName && /input|textarea/i.test((event.target as any).tagName)) { | ||
return | ||
if ( | ||
(event.target as any)?.tagName && | ||
/input|textarea/i.test((event.target as any).tagName) | ||
) { | ||
return; | ||
} | ||
@@ -387,9 +439,9 @@ | ||
case ARROW_LEFT_KEYCODE: | ||
event.preventDefault() | ||
this.prev() | ||
break | ||
event.preventDefault(); | ||
this.prev(); | ||
break; | ||
case ARROW_RIGHT_KEYCODE: | ||
event.preventDefault() | ||
this.next() | ||
break | ||
event.preventDefault(); | ||
this.next(); | ||
break; | ||
default: | ||
@@ -403,35 +455,53 @@ } | ||
} | ||
this._items = element && element.parentNode ? | ||
Utils.makeArray(SelectorEngine.find(Selector.ITEM, element.parentNode as HTMLElement)) : | ||
[] | ||
this._items = | ||
element && element.parentNode | ||
? Utils.makeArray( | ||
SelectorEngine.find( | ||
Selector.ITEM, | ||
element.parentNode as HTMLElement | ||
) | ||
) | ||
: []; | ||
return this._items.indexOf(element) | ||
return this._items.indexOf(element); | ||
} | ||
_getItemByDirection(direction: CarouselDirection, activeElement: HTMLElement) { | ||
_getItemByDirection( | ||
direction: CarouselDirection, | ||
activeElement: HTMLElement | ||
) { | ||
if (this._items === null) { | ||
throw new Error('No items found!'); | ||
throw new Error("No items found!"); | ||
} | ||
const isNextDirection = direction === Direction.NEXT | ||
const isPrevDirection = direction === Direction.PREV | ||
const activeIndex = this._getItemIndex(activeElement) | ||
const lastItemIndex = this._items.length - 1 | ||
const isGoingToWrap = (isPrevDirection && activeIndex === 0) || | ||
(isNextDirection && activeIndex === lastItemIndex) | ||
const isNextDirection = direction === Direction.NEXT; | ||
const isPrevDirection = direction === Direction.PREV; | ||
const activeIndex = this._getItemIndex(activeElement); | ||
const lastItemIndex = this._items.length - 1; | ||
const isGoingToWrap = | ||
(isPrevDirection && activeIndex === 0) || | ||
(isNextDirection && activeIndex === lastItemIndex); | ||
if (isGoingToWrap && !this._config.wrap) { | ||
return activeElement | ||
return activeElement; | ||
} | ||
const delta = direction === Direction.PREV ? -1 : 1 | ||
const itemIndex = (activeIndex + delta) % this._items.length | ||
const delta = direction === Direction.PREV ? -1 : 1; | ||
const itemIndex = (activeIndex + delta) % this._items.length; | ||
return itemIndex === -1 ? | ||
this._items[this._items.length - 1] : | ||
this._items[itemIndex] | ||
return itemIndex === -1 | ||
? this._items[this._items.length - 1] | ||
: this._items[itemIndex]; | ||
} | ||
_triggerSlideEvent(relatedTarget: HTMLElement, eventDirectionName: CarouselDirection) { | ||
const targetIndex = this._getItemIndex(relatedTarget) | ||
const fromIndex = this._getItemIndex(SelectorEngine.findOne(Selector.ACTIVE_ITEM, this._element) as HTMLElement || null) | ||
_triggerSlideEvent( | ||
relatedTarget: HTMLElement, | ||
eventDirectionName: CarouselDirection | ||
) { | ||
const targetIndex = this._getItemIndex(relatedTarget); | ||
const fromIndex = this._getItemIndex( | ||
(SelectorEngine.findOne( | ||
Selector.ACTIVE_ITEM, | ||
this._element | ||
) as HTMLElement) || null | ||
); | ||
@@ -442,4 +512,4 @@ return EventHandler.trigger(this._element, Event.SLIDE, { | ||
from: fromIndex, | ||
to: targetIndex | ||
}) | ||
to: targetIndex, | ||
}); | ||
} | ||
@@ -449,5 +519,8 @@ | ||
if (this._indicatorsElement) { | ||
const indicators = SelectorEngine.find(Selector.ACTIVE, this._indicatorsElement) | ||
const indicators = SelectorEngine.find( | ||
Selector.ACTIVE, | ||
this._indicatorsElement | ||
); | ||
for (let i = 0; i < indicators.length; i++) { | ||
indicators[i].classList.remove(ClassName.ACTIVE) | ||
indicators[i].classList.remove(ClassName.ACTIVE); | ||
} | ||
@@ -457,6 +530,6 @@ | ||
this._getItemIndex(element) | ||
] | ||
]; | ||
if (nextIndicator) { | ||
nextIndicator.classList.add(ClassName.ACTIVE) | ||
nextIndicator.classList.add(ClassName.ACTIVE); | ||
} | ||
@@ -467,13 +540,17 @@ } | ||
_slide(direction: CarouselDirection, element?: HTMLElement) { | ||
const activeElement = SelectorEngine.findOne(Selector.ACTIVE_ITEM, this._element) as HTMLElement | undefined | ||
const activeElementIndex = this._getItemIndex(activeElement) | ||
const nextElement = element || (activeElement && | ||
this._getItemByDirection(direction, activeElement)) | ||
const activeElement = SelectorEngine.findOne( | ||
Selector.ACTIVE_ITEM, | ||
this._element | ||
) as HTMLElement | undefined; | ||
const activeElementIndex = this._getItemIndex(activeElement); | ||
const nextElement = | ||
element || | ||
(activeElement && this._getItemByDirection(direction, activeElement)); | ||
if (!nextElement) { | ||
throw new Error('Next element not found!'); | ||
throw new Error("Next element not found!"); | ||
} | ||
const nextElementIndex = this._getItemIndex(nextElement) | ||
const isCycling = Boolean(this._interval) | ||
const nextElementIndex = this._getItemIndex(nextElement); | ||
const isCycling = Boolean(this._interval); | ||
@@ -485,19 +562,19 @@ let directionalClassName: CarouselClassName; | ||
if (direction === Direction.NEXT) { | ||
directionalClassName = ClassName.LEFT | ||
orderClassName = ClassName.NEXT | ||
eventDirectionName = Direction.LEFT | ||
directionalClassName = ClassName.LEFT; | ||
orderClassName = ClassName.NEXT; | ||
eventDirectionName = Direction.LEFT; | ||
} else { | ||
directionalClassName = ClassName.RIGHT | ||
orderClassName = ClassName.PREV | ||
eventDirectionName = Direction.RIGHT | ||
directionalClassName = ClassName.RIGHT; | ||
orderClassName = ClassName.PREV; | ||
eventDirectionName = Direction.RIGHT; | ||
} | ||
if (nextElement && nextElement.classList.contains(ClassName.ACTIVE)) { | ||
this._isSliding = false | ||
return | ||
this._isSliding = false; | ||
return; | ||
} | ||
const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName) | ||
const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName); | ||
if (slideEvent.defaultPrevented) { | ||
return | ||
return; | ||
} | ||
@@ -507,59 +584,65 @@ | ||
// Some weirdness is happening, so we bail | ||
return | ||
return; | ||
} | ||
this._isSliding = true | ||
this._isSliding = true; | ||
if (isCycling) { | ||
this.pause() | ||
this.pause(); | ||
} | ||
this._setActiveIndicatorElement(nextElement) | ||
this._setActiveIndicatorElement(nextElement); | ||
if (this._element.classList.contains(ClassName.SLIDE)) { | ||
nextElement.classList.add(orderClassName) | ||
nextElement.classList.add(orderClassName); | ||
Utils.reflow(nextElement) | ||
Utils.reflow(nextElement); | ||
activeElement.classList.add(directionalClassName) | ||
nextElement.classList.add(directionalClassName) | ||
activeElement.classList.add(directionalClassName); | ||
nextElement.classList.add(directionalClassName); | ||
const nextElementInterval = parseInt(nextElement.getAttribute('data-interval') || '0', 10) | ||
const nextElementInterval = parseInt( | ||
nextElement.getAttribute("data-interval") || "0", | ||
10 | ||
); | ||
if (nextElementInterval) { | ||
this._config.defaultInterval = this._config.defaultInterval || this._config.interval | ||
this._config.interval = nextElementInterval | ||
this._config.defaultInterval = | ||
this._config.defaultInterval || this._config.interval; | ||
this._config.interval = nextElementInterval; | ||
} else { | ||
this._config.interval = this._config.defaultInterval || this._config.interval | ||
this._config.interval = | ||
this._config.defaultInterval || this._config.interval; | ||
} | ||
const transitionDuration = Utils.getTransitionDurationFromElement(activeElement) | ||
const transitionDuration = Utils.getTransitionDurationFromElement( | ||
activeElement | ||
); | ||
EventHandler | ||
.one(activeElement, TRANSITION_END, () => { | ||
nextElement.classList.remove(directionalClassName) | ||
nextElement.classList.remove(orderClassName) | ||
nextElement.classList.add(ClassName.ACTIVE) | ||
EventHandler.one(activeElement, TRANSITION_END, () => { | ||
nextElement.classList.remove(directionalClassName); | ||
nextElement.classList.remove(orderClassName); | ||
nextElement.classList.add(ClassName.ACTIVE); | ||
activeElement.classList.remove(ClassName.ACTIVE) | ||
activeElement.classList.remove(orderClassName) | ||
activeElement.classList.remove(directionalClassName) | ||
activeElement.classList.remove(ClassName.ACTIVE); | ||
activeElement.classList.remove(orderClassName); | ||
activeElement.classList.remove(directionalClassName); | ||
this._isSliding = false | ||
this._isSliding = false; | ||
setTimeout(() => { | ||
EventHandler.trigger(this._element, Event.SLID, { | ||
relatedTarget: nextElement, | ||
direction: eventDirectionName, | ||
from: activeElementIndex, | ||
to: nextElementIndex | ||
}) | ||
}, 0) | ||
}) | ||
setTimeout(() => { | ||
EventHandler.trigger(this._element, Event.SLID, { | ||
relatedTarget: nextElement, | ||
direction: eventDirectionName, | ||
from: activeElementIndex, | ||
to: nextElementIndex, | ||
}); | ||
}, 0); | ||
}); | ||
Utils.emulateTransitionEnd(activeElement, transitionDuration) | ||
Utils.emulateTransitionEnd(activeElement, transitionDuration); | ||
} else { | ||
activeElement.classList.remove(ClassName.ACTIVE) | ||
nextElement.classList.add(ClassName.ACTIVE) | ||
activeElement.classList.remove(ClassName.ACTIVE); | ||
nextElement.classList.add(ClassName.ACTIVE); | ||
this._isSliding = false | ||
this._isSliding = false; | ||
EventHandler.trigger(this._element, Event.SLID, { | ||
@@ -569,8 +652,8 @@ relatedTarget: nextElement, | ||
from: activeElementIndex, | ||
to: nextElementIndex | ||
}) | ||
to: nextElementIndex, | ||
}); | ||
} | ||
if (isCycling) { | ||
this.cycle() | ||
this.cycle(); | ||
} | ||
@@ -580,2 +663,2 @@ } | ||
export default CarouselService | ||
export default CarouselService; |
@@ -8,9 +8,6 @@ /** | ||
import { | ||
TRANSITION_END, | ||
Utils, | ||
} from './utils.service' | ||
import EventHandler from './dom/event-handler' | ||
import SelectorEngine from './dom/selector-engine' | ||
import Data from './dom/data' | ||
import { TRANSITION_END, Utils } from "./utils.service"; | ||
import EventHandler from "./dom/event-handler"; | ||
import SelectorEngine from "./dom/selector-engine"; | ||
import Data from "./dom/data"; | ||
@@ -28,31 +25,31 @@ export interface Config { | ||
export const NAME = 'collapse' | ||
export const VERSION = '4.3.1' | ||
export const DATA_KEY = 'bs.collapse' | ||
export const EVENT_KEY = `.${DATA_KEY}` | ||
export const NAME = "collapse"; | ||
export const VERSION = "4.3.1"; | ||
export const DATA_KEY = "bs.collapse"; | ||
export const EVENT_KEY = `.${DATA_KEY}`; | ||
export const Default = { | ||
toggle: true, | ||
parent: '' | ||
} | ||
parent: "", | ||
}; | ||
export const DefaultType = { | ||
toggle: 'boolean', | ||
parent: '(string|element)' | ||
} | ||
toggle: "boolean", | ||
parent: "(string|element)", | ||
}; | ||
export const EVENT_SHOW = `show${EVENT_KEY}` | ||
export const EVENT_SHOWN = `shown${EVENT_KEY}` | ||
export const EVENT_HIDE = `hide${EVENT_KEY}` | ||
export const EVENT_HIDDEN = `hidden${EVENT_KEY}` | ||
export const EVENT_SHOW = `show${EVENT_KEY}`; | ||
export const EVENT_SHOWN = `shown${EVENT_KEY}`; | ||
export const EVENT_HIDE = `hide${EVENT_KEY}`; | ||
export const EVENT_HIDDEN = `hidden${EVENT_KEY}`; | ||
export const CLASS_NAME_SHOW = 'show' | ||
export const CLASS_NAME_COLLAPSE = 'collapse' | ||
export const CLASS_NAME_COLLAPSING = 'collapsing' | ||
export const CLASS_NAME_COLLAPSED = 'collapsed' | ||
export const CLASS_NAME_SHOW = "show"; | ||
export const CLASS_NAME_COLLAPSE = "collapse"; | ||
export const CLASS_NAME_COLLAPSING = "collapsing"; | ||
export const CLASS_NAME_COLLAPSED = "collapsed"; | ||
export const WIDTH = 'width' | ||
export const HEIGHT = 'height' | ||
export const WIDTH = "width"; | ||
export const HEIGHT = "height"; | ||
export const SELECTOR_ACTIVES = '.show, .collapsing' | ||
export const SELECTOR_ACTIVES = ".show, .collapsing"; | ||
// export const SELECTOR_DATA_TOGGLE = '[data-toggle="collapse"]' | ||
@@ -74,6 +71,10 @@ | ||
constructor(element: HTMLElement, triggerList: NodeListOf<HTMLElement> | HTMLElement[], config: Partial<Config> = {}) { | ||
this._isTransitioning = false | ||
this._element = element | ||
this._config = this._getConfig(config) | ||
constructor( | ||
element: HTMLElement, | ||
triggerList: NodeListOf<HTMLElement> | HTMLElement[], | ||
config: Partial<Config> = {} | ||
) { | ||
this._isTransitioning = false; | ||
this._element = element; | ||
this._config = this._getConfig(config); | ||
this._triggerArray = Array.from(triggerList); | ||
@@ -99,6 +100,6 @@ // this._triggerArray = Array.from(SelectorEngine.find( | ||
this._parent = this._config.parent ? this._getParent() : null | ||
this._parent = this._config.parent ? this._getParent() : null; | ||
if (!this._config.parent) { | ||
this._addAriaAndCollapsedClass(this._element, this._triggerArray) | ||
this._addAriaAndCollapsedClass(this._element, this._triggerArray); | ||
// this._addAriaAndCollapsedClass(this._element, []) | ||
@@ -108,6 +109,6 @@ } | ||
if (this._config.toggle) { | ||
this.toggle() | ||
this.toggle(); | ||
} | ||
Data.setData(element, DATA_KEY, this) | ||
Data.setData(element, DATA_KEY, this); | ||
} | ||
@@ -118,7 +119,7 @@ | ||
static get VERSION() { | ||
return VERSION | ||
return VERSION; | ||
} | ||
static get Default() { | ||
return Default | ||
return Default; | ||
} | ||
@@ -138,5 +139,5 @@ | ||
if (this.isExpanded()) { | ||
this.hide() | ||
this.hide(); | ||
} else { | ||
this.show() | ||
this.show(); | ||
} | ||
@@ -146,11 +147,12 @@ } | ||
show() { | ||
if (!this._element) { | ||
console.warn('this._element not set!'); | ||
console.warn("this._element not set!"); | ||
return; | ||
} | ||
if (this._isTransitioning || | ||
this._element.classList.contains(CLASS_NAME_SHOW)) { | ||
return | ||
if ( | ||
this._isTransitioning || | ||
this._element.classList.contains(CLASS_NAME_SHOW) | ||
) { | ||
return; | ||
} | ||
@@ -162,127 +164,138 @@ | ||
if (this._parent) { | ||
actives = Array.from(SelectorEngine.find(SELECTOR_ACTIVES, this._parent)) | ||
.filter(elem => { | ||
if (typeof this._config.parent === 'string') { | ||
return elem.getAttribute('data-parent') === this._config.parent | ||
} | ||
actives = Array.from( | ||
SelectorEngine.find(SELECTOR_ACTIVES, this._parent) | ||
).filter((elem) => { | ||
if (typeof this._config.parent === "string") { | ||
return elem.getAttribute("data-parent") === this._config.parent; | ||
} | ||
return elem.classList.contains(CLASS_NAME_COLLAPSE) | ||
}) as HTMLElement[]; | ||
return elem.classList.contains(CLASS_NAME_COLLAPSE); | ||
}) as HTMLElement[]; | ||
if (actives.length === 0) { | ||
actives = null | ||
actives = null; | ||
} | ||
} | ||
const container = this._selector ? SelectorEngine.findOne(this._selector) : null; | ||
const container = this._selector | ||
? SelectorEngine.findOne(this._selector) | ||
: null; | ||
if (actives) { | ||
const tempActiveData = actives.filter(elem => container !== elem) | ||
activesData = tempActiveData[0] ? Data.getData(tempActiveData[0], DATA_KEY) : null | ||
const tempActiveData = actives.filter((elem) => container !== elem); | ||
activesData = tempActiveData[0] | ||
? Data.getData(tempActiveData[0], DATA_KEY) | ||
: null; | ||
if (activesData && activesData._isTransitioning) { | ||
return | ||
return; | ||
} | ||
} | ||
const startEvent = EventHandler.trigger(this._element, EVENT_SHOW) | ||
const startEvent = EventHandler.trigger(this._element, EVENT_SHOW); | ||
if (startEvent.defaultPrevented) { | ||
return | ||
return; | ||
} | ||
if (actives) { | ||
actives.forEach(elemActive => { | ||
actives.forEach((elemActive) => { | ||
if (container !== elemActive) { | ||
CollapseService.collapseInterface(elemActive, 'hide') | ||
CollapseService.collapseInterface(elemActive, "hide"); | ||
} | ||
if (!activesData) { | ||
Data.setData(elemActive, DATA_KEY, null) | ||
Data.setData(elemActive, DATA_KEY, null); | ||
} | ||
}) | ||
}); | ||
} | ||
const dimension = this._getDimension() | ||
const dimension = this._getDimension(); | ||
this._element.classList.remove(CLASS_NAME_COLLAPSE) | ||
this._element.classList.add(CLASS_NAME_COLLAPSING) | ||
this._element.classList.remove(CLASS_NAME_COLLAPSE); | ||
this._element.classList.add(CLASS_NAME_COLLAPSING); | ||
this._element.style[dimension] = '0' | ||
this._element.style[dimension] = "0"; | ||
if (this._triggerArray?.length) { | ||
this._triggerArray.forEach(element => { | ||
element.classList.remove(CLASS_NAME_COLLAPSED) | ||
element.setAttribute('aria-expanded', 'true') | ||
}) | ||
this._triggerArray.forEach((element) => { | ||
element.classList.remove(CLASS_NAME_COLLAPSED); | ||
element.setAttribute("aria-expanded", "true"); | ||
}); | ||
} | ||
this.setTransitioning(true) | ||
this.setTransitioning(true); | ||
const complete = () => { | ||
if (!this._element) { | ||
console.warn('this._element not set!'); | ||
console.warn("this._element not set!"); | ||
return; | ||
} | ||
this._element.classList.remove(CLASS_NAME_COLLAPSING) | ||
this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW) | ||
this._element.classList.remove(CLASS_NAME_COLLAPSING); | ||
this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW); | ||
this._element.style[dimension] = '' | ||
this._element.style[dimension] = ""; | ||
this.setTransitioning(false) | ||
this.setTransitioning(false); | ||
EventHandler.trigger(this._element, EVENT_SHOWN) | ||
} | ||
EventHandler.trigger(this._element, EVENT_SHOWN); | ||
}; | ||
const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1) | ||
const scrollSize = `scroll${capitalizedDimension}` as 'scrollWidth' | 'scrollHeight'; | ||
const transitionDuration = Utils.getTransitionDurationFromElement(this._element) | ||
const capitalizedDimension = | ||
dimension[0].toUpperCase() + dimension.slice(1); | ||
const scrollSize = `scroll${capitalizedDimension}` as | ||
| "scrollWidth" | ||
| "scrollHeight"; | ||
const transitionDuration = Utils.getTransitionDurationFromElement( | ||
this._element | ||
); | ||
EventHandler.one(this._element, TRANSITION_END, complete) | ||
EventHandler.one(this._element, TRANSITION_END, complete); | ||
Utils.emulateTransitionEnd(this._element, transitionDuration) | ||
this._element.style[dimension] = `${this._element[scrollSize]}px` | ||
Utils.emulateTransitionEnd(this._element, transitionDuration); | ||
this._element.style[dimension] = `${this._element[scrollSize]}px`; | ||
if (!this._config.parent && this._triggerArray) { | ||
this._addAriaAndCollapsedClass(this._element, this._triggerArray, true) | ||
this._addAriaAndCollapsedClass(this._element, this._triggerArray, true); | ||
// this._addAriaAndCollapsedClass(this._element, []) | ||
} | ||
} | ||
hide() { | ||
if (!this._element) { | ||
console.warn('this._element not set!'); | ||
console.warn("this._element not set!"); | ||
return; | ||
} | ||
if (this._isTransitioning || | ||
!this._element.classList.contains(CLASS_NAME_SHOW)) { | ||
return | ||
if ( | ||
this._isTransitioning || | ||
!this._element.classList.contains(CLASS_NAME_SHOW) | ||
) { | ||
return; | ||
} | ||
const startEvent = EventHandler.trigger(this._element, EVENT_HIDE) | ||
const startEvent = EventHandler.trigger(this._element, EVENT_HIDE); | ||
if (startEvent.defaultPrevented) { | ||
return | ||
return; | ||
} | ||
const dimension = this._getDimension() | ||
const dimension = this._getDimension(); | ||
this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px` | ||
this._element.style[dimension] = `${ | ||
this._element.getBoundingClientRect()[dimension] | ||
}px`; | ||
Utils.reflow(this._element) | ||
Utils.reflow(this._element); | ||
this._element.classList.add(CLASS_NAME_COLLAPSING) | ||
this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW) | ||
this._element.classList.add(CLASS_NAME_COLLAPSING); | ||
this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW); | ||
const triggerArrayLength = this._triggerArray?.length | ||
const triggerArrayLength = this._triggerArray?.length; | ||
if (triggerArrayLength && this._triggerArray && triggerArrayLength > 0) { | ||
for (let i = 0; i < triggerArrayLength; i++) { | ||
const trigger = this._triggerArray[i] | ||
const elem = Utils.getElementFromSelector(trigger) | ||
const trigger = this._triggerArray[i]; | ||
const elem = Utils.getElementFromSelector(trigger); | ||
if (elem && !elem.classList.contains(CLASS_NAME_SHOW)) { | ||
trigger.classList.add(CLASS_NAME_COLLAPSED) | ||
trigger.setAttribute('aria-expanded', 'false') | ||
trigger.classList.add(CLASS_NAME_COLLAPSED); | ||
trigger.setAttribute("aria-expanded", "false"); | ||
} | ||
@@ -292,3 +305,3 @@ } | ||
this.setTransitioning(true) | ||
this.setTransitioning(true); | ||
@@ -298,18 +311,20 @@ const complete = () => { | ||
if (!this._element) { | ||
console.warn('this._element not set!'); | ||
console.warn("this._element not set!"); | ||
return; | ||
} | ||
this._element.classList.remove(CLASS_NAME_COLLAPSING) | ||
this._element.classList.add(CLASS_NAME_COLLAPSE) | ||
EventHandler.trigger(this._element, EVENT_HIDDEN) | ||
} | ||
this._element.classList.remove(CLASS_NAME_COLLAPSING); | ||
this._element.classList.add(CLASS_NAME_COLLAPSE); | ||
EventHandler.trigger(this._element, EVENT_HIDDEN); | ||
}; | ||
this._element.style[dimension] = '' | ||
const transitionDuration = Utils.getTransitionDurationFromElement(this._element) | ||
this._element.style[dimension] = ""; | ||
const transitionDuration = Utils.getTransitionDurationFromElement( | ||
this._element | ||
); | ||
EventHandler.one(this._element, TRANSITION_END, complete) | ||
EventHandler.one(this._element, TRANSITION_END, complete); | ||
Utils.emulateTransitionEnd(this._element, transitionDuration); | ||
if (!this._config.parent && this._triggerArray) { | ||
this._addAriaAndCollapsedClass(this._element, this._triggerArray, false) | ||
this._addAriaAndCollapsedClass(this._element, this._triggerArray, false); | ||
// this._addAriaAndCollapsedClass(this._element, []) | ||
@@ -320,3 +335,3 @@ } | ||
setTransitioning(isTransitioning: boolean) { | ||
this._isTransitioning = isTransitioning | ||
this._isTransitioning = isTransitioning; | ||
} | ||
@@ -329,7 +344,7 @@ | ||
this._config = null | ||
this._parent = null | ||
this._element = null | ||
this._config = null; | ||
this._parent = null; | ||
this._element = null; | ||
// this._triggerArray = null | ||
this._isTransitioning = false | ||
this._isTransitioning = false; | ||
} | ||
@@ -342,63 +357,68 @@ | ||
...Default, | ||
...config | ||
} | ||
config.toggle = Boolean(config.toggle) // Coerce string values | ||
Utils.typeCheckConfig(NAME, config, DefaultType) | ||
return config as Config | ||
...config, | ||
}; | ||
config.toggle = Boolean(config.toggle); // Coerce string values | ||
Utils.typeCheckConfig(NAME, config, DefaultType); | ||
return config as Config; | ||
} | ||
_getDimension() { | ||
const hasWidth = this._element ? this._element.classList.contains(WIDTH) : false; | ||
return hasWidth ? WIDTH : HEIGHT | ||
const hasWidth = this._element | ||
? this._element.classList.contains(WIDTH) | ||
: false; | ||
return hasWidth ? WIDTH : HEIGHT; | ||
} | ||
_getParent() { | ||
let { parent } = this._config | ||
let { parent } = this._config; | ||
if (Utils.isElement(parent)) { | ||
// it's a jQuery object | ||
if (typeof parent.jquery !== 'undefined' || typeof parent[0] !== 'undefined') { | ||
parent = parent[0] | ||
if ( | ||
typeof parent.jquery !== "undefined" || | ||
typeof parent[0] !== "undefined" | ||
) { | ||
parent = parent[0]; | ||
} | ||
} else { | ||
parent = SelectorEngine.findOne(parent) | ||
parent = SelectorEngine.findOne(parent); | ||
} | ||
// const selector = `${SELECTOR_DATA_TOGGLE}[data-parent="${parent}"]` | ||
const selector = `[data-parent="${parent}"]` | ||
const selector = `[data-parent="${parent}"]`; | ||
SelectorEngine.find(selector, parent) | ||
.forEach(element => { | ||
const selected = Utils.getElementFromSelector(element) | ||
SelectorEngine.find(selector, parent).forEach((element) => { | ||
const selected = Utils.getElementFromSelector(element); | ||
if (selected) { | ||
this._addAriaAndCollapsedClass( | ||
selected, | ||
[element] | ||
) | ||
} else { | ||
console.warn(); | ||
} | ||
}) | ||
if (selected) { | ||
this._addAriaAndCollapsedClass(selected, [element]); | ||
} else { | ||
console.warn(); | ||
} | ||
}); | ||
return parent | ||
return parent; | ||
} | ||
_addAriaAndCollapsedClass(element: HTMLElement, triggerArray: HTMLElement[], isOpen?: boolean) { | ||
_addAriaAndCollapsedClass( | ||
element: HTMLElement, | ||
triggerArray: HTMLElement[], | ||
isOpen?: boolean | ||
) { | ||
// console.debug('_addAriaAndCollapsedClass', element, triggerArray); | ||
if (element) { | ||
if (typeof isOpen !== 'boolean') { | ||
isOpen = element.classList.contains(CLASS_NAME_SHOW) | ||
if (typeof isOpen !== "boolean") { | ||
isOpen = element.classList.contains(CLASS_NAME_SHOW); | ||
} | ||
if (triggerArray.length) { | ||
triggerArray.forEach(elem => { | ||
triggerArray.forEach((elem) => { | ||
if (isOpen) { | ||
elem.classList.remove(CLASS_NAME_COLLAPSED) | ||
elem.classList.remove(CLASS_NAME_COLLAPSED); | ||
} else { | ||
elem.classList.add(CLASS_NAME_COLLAPSED) | ||
elem.classList.add(CLASS_NAME_COLLAPSED); | ||
} | ||
elem.setAttribute('aria-expanded', (!!isOpen).toString()) | ||
}) | ||
elem.setAttribute("aria-expanded", (!!isOpen).toString()); | ||
}); | ||
} | ||
@@ -411,30 +431,29 @@ } | ||
static collapseInterface(element: HTMLElement, config: string) { | ||
let data = Data.getData(element, DATA_KEY) | ||
let data = Data.getData(element, DATA_KEY); | ||
const _config: Config = { | ||
...Default, | ||
...element.dataset, | ||
...typeof config === 'object' && config ? config : {} | ||
} | ||
...(typeof config === "object" && config ? config : {}), | ||
}; | ||
if (!data && _config.toggle && /show|hide/.test(config)) { | ||
_config.toggle = false | ||
_config.toggle = false; | ||
} | ||
if (!data) { | ||
data = new CollapseService(element, [], _config) | ||
data = new CollapseService(element, [], _config); | ||
} | ||
if (typeof config === 'string') { | ||
if (typeof data[config] === 'undefined') { | ||
throw new TypeError(`No method named "${config}"`) | ||
if (typeof config === "string") { | ||
if (typeof data[config] === "undefined") { | ||
throw new TypeError(`No method named "${config}"`); | ||
} | ||
data[config]() | ||
data[config](); | ||
} | ||
} | ||
static getInstance(element: HTMLElement) { | ||
return Data.getData(element, DATA_KEY) | ||
return Data.getData(element, DATA_KEY); | ||
} | ||
} |
@@ -15,19 +15,18 @@ /** | ||
const mapData = (() => { | ||
const storeData: { [id: string]: any} = {}; | ||
let id = 1 | ||
const storeData: { [id: string]: any } = {}; | ||
let id = 1; | ||
return { | ||
set(element: HTMLElement, key: string, data: any) { | ||
if (typeof element.dataset.key === 'undefined') { | ||
if (typeof element.dataset.key === "undefined") { | ||
element.dataset.key = key; | ||
element.dataset.id = id.toString(); | ||
id++ | ||
id++; | ||
} | ||
if (element.dataset.id) { | ||
storeData[element.dataset.id] = data | ||
storeData[element.dataset.id] = data; | ||
} | ||
}, | ||
get(element: HTMLElement, key: string) { | ||
if (!element || typeof element.dataset.key === 'undefined') { | ||
return null | ||
if (!element || typeof element.dataset.key === "undefined") { | ||
return null; | ||
} | ||
@@ -38,12 +37,15 @@ | ||
id: element.dataset.id, | ||
}; | ||
if ( | ||
keyProperties.key === key && | ||
typeof keyProperties.id !== "undefined" | ||
) { | ||
return storeData[keyProperties.id]; | ||
} | ||
if (keyProperties.key === key && typeof(keyProperties.id) !== 'undefined') { | ||
return storeData[keyProperties.id] | ||
} | ||
return null | ||
return null; | ||
}, | ||
delete(element: HTMLElement, key: string) { | ||
if (typeof element.dataset.key === 'undefined') { | ||
return | ||
if (typeof element.dataset.key === "undefined") { | ||
return; | ||
} | ||
@@ -54,23 +56,26 @@ | ||
id: element.dataset.id, | ||
}; | ||
if ( | ||
keyProperties.key === key && | ||
typeof keyProperties.id !== "undefined" | ||
) { | ||
delete storeData[keyProperties.id]; | ||
delete element.dataset.key; | ||
} | ||
if (keyProperties.key === key && typeof(keyProperties.id) !== 'undefined') { | ||
delete storeData[keyProperties.id] | ||
delete element.dataset.key | ||
} | ||
} | ||
} | ||
})() | ||
}, | ||
}; | ||
})(); | ||
class Data { | ||
public static setData(instance: HTMLElement, key: string, data: any) { | ||
mapData.set(instance, key, data) | ||
mapData.set(instance, key, data); | ||
} | ||
public static getData(instance: HTMLElement, key: string) { | ||
return mapData.get(instance, key) | ||
return mapData.get(instance, key); | ||
} | ||
public static removeData(instance: HTMLElement, key: string) { | ||
mapData.delete(instance, key) | ||
mapData.delete(instance, key); | ||
} | ||
} | ||
export default Data | ||
export default Data; |
@@ -5,15 +5,31 @@ /** | ||
class EventHandler { | ||
public static on<T>(element: HTMLElement, eventName: string, handler: (e: T) => void) { | ||
public static on<T>( | ||
element: HTMLElement, | ||
eventName: string, | ||
handler: (e: T) => void | ||
) { | ||
return element.addEventListener(eventName as any, handler, {}); | ||
} | ||
public static one<T>(element: HTMLElement, eventName: string, handler: (e: T) => void) { | ||
return element.addEventListener(eventName as any, handler, {once: true}); | ||
public static one<T>( | ||
element: HTMLElement, | ||
eventName: string, | ||
handler: (e: T) => void | ||
) { | ||
return element.addEventListener(eventName as any, handler, { once: true }); | ||
} | ||
public static off<T>(element: HTMLElement, originalTypeEvent: string, handler: (e: T) => void) { | ||
public static off<T>( | ||
element: HTMLElement, | ||
originalTypeEvent: string, | ||
handler: (e: T) => void | ||
) { | ||
return element.removeEventListener(originalTypeEvent as any, handler); | ||
} | ||
public static trigger<T = any>(element: HTMLElement, eventName: string, extraParameters: any = {}) { | ||
public static trigger<T = any>( | ||
element: HTMLElement, | ||
eventName: string, | ||
extraParameters: any = {} | ||
) { | ||
const event = new CustomEvent<T>(eventName, { | ||
@@ -27,2 +43,2 @@ detail: extraParameters, | ||
export default EventHandler | ||
export default EventHandler; |
@@ -1,3 +0,3 @@ | ||
export * from './data'; | ||
export * from './event-handler'; | ||
export * from './selector-engine'; | ||
export * from "./data"; | ||
export * from "./event-handler"; | ||
export * from "./selector-engine"; |
@@ -9,3 +9,3 @@ /** | ||
import { Utils } from '../utils.service' | ||
import { Utils } from "../utils.service"; | ||
@@ -18,59 +18,76 @@ /** | ||
const NODE_TEXT = 3 | ||
const NODE_TEXT = 3; | ||
class SelectorEngine { | ||
public static matches(element: HTMLElement | Node & ParentNode, selector: string) { | ||
return Element.prototype.matches.call(element, selector) | ||
public static matches( | ||
element: HTMLElement | (Node & ParentNode), | ||
selector: string | ||
) { | ||
return Element.prototype.matches.call(element, selector); | ||
} | ||
public static find(selector: string, element = document.documentElement) { | ||
return Element.prototype.querySelectorAll.call(element, selector) as NodeListOf<HTMLElement> | ||
return Element.prototype.querySelectorAll.call( | ||
element, | ||
selector | ||
) as NodeListOf<HTMLElement>; | ||
} | ||
public static findOne(selector: string, element = document.documentElement) { | ||
return Element.prototype.querySelector.call(element, selector) as HTMLElement | null; | ||
return Element.prototype.querySelector.call( | ||
element, | ||
selector | ||
) as HTMLElement | null; | ||
} | ||
public static children(element: HTMLElement, selector: string) { | ||
const children = Utils.makeArray(element.children) | ||
return children.filter(child => this.matches(child, selector)) | ||
const children = Utils.makeArray(element.children); | ||
return children.filter((child) => this.matches(child, selector)); | ||
} | ||
public static parents(element: HTMLElement, selector: string) { | ||
const parents = [] | ||
const parents = []; | ||
let ancestor = element.parentNode | ||
let ancestor = element.parentNode; | ||
while (ancestor && ancestor.nodeType === Node.ELEMENT_NODE && ancestor.nodeType !== NODE_TEXT) { | ||
while ( | ||
ancestor && | ||
ancestor.nodeType === Node.ELEMENT_NODE && | ||
ancestor.nodeType !== NODE_TEXT | ||
) { | ||
if (this.matches(ancestor, selector)) { | ||
parents.push(ancestor) | ||
parents.push(ancestor); | ||
} | ||
ancestor = ancestor.parentNode | ||
ancestor = ancestor.parentNode; | ||
} | ||
return parents | ||
return parents; | ||
} | ||
public static closest(element: HTMLElement, selector: string) { | ||
return Element.prototype.closest.call(element, selector) | ||
return Element.prototype.closest.call(element, selector); | ||
} | ||
public static prev(element: HTMLElement, selector: string) { | ||
const siblings = [] | ||
const siblings = []; | ||
let previous = element.previousSibling | ||
let previous = element.previousSibling; | ||
while (previous && previous.nodeType === Node.ELEMENT_NODE && previous.nodeType !== NODE_TEXT) { | ||
while ( | ||
previous && | ||
previous.nodeType === Node.ELEMENT_NODE && | ||
previous.nodeType !== NODE_TEXT | ||
) { | ||
if (this.matches(previous as HTMLElement, selector)) { | ||
siblings.push(previous) | ||
siblings.push(previous); | ||
} | ||
previous = previous.previousSibling | ||
previous = previous.previousSibling; | ||
} | ||
return siblings | ||
return siblings; | ||
} | ||
} | ||
export default SelectorEngine | ||
export default SelectorEngine; |
@@ -1,3 +0,3 @@ | ||
import Popper from 'popper.js'; // /dist/umd/popper | ||
import { Utils } from './utils.service'; | ||
import Popper from "popper.js"; // /dist/umd/popper | ||
import { Utils } from "./utils.service"; | ||
/** | ||
@@ -17,70 +17,72 @@ * -------------------------------------------------------------------------- | ||
export const NAME = 'dropdown'; | ||
export const VERSION = '4.1.3'; | ||
export const DATA_KEY = 'bs.dropdown'; | ||
export const EVENT_KEY = `.${DATA_KEY}`; | ||
export const DATA_API_KEY = '.data-api'; | ||
export const ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key | ||
export const SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key | ||
export const TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key | ||
export const ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key | ||
export const ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key | ||
export const NAME = "dropdown"; | ||
export const VERSION = "4.1.3"; | ||
export const DATA_KEY = "bs.dropdown"; | ||
export const EVENT_KEY = `.${DATA_KEY}`; | ||
export const DATA_API_KEY = ".data-api"; | ||
export const ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key | ||
export const SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key | ||
export const TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key | ||
export const ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key | ||
export const ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key | ||
export const RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse) | ||
export const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`); | ||
export const REGEXP_KEYDOWN = new RegExp( | ||
`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}` | ||
); | ||
export const EVENT = { | ||
HIDE : `hide${EVENT_KEY}`, | ||
HIDDEN : `hidden${EVENT_KEY}`, | ||
SHOW : `show${EVENT_KEY}`, | ||
SHOWN : `shown${EVENT_KEY}`, | ||
CLICK : `click${EVENT_KEY}`, | ||
CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`, | ||
KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`, | ||
KEYUP_DATA_API : `keyup${EVENT_KEY}${DATA_API_KEY}`, | ||
HIDE: `hide${EVENT_KEY}`, | ||
HIDDEN: `hidden${EVENT_KEY}`, | ||
SHOW: `show${EVENT_KEY}`, | ||
SHOWN: `shown${EVENT_KEY}`, | ||
CLICK: `click${EVENT_KEY}`, | ||
CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`, | ||
KEYDOWN_DATA_API: `keydown${EVENT_KEY}${DATA_API_KEY}`, | ||
KEYUP_DATA_API: `keyup${EVENT_KEY}${DATA_API_KEY}`, | ||
}; | ||
export const CLASSNAME = { | ||
DISABLED : 'disabled', | ||
SHOW : 'show', | ||
DROPUP : 'dropup', | ||
DROPRIGHT : 'dropright', | ||
DROPLEFT : 'dropleft', | ||
MENURIGHT : 'dropdown-menu-right', | ||
MENULEFT : 'dropdown-menu-left', | ||
POSITION_STATIC : 'position-static', | ||
DISABLED: "disabled", | ||
SHOW: "show", | ||
DROPUP: "dropup", | ||
DROPRIGHT: "dropright", | ||
DROPLEFT: "dropleft", | ||
MENURIGHT: "dropdown-menu-right", | ||
MENULEFT: "dropdown-menu-left", | ||
POSITION_STATIC: "position-static", | ||
}; | ||
export const SELECTOR = { | ||
DATA_TOGGLE : 'bs4-dropdown .dropdown-toggle', | ||
FORM_CHILD : '.dropdown form', | ||
MENU : '.dropdown-menu', | ||
NAVBAR_NAV : '.navbar-nav', | ||
VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)', | ||
DATA_TOGGLE: "bs4-dropdown .dropdown-toggle", | ||
FORM_CHILD: ".dropdown form", | ||
MENU: ".dropdown-menu", | ||
NAVBAR_NAV: ".navbar-nav", | ||
VISIBLE_ITEMS: ".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)", | ||
}; | ||
export const ATTACHMENTMAP = { | ||
TOP : 'top-start', | ||
TOPEND : 'top-end', | ||
BOTTOM : 'bottom-start', | ||
BOTTOMEND : 'bottom-end', | ||
RIGHT : 'right-start', | ||
RIGHTEND : 'right-end', | ||
LEFT : 'left-start', | ||
LEFTEND : 'left-end', | ||
TOP: "top-start", | ||
TOPEND: "top-end", | ||
BOTTOM: "bottom-start", | ||
BOTTOMEND: "bottom-end", | ||
RIGHT: "right-start", | ||
RIGHTEND: "right-end", | ||
LEFT: "left-start", | ||
LEFTEND: "left-end", | ||
}; | ||
export const DEFAULT = { | ||
offset : 0, | ||
flip : true, | ||
boundary : 'scrollParent', | ||
reference : 'toggle', | ||
display : 'dynamic', | ||
offset: 0, | ||
flip: true, | ||
boundary: "scrollParent", | ||
reference: "toggle", | ||
display: "dynamic", | ||
}; | ||
export const DEFAULTTYPE = { | ||
offset : '(number|string|function)', | ||
flip : 'boolean', | ||
boundary : '(string|element)', | ||
reference : '(string|element)', | ||
display : 'string', | ||
offset: "(number|string|function)", | ||
flip: "boolean", | ||
boundary: "(string|element)", | ||
reference: "(string|element)", | ||
display: "string", | ||
}; | ||
@@ -94,3 +96,2 @@ | ||
export class DropdownService { | ||
// Getters | ||
@@ -116,3 +117,6 @@ | ||
if (button.parentElement) { | ||
const menu = button.parentElement.querySelector(SELECTOR.MENU + '.' + CLASSNAME.SHOW) || undefined; | ||
const menu = | ||
button.parentElement.querySelector( | ||
SELECTOR.MENU + "." + CLASSNAME.SHOW | ||
) || undefined; | ||
if (menu) { | ||
@@ -126,3 +130,7 @@ return this.close(button, menu, button); | ||
public static close(triggerCloseElement: Element, menu: Element, dropdown?: Element) { | ||
public static close( | ||
triggerCloseElement: Element, | ||
menu: Element, | ||
dropdown?: Element | ||
) { | ||
const relatedTarget = { | ||
@@ -138,3 +146,5 @@ relatedTarget: triggerCloseElement, | ||
dropdown.classList.remove(CLASSNAME.SHOW); | ||
dropdown.dispatchEvent(new CustomEvent(EVENT.HIDDEN, { detail: relatedTarget})); | ||
dropdown.dispatchEvent( | ||
new CustomEvent(EVENT.HIDDEN, { detail: relatedTarget }) | ||
); | ||
} | ||
@@ -146,3 +156,5 @@ | ||
parent.classList.remove(CLASSNAME.SHOW); | ||
parent.dispatchEvent(new CustomEvent(EVENT.HIDDEN, { detail: relatedTarget})); | ||
parent.dispatchEvent( | ||
new CustomEvent(EVENT.HIDDEN, { detail: relatedTarget }) | ||
); | ||
} | ||
@@ -157,3 +169,3 @@ } | ||
if (!element.parentElement) { | ||
throw new Error('Parent element not found!'); | ||
throw new Error("Parent element not found!"); | ||
} | ||
@@ -164,3 +176,3 @@ return element.parentElement; | ||
private _element: HTMLButtonElement | HTMLAnchorElement; | ||
private _popper: any /* Popper */ | null; // TODO Popper namcespace error | ||
private _popper: any | /* Popper */ null; // TODO Popper namcespace error | ||
private _config: any; // TODO | ||
@@ -171,8 +183,10 @@ private _menu: Element; | ||
constructor(elements: HTMLButtonElement | HTMLAnchorElement, config?: any) { | ||
this._element = elements; | ||
this._popper = null; | ||
this._config = this._getConfig(config); | ||
this._menu = this._getMenuElement(); | ||
this._element = elements; | ||
this._popper = null; | ||
this._config = this._getConfig(config); | ||
this._menu = this._getMenuElement(); | ||
this._inNavbar = this._detectNavbar(); | ||
this.clouseOnClickOutsite(DropdownService._getParentFromElement(this._element)); | ||
this.clouseOnClickOutsite( | ||
DropdownService._getParentFromElement(this._element) | ||
); | ||
} | ||
@@ -199,3 +213,5 @@ | ||
parent.classList.add(CLASSNAME.SHOW); | ||
parent.dispatchEvent(new CustomEvent(EVENT.SHOWN, {detail: relatedTarget})); | ||
parent.dispatchEvent( | ||
new CustomEvent(EVENT.SHOWN, { detail: relatedTarget }) | ||
); | ||
} | ||
@@ -205,7 +221,10 @@ } | ||
public toggle() { | ||
if ((this._element as HTMLButtonElement).disabled || this._element.classList.contains(CLASSNAME.DISABLED)) { | ||
if ( | ||
(this._element as HTMLButtonElement).disabled || | ||
this._element.classList.contains(CLASSNAME.DISABLED) | ||
) { | ||
return; | ||
} | ||
const parent = DropdownService._getParentFromElement(this._element); | ||
const parent = DropdownService._getParentFromElement(this._element); | ||
const isActive = this._menu.classList.contains(CLASSNAME.SHOW); | ||
@@ -223,3 +242,3 @@ | ||
}; | ||
const showEvent = new CustomEvent(EVENT.SHOW, {detail: relatedTarget}); | ||
const showEvent = new CustomEvent(EVENT.SHOW, { detail: relatedTarget }); | ||
@@ -233,3 +252,5 @@ if (parent) { | ||
this.clouseOnClickOutsite(DropdownService._getParentFromElement(this._element)); | ||
this.clouseOnClickOutsite( | ||
DropdownService._getParentFromElement(this._element) | ||
); | ||
@@ -242,4 +263,6 @@ // Disable totally Popper.js for Dropdown in Navbar | ||
*/ | ||
if (typeof Popper === 'undefined') { | ||
throw new TypeError('Bootstrap dropdown require Popper.js (https://popper.js.org)'); | ||
if (typeof Popper === "undefined") { | ||
throw new TypeError( | ||
"Bootstrap dropdown require Popper.js (https://popper.js.org)" | ||
); | ||
} | ||
@@ -249,3 +272,3 @@ | ||
if (this._config.reference === 'parent') { | ||
if (this._config.reference === "parent") { | ||
referenceElement = parent as HTMLElement; | ||
@@ -256,3 +279,3 @@ } else if (Utils.isElement(this._config.reference)) { | ||
// Check if it's jQuery element | ||
if (typeof this._config.reference.jquery !== 'undefined') { | ||
if (typeof this._config.reference.jquery !== "undefined") { | ||
referenceElement = this._config.reference[0]; | ||
@@ -265,12 +288,18 @@ } | ||
// https://github.com/twbs/bootstrap/issues/24251 | ||
if (parent && this._config.boundary !== 'scrollParent') { | ||
if (parent && this._config.boundary !== "scrollParent") { | ||
parent.classList.add(CLASSNAME.POSITION_STATIC); | ||
} | ||
this._popper = new Popper(referenceElement, this._menu as HTMLElement, this._getPopperConfig()); | ||
this._popper = new Popper( | ||
referenceElement, | ||
this._menu as HTMLElement, | ||
this._getPopperConfig() | ||
); | ||
} | ||
this.clouseOnClickOutsite(DropdownService._getParentFromElement(this._element)); | ||
this.clouseOnClickOutsite( | ||
DropdownService._getParentFromElement(this._element) | ||
); | ||
this._element.focus(); | ||
this._element.setAttribute('aria-expanded', 'true'); | ||
this._element.setAttribute("aria-expanded", "true"); | ||
@@ -282,7 +311,9 @@ if (this._menu.classList.contains(CLASSNAME.SHOW)) { | ||
} | ||
this._menu.dispatchEvent(new CustomEvent(EVENT.SHOWN, {detail: relatedTarget})); | ||
this._menu.dispatchEvent( | ||
new CustomEvent(EVENT.SHOWN, { detail: relatedTarget }) | ||
); | ||
} | ||
public dispose() { | ||
this._element.removeAttribute('data-' + DATA_KEY); | ||
this._element.removeAttribute("data-" + DATA_KEY); | ||
delete this._element; | ||
@@ -309,3 +340,6 @@ delete this._menu; | ||
this.close(); | ||
document.removeEventListener('click', this.outsideClickListener.bind(this, element)); | ||
document.removeEventListener( | ||
"click", | ||
this.outsideClickListener.bind(this, element) | ||
); | ||
} | ||
@@ -319,3 +353,6 @@ } | ||
private clouseOnClickOutsite(element: Element) { | ||
document.addEventListener('click', this.outsideClickListener.bind(this, element)); | ||
document.addEventListener( | ||
"click", | ||
this.outsideClickListener.bind(this, element) | ||
); | ||
} | ||
@@ -330,7 +367,3 @@ | ||
Utils.typeCheckConfig( | ||
NAME, | ||
config, | ||
DropdownService.DefaultType, | ||
); | ||
Utils.typeCheckConfig(NAME, config, DropdownService.DefaultType); | ||
@@ -346,3 +379,3 @@ return config; | ||
if (!menu) { | ||
throw new Error('Menu not found!'); | ||
throw new Error("Menu not found!"); | ||
} | ||
@@ -360,3 +393,3 @@ this._menu = menu; | ||
if (!parentDropdown) { | ||
throw new Error('Parent of element not found!'); | ||
throw new Error("Parent of element not found!"); | ||
} | ||
@@ -381,3 +414,3 @@ | ||
private _detectNavbar() { | ||
return this._element.closest && this._element.closest('.navbar') !== null; | ||
return this._element.closest && this._element.closest(".navbar") !== null; | ||
} | ||
@@ -387,7 +420,7 @@ | ||
const offsetConf: any = {}; | ||
if (typeof this._config.offset === 'function') { | ||
if (typeof this._config.offset === "function") { | ||
offsetConf.fn = (data: any) => { | ||
data.offsets = { | ||
...data.offsets, | ||
...this._config.offset(data.offsets) || {}, | ||
...(this._config.offset(data.offsets) || {}), | ||
}; | ||
@@ -414,3 +447,3 @@ return data; | ||
// Disable Popper.js if we have a static display | ||
if (this._config.display === 'static') { | ||
if (this._config.display === "static") { | ||
popperConfig.modifiers.applyStyle = { | ||
@@ -422,3 +455,2 @@ enabled: false, | ||
} | ||
} |
@@ -1,5 +0,6 @@ | ||
export * from './dom'; | ||
export * from './carousel.service'; | ||
export { CollapseService } from './collapse.service'; | ||
export { DropdownService } from './dropdown.service'; | ||
export * from './utils.service'; | ||
export * from "./dom"; | ||
export * from "./carousel.service"; | ||
export { CollapseService } from "./collapse.service"; | ||
export { DropdownService } from "./dropdown.service"; | ||
export { ToastService } from "./toast.service"; | ||
export * from "./utils.service"; |
@@ -1,8 +0,5 @@ | ||
import { | ||
Utils as RibaUtils, | ||
} from '@ribajs/core'; | ||
import { Utils as RibaUtils } from "@ribajs/core"; | ||
export const MAX_UID = 1000000 | ||
export const MILLISECONDS_MULTIPLIER = 1000 | ||
export const TRANSITION_END = 'transitionend' | ||
export const MILLISECONDS_MULTIPLIER = 1000; | ||
export const TRANSITION_END = "transitionend"; | ||
@@ -14,3 +11,2 @@ /** | ||
export class Utils extends RibaUtils { | ||
/** | ||
@@ -21,95 +17,94 @@ * Shoutout AngusCroll (https://goo.gl/pxwQGp) | ||
public static toType(obj: any) { | ||
const matches = {}.toString.call(obj).match(/\s([a-z]+)/i); | ||
const matches = {}.toString.call(obj).match(/\s([a-z]+)/i); | ||
return matches ? matches[1].toLowerCase() : null; | ||
} | ||
public static getUID(prefix: string) { | ||
do { | ||
prefix += ~~(Math.random() * MAX_UID) // "~~" acts like a faster Math.floor() here | ||
} while (document.getElementById(prefix)) | ||
return prefix | ||
} | ||
public static getSelector(element: HTMLElement) { | ||
let selector = element.getAttribute('data-target') | ||
if (!selector || selector === '#') { | ||
const hrefAttr = element.getAttribute('href') | ||
selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null | ||
public static getSelector(element: HTMLElement) { | ||
let selector = element.getAttribute("data-target"); | ||
if (!selector || selector === "#") { | ||
const hrefAttr = element.getAttribute("href"); | ||
selector = hrefAttr && hrefAttr !== "#" ? hrefAttr.trim() : null; | ||
} | ||
return selector | ||
return selector; | ||
} | ||
public static getSelectorFromElement(element: HTMLElement) { | ||
const selector = Utils.getSelector(element) | ||
const selector = Utils.getSelector(element); | ||
if (selector) { | ||
return document.querySelector(selector) ? selector : null | ||
return document.querySelector(selector) ? selector : null; | ||
} | ||
return null | ||
return null; | ||
} | ||
public static getElementFromSelector(element: HTMLElement) { | ||
const selector = Utils.getSelector(element) | ||
return (selector ? document.querySelector(selector) : null) as HTMLElement | null; | ||
const selector = Utils.getSelector(element); | ||
return (selector | ||
? document.querySelector(selector) | ||
: null) as HTMLElement | null; | ||
} | ||
public static getTransitionDurationFromElement(element: HTMLElement) { | ||
if (!element) { | ||
return 0 | ||
return 0; | ||
} | ||
// Get transition-duration of the element | ||
let { | ||
transitionDuration, | ||
transitionDelay | ||
} = window.getComputedStyle(element) | ||
const floatTransitionDuration = parseFloat(transitionDuration) | ||
const floatTransitionDelay = parseFloat(transitionDelay) | ||
let { transitionDuration, transitionDelay } = window.getComputedStyle( | ||
element | ||
); | ||
const floatTransitionDuration = parseFloat(transitionDuration); | ||
const floatTransitionDelay = parseFloat(transitionDelay); | ||
// Return 0 if element or transition duration is not found | ||
if (!floatTransitionDuration && !floatTransitionDelay) { | ||
return 0 | ||
return 0; | ||
} | ||
// If multiple durations are defined, take the first | ||
transitionDuration = transitionDuration.split(',')[0] | ||
transitionDelay = transitionDelay.split(',')[0] | ||
return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER | ||
transitionDuration = transitionDuration.split(",")[0]; | ||
transitionDelay = transitionDelay.split(",")[0]; | ||
return ( | ||
(parseFloat(transitionDuration) + parseFloat(transitionDelay)) * | ||
MILLISECONDS_MULTIPLIER | ||
); | ||
} | ||
public static triggerTransitionEnd(element: HTMLElement) { | ||
const evt = document.createEvent('HTMLEvents') | ||
evt.initEvent(TRANSITION_END, true, true) | ||
element.dispatchEvent(evt) | ||
const evt = document.createEvent("HTMLEvents"); | ||
evt.initEvent(TRANSITION_END, true, true); | ||
element.dispatchEvent(evt); | ||
} | ||
public static isElement(obj: Element | Element[]) { | ||
return ((obj as Element[])[0] || obj as Element).nodeType; | ||
return ((obj as Element[])[0] || (obj as Element)).nodeType; | ||
} | ||
public static emulateTransitionEnd = (element: HTMLElement, duration: number) => { | ||
let called = false | ||
const durationPadding = 5 | ||
const emulatedDuration = duration + durationPadding | ||
public static emulateTransitionEnd = ( | ||
element: HTMLElement, | ||
duration: number | ||
) => { | ||
let called = false; | ||
const durationPadding = 5; | ||
const emulatedDuration = duration + durationPadding; | ||
function listener() { | ||
called = true | ||
element.removeEventListener(TRANSITION_END, listener) | ||
called = true; | ||
element.removeEventListener(TRANSITION_END, listener); | ||
} | ||
element.addEventListener(TRANSITION_END, listener) | ||
element.addEventListener(TRANSITION_END, listener); | ||
setTimeout(() => { | ||
if (!called) { | ||
Utils.triggerTransitionEnd(element) | ||
Utils.triggerTransitionEnd(element); | ||
} | ||
}, emulatedDuration) | ||
} | ||
}, emulatedDuration); | ||
}; | ||
@@ -122,8 +117,13 @@ /** | ||
*/ | ||
public static typeCheckConfig(componentName: string, config: any, configTypes: any) { | ||
public static typeCheckConfig( | ||
componentName: string, | ||
config: any, | ||
configTypes: any | ||
) { | ||
for (const property in configTypes) { | ||
if (Object.prototype.hasOwnProperty.call(configTypes, property)) { | ||
const expectedTypes = configTypes[property]; | ||
const value = config[property]; | ||
const valueType = value && Utils.isElement(value) ? 'element' : Utils.toType(value); | ||
const value = config[property]; | ||
const valueType = | ||
value && Utils.isElement(value) ? "element" : Utils.toType(value); | ||
@@ -133,4 +133,5 @@ if (!valueType || !new RegExp(expectedTypes).test(valueType)) { | ||
`${componentName.toUpperCase()}: ` + | ||
`Option "${property}" provided type "${valueType}" ` + | ||
`but expected type "${expectedTypes}".`); | ||
`Option "${property}" provided type "${valueType}" ` + | ||
`but expected type "${expectedTypes}".` | ||
); | ||
} | ||
@@ -143,66 +144,77 @@ } | ||
if (!nodeList) { | ||
return [] | ||
return []; | ||
} | ||
return [].slice.call(nodeList) | ||
return [].slice.call(nodeList); | ||
} | ||
public static isVisible(element: HTMLElement) { | ||
if (!element) { | ||
return false | ||
return false; | ||
} | ||
if (element.style && element.parentNode && (element.parentNode as HTMLElement).style) { | ||
const elementStyle = getComputedStyle(element) | ||
const parentNodeStyle = getComputedStyle(element.parentNode as HTMLElement) | ||
return elementStyle.display !== 'none' && | ||
parentNodeStyle.display !== 'none' && | ||
elementStyle.visibility !== 'hidden' | ||
if ( | ||
element.style && | ||
element.parentNode && | ||
(element.parentNode as HTMLElement).style | ||
) { | ||
const elementStyle = getComputedStyle(element); | ||
const parentNodeStyle = getComputedStyle( | ||
element.parentNode as HTMLElement | ||
); | ||
return ( | ||
elementStyle.display !== "none" && | ||
parentNodeStyle.display !== "none" && | ||
elementStyle.visibility !== "hidden" | ||
); | ||
} | ||
return false | ||
return false; | ||
} | ||
public static findShadowRoot(element: HTMLElement | Node & ParentNode): HTMLElement | Node & ParentNode | null { | ||
public static findShadowRoot( | ||
element: HTMLElement | (Node & ParentNode) | ||
): HTMLElement | (Node & ParentNode) | null { | ||
if (!document.documentElement.attachShadow) { | ||
return null | ||
return null; | ||
} | ||
// Can find the shadow root otherwise it'll return the document | ||
if (typeof element.getRootNode === 'function') { | ||
const root = element.getRootNode() | ||
return root instanceof ShadowRoot ? root : null | ||
if (typeof element.getRootNode === "function") { | ||
const root = element.getRootNode(); | ||
return root instanceof ShadowRoot ? root : null; | ||
} | ||
if (element instanceof ShadowRoot) { | ||
return element | ||
return element; | ||
} | ||
// when we don't find a shadow root | ||
if (!element.parentNode) { | ||
return null | ||
return null; | ||
} | ||
return Utils.findShadowRoot(element.parentNode) | ||
return Utils.findShadowRoot(element.parentNode); | ||
} | ||
public static noop(){ | ||
return function () {/** nothing */}; | ||
} | ||
public static reflow(element: HTMLElement){ | ||
public static noop() { | ||
return function () { | ||
/** nothing */ | ||
}; | ||
} | ||
public static reflow(element: HTMLElement) { | ||
return element.offsetHeight; | ||
} | ||
} | ||
public static getjQuery = () => { | ||
const { jQuery } = (window as any) | ||
if (jQuery && !document.body.hasAttribute('data-no-jquery')) { | ||
return jQuery | ||
const { jQuery } = window as any; | ||
if (jQuery && !document.body.hasAttribute("data-no-jquery")) { | ||
return jQuery; | ||
} | ||
return null | ||
} | ||
return null; | ||
}; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
96
246918
32
6549
+ Added@ribajs/cache@1.9.0-alpha.1(transitive)
+ Added@ribajs/core@1.9.0-alpha.1(transitive)
+ Added@ribajs/extras@1.9.0-alpha.1(transitive)
+ Added@ribajs/utils@1.9.0-alpha.1(transitive)
- Removed@ribajs/cache@1.9.0-alpha.0(transitive)
- Removed@ribajs/core@1.9.0-alpha.0(transitive)
- Removed@ribajs/extras@1.9.0-alpha.0(transitive)
- Removed@ribajs/utils@1.9.0-alpha.0(transitive)
Updated@ribajs/cache@1.9.0-alpha.1
Updated@ribajs/core@1.9.0-alpha.1
Updated@ribajs/extras@1.9.0-alpha.1
Updated@ribajs/utils@1.9.0-alpha.1
Updatedbootstrap@^4.5.0