Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/js/main/sidepanel/src/ |
Upload File : |
import type { JsonObject } from 'main.core'; import { Type, Dom, Event, Runtime, Reflection, Browser, ajax as Ajax, Uri } from 'main.core'; import { EventEmitter, BaseEvent } from 'main.core.events'; import { Slider } from './slider'; import type { SliderEvent } from './slider-event'; import { Toolbar } from './toolbar'; import { MessageEvent } from './message-event'; import type { ToolbarItem } from './toolbar-item'; import type { LinkOptions } from './types/link-options'; import type { MinimizeOptions } from './types/minimize-options'; import type { RuleOptions } from './types/rule-options'; import { type SliderOptions } from './types/slider-options'; let sliderClassName = null; let sliderDefaultOptions: SliderOptions = null; let sliderPriorityOptions: SliderOptions = null; /** * @namespace BX.SidePanel * @alias Manager */ export class SliderManager { constructor() { this.anchorRules = []; this.anchorBinding = true; this.openSliders = []; this.lastOpenSlider = null; this.opened = false; this.hidden = false; this.hacksApplied = false; this.pageUrl = this.getCurrentUrl(); this.pageTitle = this.getCurrentTitle(); this.titleChanged = false; this.toolbar = null; this.fullScreenSlider = null; this.handleAnchorClick = this.handleAnchorClick.bind(this); this.handleDocumentKeyDown = this.handleDocumentKeyDown.bind(this); this.handleWindowResize = Runtime.throttle(this.handleWindowResize, 300, this); this.handleWindowScroll = this.handleWindowScroll.bind(this); this.handleTouchMove = this.handleTouchMove.bind(this); this.handleSliderOpenStart = this.handleSliderOpenStart.bind(this); this.handleSliderOpenComplete = this.handleSliderOpenComplete.bind(this); this.handleSliderMaximizeStart = this.handleSliderMaximizeStart.bind(this); this.handleSliderCloseStart = this.handleSliderCloseStart.bind(this); this.handleSliderCloseComplete = this.handleSliderCloseComplete.bind(this); this.handleSliderMinimizeStart = this.handleSliderMinimizeStart.bind(this); this.handleSliderLoad = this.handleSliderLoad.bind(this); this.handleSliderDestroy = this.handleSliderDestroy.bind(this); this.handleEscapePress = this.handleEscapePress.bind(this); this.handleFullScreenChange = this.handleFullScreenChange.bind(this); EventEmitter.subscribe('SidePanel:open', this.open.bind(this), { compatMode: true }); EventEmitter.subscribe('SidePanel:close', this.close.bind(this), { compatMode: true }); EventEmitter.subscribe('SidePanel:closeAll', this.closeAll.bind(this), { compatMode: true }); EventEmitter.subscribe('SidePanel:destroy', this.destroy.bind(this), { compatMode: true }); EventEmitter.subscribe('SidePanel:hide', this.hide.bind(this), { compatMode: true }); EventEmitter.subscribe('SidePanel:unhide', this.unhide.bind(this), { compatMode: true }); EventEmitter.subscribe('SidePanel:postMessage', this.postMessage.bind(this), { compatMode: true }); EventEmitter.subscribe('SidePanel:postMessageAll', this.postMessageAll.bind(this), { compatMode: true }); EventEmitter.subscribe('SidePanel:postMessageTop', this.postMessageTop.bind(this), { compatMode: true }); // Compatibility EventEmitter.subscribe('BX.Bitrix24.PageSlider:close', this.close.bind(this), { compatMode: true }); EventEmitter.subscribe('Bitrix24.Slider:postMessage', this.handlePostMessageCompatible.bind(this), { compatMode: true }); } static registerSliderClass( className: string, defaultOptions: SliderOptions = null, priorityOptions: SliderOptions = null, ): void { if (Type.isStringFilled(className)) { sliderClassName = className; } if (Type.isPlainObject(defaultOptions)) { sliderDefaultOptions = defaultOptions; } if (Type.isPlainObject(priorityOptions)) { sliderPriorityOptions = priorityOptions; } } static getSliderClass(): Slider { const sliderClass = sliderClassName === null ? null : Reflection.getClass(sliderClassName); return sliderClass === null ? Slider : sliderClass; } static getSliderDefaultOptions(): SliderOptions { return sliderDefaultOptions === null ? {} : sliderDefaultOptions; } static getSliderPriorityOptions(): SliderOptions { return sliderPriorityOptions === null ? {} : sliderPriorityOptions; } open(url: string, options: SliderOptions): boolean { const slider = this.#createSlider(url, options); if (slider === null) { return false; } return this.tryApplyHacks( slider, () => slider.open(), ); } #createSlider(sliderUrl: string, sliderOptions: SliderOptions): Slider | null { if (!Type.isStringFilled(sliderUrl)) { return null; } const url = this.refineUrl(sliderUrl); if (this.isHidden()) { this.unhide(); } const topSlider = this.getTopSlider(); if (topSlider && topSlider.isOpen() && topSlider.getUrl() === url) { return null; } if (this.getLastOpenSlider() && this.getLastOpenSlider().getUrl() === url) { return this.getLastOpenSlider(); } const rule = this.getUrlRule(url); const ruleOptions = rule !== null && Type.isPlainObject(rule.options) ? rule.options : {}; const options = Type.isPlainObject(sliderOptions) ? sliderOptions : ruleOptions; if ( Type.isPlainObject(ruleOptions.minimizeOptions) && Type.isPlainObject(sliderOptions) && !Type.isPlainObject(sliderOptions.minimizeOptions) ) { options.minimizeOptions = ruleOptions.minimizeOptions; } if (this.getToolbar() === null && options.minimizeOptions) { options.minimizeOptions = null; } const defaultOptions = SliderManager.getSliderDefaultOptions(); const priorityOptions = SliderManager.getSliderPriorityOptions(); const SliderClass = SliderManager.getSliderClass(); const slider: Slider = new SliderClass(url, Runtime.merge(defaultOptions, options, priorityOptions)); let offset = null; if (slider.shouldUseAutoOffset() && slider.getWidth() === null && slider.getCustomLeftBoundary() === null) { offset = 0; const lastOffset = this.#getLastOffset(); if (topSlider && lastOffset !== null) { offset = Math.min(lastOffset + this.#getMinOffset(), this.#getMaxOffset()); } } slider.setOffset(offset); if (topSlider && topSlider.getCustomRightBoundary() !== null) { const rightBoundary = slider.calculateRightBoundary(); if (rightBoundary > topSlider.getCustomRightBoundary()) { slider.setCustomRightBoundary(topSlider.getCustomRightBoundary()); } } EventEmitter.subscribe(slider, 'SidePanel.Slider:onOpenStart', this.handleSliderOpenStart, { compatMode: true }); EventEmitter.subscribe(slider, 'SidePanel.Slider:onBeforeOpenComplete', this.handleSliderOpenComplete, { compatMode: true }); EventEmitter.subscribe(slider, 'SidePanel.Slider:onMaximizeStart', this.handleSliderMaximizeStart, { compatMode: true }); EventEmitter.subscribe(slider, 'SidePanel.Slider:onCloseStart', this.handleSliderCloseStart, { compatMode: true }); EventEmitter.subscribe(slider, 'SidePanel.Slider:onBeforeCloseComplete', this.handleSliderCloseComplete, { compatMode: true }); EventEmitter.subscribe(slider, 'SidePanel.Slider:onMinimizeStart', this.handleSliderMinimizeStart, { compatMode: true }); EventEmitter.subscribe(slider, 'SidePanel.Slider:onLoad', this.handleSliderLoad, { compatMode: true }); EventEmitter.subscribe(slider, 'SidePanel.Slider:onDestroy', this.handleSliderDestroy, { compatMode: true }); EventEmitter.subscribe(slider, 'SidePanel.Slider:onEscapePress', this.handleEscapePress, { compatMode: true }); return slider; } getMinimizeOptions(url: string): MinimizeOptions | null { const rule = this.getUrlRule(url); const ruleOptions = rule !== null && Type.isPlainObject(rule.options) ? rule.options : {}; return Type.isPlainObject(ruleOptions.minimizeOptions) ? ruleOptions.minimizeOptions : null; } maximize(url, options: SliderOptions): boolean { const slider = this.#createSlider(url, options); if (slider === null) { return false; } return this.tryApplyHacks( slider, () => slider.maximize(), ); } tryApplyHacks(slider, cb: Function): boolean { if (!this.isOpen()) { this.applyHacks(slider); } const success = cb(); if (!success) { this.resetHacks(slider); } return success; } isOpen(): boolean { return this.opened; } close(immediately: boolean, callback: Function): void { const topSlider = this.getTopSlider(); if (topSlider) { topSlider.close(immediately, callback); } } closeAll(immediately: boolean): void { const openSliders = this.getOpenSliders(); for (let i = openSliders.length - 1; i >= 0; i--) { const slider = openSliders[i]; const success = slider.close(immediately); if (!success) { break; } } } minimize(immediately: boolean, callback: Function): void { const topSlider = this.getTopSlider(); if (topSlider) { topSlider.minimize(immediately, callback); } } hide(): boolean { if (this.hidden) { return false; } const topSlider = this.getTopSlider(); this.getOpenSliders().forEach((slider: Slider) => { slider.hide(); }); this.hidden = true; this.resetHacks(topSlider); return true; } unhide(): boolean { if (!this.hidden) { return false; } this.getOpenSliders().forEach((slider) => { slider.unhide(); }); this.hidden = false; setTimeout(() => { this.applyHacks(this.getTopSlider()); }, 0); return true; } isHidden(): boolean { return this.hidden; } destroy(sliderUrl: string) { if (!Type.isStringFilled(sliderUrl)) { return; } const url = this.refineUrl(sliderUrl); const sliderToDestroy = this.getSlider(url); if (this.getLastOpenSlider() && (sliderToDestroy || this.getLastOpenSlider().getUrl() === url)) { this.getLastOpenSlider().destroy(); } if (sliderToDestroy !== null) { const openSliders = this.getOpenSliders(); for (let i = openSliders.length - 1; i >= 0; i--) { const slider = openSliders[i]; slider.destroy(); if (slider === sliderToDestroy) { break; } } } } reload(): void { const topSlider = this.getTopSlider(); if (topSlider) { topSlider.reload(); } } getTopSlider(): Slider { const count = this.openSliders.length; return this.openSliders[count - 1] || null; } getPreviousSlider(currentSlider?: Slider): Slider | null { let previousSlider = null; const openSliders = this.getOpenSliders(); currentSlider = currentSlider || this.getTopSlider(); for (let i = openSliders.length - 1; i >= 0; i--) { const slider = openSliders[i]; if (slider === currentSlider) { previousSlider = openSliders[i - 1] || null; break; } } return previousSlider; } getSlider(sliderUrl: string): Slider | null { const url = this.refineUrl(sliderUrl); const openSliders = this.getOpenSliders(); for (const slider of openSliders) { if (slider.getUrl() === url) { return slider; } } return null; } getSliderByWindow(window: Window): Slider | null { const openSliders = this.getOpenSliders(); for (const slider of openSliders) { if (slider.getFrameWindow() === window) { return slider; } } return null; } getOpenSliders(): Slider[] { return this.openSliders; } getOpenSlidersCount(): number { return this.openSliders.length; } /** * @private */ #addOpenSlider(slider: Slider): void { if (!(slider instanceof Slider)) { throw new TypeError('Slider is not an instance of BX.SidePanel.Slider'); } this.openSliders.push(slider); } /** * @private */ #removeOpenSlider(slider): boolean { const openSliders = [...this.getOpenSliders()]; for (const [i, openSlider] of openSliders.entries()) { if (openSlider === slider) { this.openSliders.splice(i, 1); return true; } } return false; } getLastOpenSlider(): Slider | null { return this.lastOpenSlider; } #setLastOpenSlider(slider: Slider): void { if (this.lastOpenSlider !== slider) { if (this.lastOpenSlider) { this.lastOpenSlider.destroy(); } this.lastOpenSlider = slider; } } #resetLastOpenSlider(): void { if (this.lastOpenSlider && this.getTopSlider() !== this.lastOpenSlider) { this.lastOpenSlider.destroy(); } this.lastOpenSlider = null; } adjustLayout(): void { this.getOpenSliders().forEach((slider: Slider) => { slider.adjustLayout(); }); } createToolbar(options): Toolbar { if (this.toolbar === null) { this.toolbar = new Toolbar(options); } return this.toolbar; } getToolbar(): Toolbar { return this.toolbar; } #getLastOffset(): number | null { const openSliders = this.getOpenSliders(); for (let i = openSliders.length - 1; i >= 0; i--) { const slider = openSliders[i]; if (slider.getOffset() !== null) { return slider.getOffset(); } } return null; } refineUrl(url: string): string { if (Type.isStringFilled(url) && /IFRAME/.test(url)) { return Uri.removeParam(url, ['IFRAME', 'IFRAME_TYPE']); } return url; } getPageUrl(): string { return this.pageUrl; } getCurrentUrl(): string { return window.location.pathname + window.location.search + window.location.hash; } getPageTitle(): string { return this.pageTitle; } getCurrentTitle(): string { let title = document.title; if (!Type.isUndefined(window.BXIM)) { title = title.replace(/^\(\d+\) /, ''); // replace a messenger counter. } return title; } enterFullScreen() { if (!this.getTopSlider() || this.getFullScreenSlider()) { return; } const container = document.body; if (container.requestFullscreen) { Event.bind(document, 'fullscreenchange', this.handleFullScreenChange); container.requestFullscreen(); } else if (container.webkitRequestFullScreen) { Event.bind(document, 'webkitfullscreenchange', this.handleFullScreenChange); container.webkitRequestFullScreen(); } else if (container.msRequestFullscreen) { Event.bind(document, 'MSFullscreenChange', this.handleFullScreenChange); container.msRequestFullscreen(); } else if (container.mozRequestFullScreen) { Event.bind(document, 'mozfullscreenchange', this.handleFullScreenChange); container.mozRequestFullScreen(); } else { console.log('Slider: Full Screen mode is not supported.'); } } exitFullScreen() { if (!this.getFullScreenSlider()) { return; } if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } } getFullScreenElement(): HTMLElement { return ( document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement || null ); } getFullScreenSlider(): Slider | null { return this.fullScreenSlider; } handleFullScreenChange(event): void { if (this.getFullScreenElement()) { this.fullScreenSlider = this.getTopSlider(); Dom.addClass(this.fullScreenSlider.getOverlay(), 'side-panel-fullscreen'); this.fullScreenSlider.fireEvent('onFullScreenEnter'); } else { if (this.getFullScreenSlider()) { Dom.removeClass(this.getFullScreenSlider().getOverlay(), 'side-panel-fullscreen'); this.fullScreenSlider.fireEvent('onFullScreenExit'); this.fullScreenSlider = null; } Event.unbind(document, event.type, this.handleFullScreenChange); window.scrollTo(0, this.pageScrollTop); setTimeout(() => { this.adjustLayout(); const resizeEvent = document.createEvent('Event'); resizeEvent.initEvent('resize', true, true); window.dispatchEvent(resizeEvent); }, 1000); } } postMessage(source: string | Window | Slider, eventId: string, data: JsonObject): void { const sender = this.getSliderFromSource(source); if (!sender) { return; } let previousSlider: Slider = null; const openSliders = this.getOpenSliders(); for (let i = openSliders.length - 1; i >= 0; i--) { const slider = openSliders[i]; if (slider === sender) { previousSlider = openSliders[i - 1] || null; break; } } const sliderWindow = previousSlider ? previousSlider.getWindow() : window; sliderWindow.BX.onCustomEvent('Bitrix24.Slider:onMessage', [sender, data]); // Compatibility const event = new MessageEvent({ sender, slider: previousSlider || null, data, eventId, }); if (previousSlider) { previousSlider.firePageEvent(event); previousSlider.fireFrameEvent(event); } else { EventEmitter.emit(event.getFullName().toLowerCase(), new BaseEvent({ data: [event], compatData: [event] })); } } postMessageAll(source: string | Window | Slider, eventId: string, data: JsonObject): void { const sender = this.getSliderFromSource(source); if (!sender) { return; } let event = null; const openSliders = this.getOpenSliders(); for (let i = openSliders.length - 1; i >= 0; i--) { const slider = openSliders[i]; if (slider === sender) { continue; } event = new MessageEvent({ sender, slider, data, eventId }); slider.firePageEvent(event); slider.fireFrameEvent(event); } event = new MessageEvent({ sender, slider: null, data, eventId }); EventEmitter.emit(event.getFullName().toLowerCase(), new BaseEvent({ data: [event], compatData: [event] })); } postMessageTop(source: string | Window | Slider, eventId: string, data: JsonObject): void { const sender = this.getSliderFromSource(source); if (!sender) { return; } const event = new MessageEvent({ sender, slider: null, data, eventId }); EventEmitter.emit(event.getFullName().toLowerCase(), new BaseEvent({ data: [event], compatData: [event] })); } #getMinOffset(): number { return 63; } #getMaxOffset(): number { return this.#getMinOffset() * 3; } bindAnchors(parameters: { rules: RuleOptions[] }) { if (!Type.isPlainObject(parameters) || !Type.isArray(parameters.rules) || parameters.rules.length === 0) { return; } if (this.anchorRules.length === 0) { this.registerAnchorListener(window.document); } if (!(parameters.rules instanceof Object)) { console.error( 'BX.SitePanel: anchor rules were created in a different context. ' + 'This might be a reason for a memory leak.', ); console.trace(); } parameters.rules.forEach((rule) => { if (Type.isArray(rule.condition)) { for (let m = 0; m < rule.condition.length; m++) { if (Type.isString(rule.condition[m])) { rule.condition[m] = new RegExp(rule.condition[m], 'i'); } } } rule.options = Type.isPlainObject(rule.options) ? rule.options : {}; if (Type.isStringFilled(rule.loader) && !Type.isStringFilled(rule.options.loader)) { rule.options.loader = rule.loader; delete rule.loader; } this.anchorRules.push(rule); }); } isAnchorBinding(): boolean { return this.anchorBinding; } enableAnchorBinding(): void { this.anchorBinding = true; } disableAnchorBinding(): void { this.anchorBinding = false; } registerAnchorListener(targetDocument) { Event.bind(targetDocument, 'click', this.handleAnchorClick, true); } unregisterAnchorListener(targetDocument) { Event.unbind(targetDocument, 'click', this.handleAnchorClick, true); } /** * @private */ handleSliderOpenStart(event: SliderEvent) { if (!event.isActionAllowed()) { return; } const slider = event.getSlider(); if (slider.isDestroyed()) { return; } if (this.getTopSlider()) { this.exitFullScreen(); this.getTopSlider().hideOverlay(); slider.setOverlayBackground(); const sameWidth = ( this.getTopSlider().getOffset() === slider.getOffset() && this.getTopSlider().getWidth() === slider.getWidth() && this.getTopSlider().getCustomLeftBoundary() === slider.getCustomLeftBoundary() ); if (!sameWidth) { this.getTopSlider().showShadow(); } this.getTopSlider().hideOrDarkenCloseBtn(); this.getTopSlider().hidePrintBtn(); this.getTopSlider().hideExtraLabels(); } else { slider.setOverlayAnimation(true); } this.#addOpenSlider(slider); this.getOpenSliders().forEach((currentSlider: Slider, index: number, openSliders: Slider[]) => { currentSlider.getLabel().moveAt(openSliders.length - index - 1); // move down }); this.losePageFocus(); if (!this.opened) { this.pageUrl = this.getCurrentUrl(); this.pageTitle = this.getCurrentTitle(); } this.opened = true; this.#resetLastOpenSlider(); } /** * @private */ handleSliderOpenComplete(event: SliderEvent) { this.setBrowserHistory(event.getSlider()); this.updateBrowserTitle(); event.getSlider().setAnimation('sliding'); } /** * @private */ handleSliderCloseStart(event: SliderEvent) { if (!event.isActionAllowed()) { return; } if (event.getSlider() && event.getSlider().isDestroyed()) { return; } const previousSlider = this.getPreviousSlider(); const topSlider = this.getTopSlider(); this.exitFullScreen(); this.getOpenSliders().forEach((slider, index, openSliders) => { slider.getLabel().moveAt(openSliders.length - index - 2); // move up }); if (previousSlider) { previousSlider.unhideOverlay(); previousSlider.hideShadow(); previousSlider.showOrLightenCloseBtn(); if (topSlider) { topSlider.hideOverlay(); topSlider.hideShadow(); } } } handleSliderMaximizeStart(event) { if (!event.isActionAllowed() || this.getToolbar() === null) { return; } const slider = event.getSlider(); if (slider && slider.isDestroyed()) { return; } const { entityType, entityId } = slider.getMinimizeOptions() || {}; const item = this.getToolbar().getItem(entityType, entityId); this.getToolbar().request('maximize', item); const origin = this.#getItemOrigin(slider, item); slider.setAnimation('scale', { origin }); } handleSliderMinimizeStart(event) { if (!event.isActionAllowed() || this.getToolbar() === null) { return; } const slider = event.getSlider(); if (slider && slider.isDestroyed()) { return; } if (!this.getToolbar().isShown()) { this.getToolbar().show(); } let title = slider.getTitle(); if (!title) { title = slider.getFrameWindow() ? slider.getFrameWindow().document.title : null; } this.getToolbar().expand(true); const minimizeOptions = this.getMinimizeOptions(slider.getUrl()); const { entityType, entityId, url } = minimizeOptions || slider.getMinimizeOptions() || {}; const item = this.getToolbar().minimizeItem({ title, url: Type.isStringFilled(url) ? url : slider.getUrl(), entityType, entityId, }); const origin = this.#getItemOrigin(slider, item); slider.setAnimation('scale', { origin }); } #getItemOrigin(slider: Slider, item: ToolbarItem): void { if (item && item.getContainer().offsetWidth > 0) { const rect = item.getContainer().getBoundingClientRect(); const offset = slider.getContainer().getBoundingClientRect().left; const left = rect.left - offset + rect.width / 2; return `${left}px ${rect.top}px`; } return '50% 100%'; } /** * @private */ handleSliderCloseComplete(event: SliderEvent) { const slider = event.getSlider(); if (slider === this.getTopSlider()) { this.#setLastOpenSlider(slider); } event.getSlider().setAnimation('sliding'); this.cleanUpClosedSlider(slider); } /** * @private */ handleSliderDestroy(event: SliderEvent) { const slider = event.getSlider(); EventEmitter.unsubscribe(slider, 'SidePanel.Slider:onOpenStart', this.handleSliderOpenStart); EventEmitter.unsubscribe(slider, 'SidePanel.Slider:onBeforeOpenComplete', this.handleSliderOpenComplete); EventEmitter.unsubscribe(slider, 'SidePanel.Slider:onMaximizeStart', this.handleSliderMaximizeStart); EventEmitter.unsubscribe(slider, 'SidePanel.Slider:onCloseStart', this.handleSliderCloseStart); EventEmitter.unsubscribe(slider, 'SidePanel.Slider:onBeforeCloseComplete', this.handleSliderCloseComplete); EventEmitter.unsubscribe(slider, 'SidePanel.Slider:onMinimizeStart', this.handleSliderMinimizeStart); EventEmitter.unsubscribe(slider, 'SidePanel.Slider:onLoad', this.handleSliderLoad); EventEmitter.unsubscribe(slider, 'SidePanel.Slider:onDestroy', this.handleSliderDestroy); EventEmitter.unsubscribe(slider, 'SidePanel.Slider:onEscapePress', this.handleEscapePress); const frameWindow = event.getSlider().getFrameWindow(); if (frameWindow && !event.getSlider().allowCrossOrigin) { this.unregisterAnchorListener(frameWindow.document); } if (slider === this.getLastOpenSlider()) { this.lastOpenSlider = null; } this.cleanUpClosedSlider(slider); } handleEscapePress(event) { if (this.isOnTop() && this.getTopSlider() && this.getTopSlider().canCloseByEsc()) { this.getTopSlider().close(); } } /** * @private */ cleanUpClosedSlider(slider: Slider) { this.#removeOpenSlider(slider); slider.unhideOverlay(); slider.hideShadow(); this.getOpenSliders().forEach((slider, index, openSliders) => { slider.getLabel().moveAt(openSliders.length - index - 1); //update position }); if (this.getTopSlider()) { this.getTopSlider().showOrLightenCloseBtn(); this.getTopSlider().unhideOverlay(); this.getTopSlider().hideShadow(); this.getTopSlider().showExtraLabels(); if (this.getTopSlider().isPrintable()) { this.getTopSlider().showPrintBtn(); } this.getTopSlider().focus(); } else { window.focus(); } if (!this.getOpenSlidersCount()) { this.resetHacks(slider); this.opened = false; } this.resetBrowserHistory(); this.updateBrowserTitle(); } /** * @private */ handleSliderLoad(event: SliderEvent) { const frameWindow = event.getSlider().getFrameWindow(); if (frameWindow) { this.registerAnchorListener(frameWindow.document); } this.setBrowserHistory(event.getSlider()); this.updateBrowserTitle(); } /** * @private */ handlePostMessageCompatible(source: string | Window | Slider, data: JsonObject) { this.postMessage(source, '', data); } /** * @private */ getSliderFromSource(source: string | Window | Slider) { if (source instanceof Slider) { return source; } if (Type.isStringFilled(source)) { return this.getSlider(source); } if (source !== null && source === source.window && window !== source) { return this.getSliderByWindow(source); } return null; } /** * @private */ applyHacks(slider: Slider): boolean { if (this.hacksApplied) { return false; } if (slider) { slider.applyHacks(); } this.disablePageScrollbar(); this.bindEvents(); if (slider) { slider.applyPostHacks(); } this.hacksApplied = true; return true; } /** * @private */ resetHacks(slider: Slider): boolean { if (!this.hacksApplied) { return false; } if (slider) { slider.resetPostHacks(); } this.enablePageScrollbar(); this.unbindEvents(); if (slider) { slider.resetHacks(); } this.hacksApplied = false; return true; } /** * @private */ bindEvents(): boolean { Event.bind(document, 'keydown', this.handleDocumentKeyDown); Event.bind(window, 'resize', this.handleWindowResize); Event.bind(window, 'scroll', this.handleWindowScroll); // Live Comments can change scrollTop if (Browser.isMobile()) { Event.bind(document.body, 'touchmove', this.handleTouchMove); } } /** * @private */ unbindEvents() { Event.unbind(document, 'keydown', this.handleDocumentKeyDown); Event.unbind(window, 'resize', this.handleWindowResize); Event.unbind(window, 'scroll', this.handleWindowScroll); if (Browser.isMobile()) { Event.unbind(document.body, 'touchmove', this.handleTouchMove); } } /** * @private */ disablePageScrollbar(): void { const scrollWidth = window.innerWidth - document.documentElement.clientWidth; document.body.style.paddingRight = scrollWidth + 'px'; Dom.style(document.body, '--scroll-shift-width', `${scrollWidth}px`); Dom.addClass(document.body, 'side-panel-disable-scrollbar'); this.pageScrollTop = window.pageYOffset || document.documentElement.scrollTop; } /** * @private */ enablePageScrollbar() { document.body.style.removeProperty('padding-right'); Dom.style(document.body, '--scroll-shift-width', null); Dom.removeClass(document.body, 'side-panel-disable-scrollbar'); } /** * @private */ losePageFocus() { if (Type.isDomNode(document.activeElement)) { document.activeElement.blur(); } } /** * @private * @param {Event} event */ handleDocumentKeyDown(event: KeyboardEvent) { if (event.keyCode !== 27) { return; } event.preventDefault(); // otherwise an iframe loading can be cancelled by a browser if (this.isOnTop() && this.getTopSlider() && this.getTopSlider().canCloseByEsc()) { this.getTopSlider().close(); } } /** * @private */ handleWindowResize() { this.adjustLayout(); } /** * @private */ handleWindowScroll() { window.scrollTo(0, this.pageScrollTop); this.adjustLayout(); } /** * @private * @param {Event} event */ handleTouchMove(event) { event.preventDefault(); } /** * @private */ isOnTop(): boolean { // Photo Slider or something else can cover Side Panel. const centerX = document.documentElement.clientWidth / 2; const centerY = document.documentElement.clientHeight / 2; const element = document.elementFromPoint(centerX, centerY); return Dom.hasClass(element, 'side-panel') || element.closest('.side-panel') !== null; } /** * @private */ extractLinkFromEvent(event: MouseEvent): LinkOptions | null { const target: HTMLElement = event.target; if (event.which !== 1 || !Type.isDomNode(target) || event.ctrlKey || event.metaKey) { return null; } let a = target; if (target.nodeName !== 'A' && Type.isElementNode(target)) { a = target.closest('a'); } if (!Type.isDomNode(a)) { return null; } // do not use a.href here, the code will fail on links like <a href="#SG13"></a> const href = a.getAttribute('href'); if (href) { return { url: href, anchor: a, target: a.getAttribute('target'), }; } return null; } /** * @private * @param {MouseEvent} event */ handleAnchorClick(event) { if (!this.isAnchorBinding()) { return; } const link = this.extractLinkFromEvent(event); if (!link || Dom.attr(link.anchor, 'data-slider-ignore-autobinding') !== null) { return; } if (Dom.attr(event.target, 'data-slider-ignore-autobinding') !== null) { return; } const rule = this.getUrlRule(link.url, link); if (!this.isValidLink(rule, link)) { return; } if (Type.isFunction(rule.handler)) { rule.handler(event, link); } else { event.preventDefault(); this.open(link.url, rule.options); } } /** * @public * @param {string} url */ emulateAnchorClick(url) { const link = { url, anchor: null, target: null, }; const rule = this.getUrlRule(url, link); if (!this.isValidLink(rule, link)) { BX.reload(url); } else if (Type.isFunction(rule.handler)) { rule.handler( new Event( 'slider', { bubbles: false, cancelable: true, }, ), link, ); } else { this.open(link.url, rule.options); } } /** * @private */ getUrlRule(href: string, link: LinkOptions): RuleOptions | null { if (!Type.isStringFilled(href)) { return null; } if (!Type.isPlainObject(link)) { const a = document.createElement('a'); a.href = href; link = { url: href, anchor: a, target: '' }; } for (let k = 0; k < this.anchorRules.length; k++) { const rule = this.anchorRules[k]; if (!Type.isArray(rule.condition)) { continue; } for (let m = 0; m < rule.condition.length; m++) { const matches = href.match(rule.condition[m]); if (matches && !this.hasStopParams(href, rule.stopParameters)) { link.matches = matches; const minimizeOptions = Type.isFunction(rule.minimizeOptions) ? rule.minimizeOptions(link) : null; if (Type.isPlainObject(minimizeOptions)) { if (Type.isPlainObject(rule.options)) { rule.options.minimizeOptions = minimizeOptions; } else { rule.options = { minimizeOptions }; } } return rule; } } } return null; } /** * @private */ isValidLink(rule: RuleOptions, link: LinkOptions): boolean { if (!rule) { return false; } if (rule.allowCrossDomain !== true && Ajax.isCrossDomain(link.url)) { return false; } if (rule.mobileFriendly !== true && Browser.isMobile()) { return false; } return !Type.isFunction(rule.validate) || rule.validate(link); } /** * @private * @param {BX.SidePanel.Slider} slider */ setBrowserHistory(slider) { if (!(slider instanceof Slider)) { return; } if (slider.canChangeHistory() && slider.isOpen() && slider.isLoaded()) { window.history.replaceState({}, '', slider.getUrl()); } } /** * @private */ resetBrowserHistory() { let topSlider = null; const openSliders = this.getOpenSliders(); for (let i = openSliders.length - 1; i >= 0; i--) { const slider = openSliders[i]; if (slider.canChangeHistory() && slider.isOpen() && slider.isLoaded()) { topSlider = slider; break; } } const url = topSlider ? topSlider.getUrl() : this.getPageUrl(); if (url) { window.history.replaceState({}, '', url); } } /** * @public */ updateBrowserTitle() { let title = null; const openSliders = this.getOpenSliders(); for (let i = openSliders.length - 1; i >= 0; i--) { title = this.getBrowserTitle(openSliders[i]); if (Type.isStringFilled(title)) { break; } } if (Type.isStringFilled(title)) { document.title = title; this.titleChanged = true; } else if (this.titleChanged) { document.title = this.getPageTitle(); this.titleChanged = false; } } /** * @private */ getBrowserTitle(slider: Slider): string | null { if (!slider || !slider.canChangeTitle() || !slider.isOpen() || !slider.isLoaded()) { return null; } let title = slider.getTitle(); if (!title && !slider.isSelfContained()) { title = slider.getFrameWindow() ? slider.getFrameWindow().document.title : null; } return Type.isStringFilled(title) ? title : null; } /** * @private */ hasStopParams(url: string, params: string[]): boolean { if (!params || !Type.isArray(params) || !Type.isStringFilled(url)) { return false; } const questionPos = url.indexOf('?'); if (questionPos === -1) { return false; } const query = url.slice(Math.max(0, questionPos)); for (const param of params) { if (new RegExp(`[?&]${param}=`, 'i').test(query)) { return true; } } return false; } /** * @deprecated use getLastOpenSlider method */ getLastOpenPage(): Slider | null { return this.getLastOpenSlider(); } /** * @deprecated use getTopSlider method */ getCurrentPage(): Slider | null { return this.getTopSlider(); } }