function debugLog(string) { //iBooks.log(string); } function debugLogError(error) { debugLog("ERROR: " + error.name + ", " + error.message); //window.alert("ERROR: " + error.name + ", " + error.message); } function debugAssert(condition, messqge) { if (!condition) { debugLog("ASSERT FAILED: " + messqge); } } function dumpObject(object, name) { debugLog(name + " BEGIN"); if (!object) { debugLog("NULL"); } for (var property in object) { try { var value = object[property]; var type = typeof(value); if (type != 'function') { debugLog(type + " " + property + " " + value); } } catch (error) { debugLog(property +" "+error); } } debugLog(name + " END"); } function dumpEpubReadingSystemFeatures() { debugLog("epubReadingSystem FEATURES BEGIN"); if (navigator.epubReadingSystem) { var featureArray = ["dom-manipulation", "layout-changes", "touch-events", "mouse-events", "keyboard-events", "spine-scripting"]; featureArray.forEach(function(feature) { var supported = navigator.epubReadingSystem.hasFeature(feature); debugLog(feature +":"+ supported); }); } debugLog("epubReadingSystem FEATURES END"); } function isKobo() { return 'koboApp' in window; } function isADE() { var epubReadingSystem = navigator.epubReadingSystem; if (epubReadingSystem) { return epubReadingSystem.name == 'RMSDK'; } return false; } function isIOS() { var platform = navigator.platform; if (["iPad", "iPod", "iPhone"].includes(platform)) { return true; } return false; } function useMouselessButtons() { return (isADE() || isKobo()) && isIOS(); } function stringForRect (rect) { return "{ " + rect.left + ", " + rect.top + ", " + rect.width + ", " + rect.height + " }"; } function stringForEventTargetElement(target) { return "{tag:" + target.tagName + ";class:" + target.className + ";ID:" + target.id + "}"; } function dumpEvent (event) { //event.type; //event.target; //event.currentTarget; } function dumpMouseEvent (event) { /* debugLog(""); debugLog(event.type); debugLog("client = " + event.clientX + ", " + event.clientY); debugLog("layer = " + event.layerX + ", " + event.layerY); debugLog("movement = " + event.movementX + ", " + event.movementY); debugLog("offset = " + event.offsetX + ", " + event.offsetY); debugLog("screen = " + event.screenX + ", " + event.screenY); debugLog("plain = " + event.x + ", " + event.y); debugLog(""); */ } function dumpTouch(touch) { debugLog(" touch: " + "ID:" + touch.identifier + ";page:"+touch.pageX+","+touch.pageY+";radius:"+touch.radiusX+","+touch.radiusY+";rotation:"+touch.rotationAngle+";force:"+touch.force+";altitude:"+touch.altitudeAngle+";azimuth:"+touch.azimuthAngle + ";target:" + stringForEventTargetElement(touch.target)+";"); } function dumpTouchList(touchListName, touchList) { if (touchList) { var count = touchList.length; debugLog(" "+touchListName + " (" + count +")"); for (var index = 0; index < count; index++) { dumpTouch(touchList.item(index)); } } } function dumpTouchEvent(event) { debugLog("event:"+event.type+";page:"+event.pageX+","+event.pageY+";scale:"+event.scale+";rotation:"+event.rotation+";target:"+stringForEventTargetElement(event.target)+";currentTarget:"+stringForEventTargetElement(event.currentTarget)+";"); dumpTouchList("touches", event.touches); dumpTouchList("targetTouches", event.targetTouches); dumpTouchList("changedTouches", event.changedTouches); } function stopEventPropagation(event) { event.stopPropagation(); } const ViewfinderAction = { none : -1, maximize : 0, goToPrev : 1, goToNext : 2, count : 3 }; class GalleryViewfinderObserver { constructor(owner) { this.owner = owner; this.galleryObject = owner.galleryObject; this.galleryElement = owner.galleryElement; this.viewfinderElement = owner.viewfinderElement; } onCurrentItemChange(oldItemIndex, newItemIndex) {} onMouseMoveInViewfinder(point) { } onMouseEnterViewfinder(point) { } onMouseLeaveViewfinder(point) { } onClickInViewfinder(point) { } onPageShow() { } onPageHide() { } onMouseEnterViewfinderChild(viewfinderChildElement) { } onMouseLeaveViewfinderChild(viewfinderChildElement) { } } class GalleryButtonsViewfinderManager extends GalleryViewfinderObserver { constructor(owner) { super(owner); var viewfinderElement = this.viewfinderElement; this.goToPrevButtonElement = viewfinderElement.getElementsByClassName("gallery-button-goToPrev")[0]; this.goToNextButtonElement = viewfinderElement.getElementsByClassName("gallery-button-goToNext")[0]; this.maximizeButtonElement = viewfinderElement.getElementsByClassName("gallery-button-maximize")[0]; this.buttonsTimeout = null; this.buttonUnderMouseCursor = null; this.setButtonMouseEnterLeaveHandlers(this.goToPrevButtonElement); this.setButtonFocusHandlers(this.goToPrevButtonElement); this.setButtonKeyupHandlers(this.goToPrevButtonElement); this.setButtonMouseEnterLeaveHandlers(this.goToNextButtonElement); this.setButtonFocusHandlers(this.goToNextButtonElement); this.setButtonKeyupHandlers(this.goToNextButtonElement); if (this.maximizeButtonElement) { this.setButtonMouseEnterLeaveHandlers(this.maximizeButtonElement); this.setButtonFocusHandlers(this.maximizeButtonElement); } } handleNextPreviousButtonKeyUpEvent(e) { var movePrevious = false; var moveNext = false; if (e.keyCode == 13 || e.keyCode == 32) /* Spacebar or Enter */ { e.preventDefault(); if (e.target == this.goToPrevButtonElement) { movePrevious = true; } else if(e.target == this.goToNextButtonElement) { moveNext = true; } } else if (e.keyCode == 37) /* Left Arrow */ { movePrevious = true; } else if (e.keyCode == 39) /* Right Arrow */ { moveNext = true; } if (movePrevious) { if (this.galleryObject.currentItemIndex > 0) { this.galleryObject.goToPrevFrame(); if (this.galleryObject.currentItemIndex == 0) { this.goToNextButtonElement.focus(); } } } if (moveNext) { if (this.galleryObject.currentItemIndex < this.galleryObject.itemCount - 1) { this.galleryObject.goToNextFrame(); if (this.galleryObject.currentItemIndex == this.galleryObject.itemCount - 1) { this.goToPrevButtonElement.focus(); } } } if (movePrevious || moveNext) { this.updateButtonsDisplayState(); } } setButtonMouseEnterLeaveHandlers(buttonElement) { buttonElement.onmouseenter = this.onMouseEnterButton.bind(this, buttonElement); buttonElement.onmouseleave = this.onMouseLeaveButton.bind(this, buttonElement); } setButtonFocusHandlers(buttonElement) { buttonElement.onfocus = this.onButtonGainedFocus.bind(this, buttonElement); buttonElement.onblur = this.onButtonLostFocus.bind(this, buttonElement); } setButtonKeyupHandlers(buttonElement) { buttonElement.onkeyup = this.handleNextPreviousButtonKeyUpEvent.bind(this); } setButtonsVisibility(showPrev, showNext, showMaximize) { Gallery.setButtonVisibility(this.goToPrevButtonElement, showPrev); Gallery.setButtonVisibility(this.goToNextButtonElement, showNext); Gallery.setButtonVisibility(this.maximizeButtonElement, showMaximize); } hideButtonsNotUnderMouseCursor() { var showPrev = this.buttonUnderMouseCursor == this.goToPrevButtonElement; var showNext = this.buttonUnderMouseCursor == this.goToNextButtonElement; var showMaximize = this.buttonUnderMouseCursor == this.maximizeButtonElement; this.setButtonsVisibility(showPrev, showNext, showMaximize); } startButtonsTimeout() { this.buttonsTimeout = setTimeout(function() { this.hideButtonsNotUnderMouseCursor() }.bind(this), 2500); } killButtonsTimeout() { if (this.buttonsTimeout) { clearTimeout(this.buttonsTimeout); this.buttonsTimeout = null; } } hideButtonsWithoutDelay() { this.killButtonsTimeout(); this.setButtonsVisibility(false, false, false); } viewfinderActionForMousePosition(point) { var itemCount = this.galleryObject.itemCount; var currentItemIndex = this.galleryObject.currentItemIndex; var viewfinderWidth = this.viewfinderElement.getBoundingClientRect().width; var x = point.x; const adjacentSlideActiveMargin = 0.2; if (currentItemIndex > 0) { if (x < adjacentSlideActiveMargin * viewfinderWidth) { return ViewfinderAction.goToPrev; } } var showNext = false; if (currentItemIndex + 1 < itemCount) { if (viewfinderWidth - x < adjacentSlideActiveMargin * viewfinderWidth) { return ViewfinderAction.goToNext; } } if (this.maximizeButtonElement) { return ViewfinderAction.maximize; } return ViewfinderAction.none; } updateButtonsVisibility(point) { var action = this.viewfinderActionForMousePosition(point); var showPrev = action == ViewfinderAction.goToPrev; var showNext = action == ViewfinderAction.goToNext; var showMaximize = true; if (!this.maximizeButtonElement) { this.viewfinderElement.style.cursor = (showPrev || showNext) ? 'pointer' : 'default'; } this.setButtonsVisibility(showPrev, showNext, showMaximize); this.updateButtonsDisplayState(); } updateButtonsDisplayState() { // Update display style of the next/previous buttons so that they are present/removed from the // focus loop at the correct indexes. var itemCount = this.galleryObject.itemCount; var currentIndex = this.galleryObject.currentItemIndex; if (currentIndex == 0) { this.goToPrevButtonElement.tabIndex = -1; this.goToPrevButtonElement.style.display = 'none'; } else { this.goToPrevButtonElement.tabIndex = 0; this.goToPrevButtonElement.style.display = 'block'; } if (currentIndex == itemCount - 1) { this.goToNextButtonElement.tabIndex = -1; this.goToNextButtonElement.style.display = 'none'; } else { this.goToNextButtonElement.tabIndex = 0; this.goToNextButtonElement.style.display = 'block'; } } onMouseMoveInViewfinder(point) { this.killButtonsTimeout(); this.updateButtonsVisibility(point); this.startButtonsTimeout(); } onMouseEnterViewfinder(point) { debugAssert(this.buttonsTimeout == null, "buttonsTimeout not null on onMouseEnterViewfinder"); } onMouseLeaveViewfinder(point) { this.hideButtonsWithoutDelay(); } onClickInViewfinder(point) { this.killButtonsTimeout(); var action = this.viewfinderActionForMousePosition(point); switch (action) { case ViewfinderAction.goToPrev: this.galleryObject.goToPrevFrame(); break; case ViewfinderAction.goToNext: this.galleryObject.goToNextFrame(); break; case ViewfinderAction.maximize: if (this.maximizeButtonElement) { this.galleryObject.maximizeFrame(); } break; } this.updateButtonsVisibility(point); this.startButtonsTimeout(); } onPageShow() { this.hideButtonsWithoutDelay(); } onPageHide() { this.hideButtonsWithoutDelay(); } onMouseEnterButton(buttonElement) { this.buttonUnderMouseCursor = buttonElement; } onMouseLeaveButton(buttonElement) { this.buttonUnderMouseCursor = null; } onButtonGainedFocus(buttonElement) { Gallery.setButtonVisibility(buttonElement, true); } onButtonLostFocus(buttonElement) { Gallery.setButtonVisibility(buttonElement, false); } } class GalleryCurrentItemObserver { constructor(galleryObject) { this.galleryObject = galleryObject; } onCurrentItemChange(oldItemIndex, newItemIndex, animate) { } } class GalleryImageRollManager { constructor(galleryObject) { this.galleryObject = galleryObject; this.rollElement = galleryObject.galleryElement.getElementsByClassName("gallery-image-roll")[0]; } removeTransition() { this.rollElement.classList.remove("gallery-image-roll-transition") } onCurrentItemChange(oldItemIndex, newItemIndex, animate) { this.removeTransition(); if (animate) { this.rollElement.classList.add("gallery-image-roll-transition"); this.rollElement.addEventListener("transitionend", this.removeTransition.bind(this)); } this.rollElement.style.left = -(newItemIndex * 100) + "%"; } } class GalleryCaptionRollManager extends GalleryCurrentItemObserver { constructor(galleryObject) { super(galleryObject); this.rollElement = galleryObject.galleryElement.getElementsByClassName("gallery-caption-roll")[0]; this.initializeCaptionIDs(); } getFirstParagraphElementOfCaption(caption) { var paragraphTagNameArray = ["p", "li" ]; for (var index = 0; index < paragraphTagNameArray.length; index++) { var paragraphTagName = paragraphTagNameArray[index]; var paragraphElementList = caption.getElementsByTagName(paragraphTagName); if (paragraphElementList.length > 0) { return paragraphElementList[0]; } } // no paragraphs/list items return null; } initializeCaptionIDs() { var captions = Array.prototype.slice.call(this.rollElement.getElementsByClassName("gallery-caption")); var galleryObject = this.galleryObject; captions.forEach(function(caption, index) { var captionTextElement = this.getFirstParagraphElementOfCaption(caption); if (captionTextElement) { captionTextElement.id = galleryObject.getCaptionElementIDForIndex(index); } }, this); } onCurrentItemChange(oldItemIndex, newItemIndex, animate) { this.rollElement.style.left = -(newItemIndex * 100) + "%"; var captions = Array.prototype.slice.call(this.rollElement.getElementsByClassName("gallery-caption")); captions.forEach(function(caption, index) { var captionTextElement = this.getFirstParagraphElementOfCaption(caption); if (captionTextElement) { captionTextElement.setAttribute("aria-hidden", newItemIndex == index ? "false" : "true"); } }, this); } } class GalleryDotManager extends GalleryCurrentItemObserver { constructor(galleryObject) { super(galleryObject); this.dotContainerElement = galleryObject.galleryElement.getElementsByClassName("gallery-dot-container")[0]; this.setupDotElementKeyupHandlers(); } setupDotElementKeyupHandlers() { var dotElements = Array.prototype.slice.call(this.dotContainerElement.getElementsByClassName("gallery-dot-selectable")); dotElements.concat(Array.prototype.slice.call(this.dotContainerElement.getElementsByClassName("gallery-dot-current"))); var handler = this.handleDotElementKeyUpEvent.bind(this); dotElements.forEach(function(dotElement) { dotElement.onkeyup = handler; }); } handleDotElementKeyUpEvent(e) { var element = e.target; var currentIndex = this.galleryObject.currentItemIndex; var itemCount = this.galleryObject.itemCount; if (e.keyCode == 37) /* Left Arrow */ { if (currentIndex > 0) { this.galleryObject.goToPrevFrame(); var selectedDotElement = Array.prototype.slice.call(this.dotContainerElement.getElementsByClassName("gallery-dot-current"))[0]; selectedDotElement.focus(); } } else if (e.keyCode == 39) /* Right Arrow */ { if (currentIndex < itemCount - 1) { this.galleryObject.goToNextFrame(); var selectedDotElement = Array.prototype.slice.call(this.dotContainerElement.getElementsByClassName("gallery-dot-current"))[0]; selectedDotElement.focus(); } } } deselectCurrentDot() { var currentDotGroupCollection = this.dotContainerElement.getElementsByClassName("gallery-dot-current"); if (currentDotGroupCollection.length > 0) { currentDotGroupCollection[0].setAttribute("aria-checked", "false"); currentDotGroupCollection[0].tabIndex = -1; currentDotGroupCollection[0].className = "gallery-dot-selectable"; } } onCurrentItemChange(oldItemIndex, newItemIndex, animate) { this.deselectCurrentDot(); var selectableDotGroupCollection = this.dotContainerElement.getElementsByClassName("gallery-dot-selectable"); selectableDotGroupCollection[newItemIndex].setAttribute("aria-checked", "true"); selectableDotGroupCollection[newItemIndex].tabIndex = 0; selectableDotGroupCollection[newItemIndex].className = "gallery-dot-current"; } } class GalleryMouselessButtonsManager extends GalleryCurrentItemObserver { constructor(galleryObject) { super(galleryObject); var viewfinderElement = galleryObject.viewfinderElement; this.goToPrevButtonElement = viewfinderElement.getElementsByClassName("gallery-button-goToPrev")[0]; this.goToPrevButtonElement.onclick = galleryObject.goToPrevFrame.bind(galleryObject); this.goToPrevButtonElement.onkeyup = this.handleNextPreviousButtonKeyUpEvent; this.goToNextButtonElement = viewfinderElement.getElementsByClassName("gallery-button-goToNext")[0]; this.goToNextButtonElement.onclick = galleryObject.goToNextFrame.bind(galleryObject); this.goToNextButtonElement.onkeyup = this.handleNextPreviousButtonKeyUpEvent; this.maximizeButtonElement = viewfinderElement.getElementsByClassName("gallery-button-maximize")[0]; if (this.maximizeButtonElement) { this.maximizeButtonElement.onclick = galleryObject.maximizeFrame.bind(galleryObject); } } onCurrentItemChange(oldItemIndex, newItemIndex, animate) { var itemCount = this.galleryObject.itemCount; var showNext = newItemIndex + 1 < this.galleryObject.itemCount; var showPrev = newItemIndex > 0; Gallery.setButtonVisibility(this.goToPrevButtonElement, showPrev); Gallery.setButtonVisibility(this.goToNextButtonElement, showNext); Gallery.setButtonVisibility(this.maximizeButtonElement, true); } } class GalleryViewfinderManager { addViewfinderHandlers() { this.viewfinderElement.onclick = this.onClickInViewfinder.bind(this); this.viewfinderElement.onmouseenter = this.onMouseEnterViewfinder.bind(this); this.viewfinderElement.onmouseleave = this.onMouseLeaveViewfinder.bind(this); this.viewfinderElement.onmousemove = this.onMouseMoveInViewfinder.bind(this); } addObservers() { this.viewfinderObserverArray = []; if (!useMouselessButtons()) { this.viewfinderObserverArray.push(new GalleryButtonsViewfinderManager(this)); } } constructor (galleryObject) { this.galleryObject = galleryObject; this.galleryElement = galleryObject.galleryElement; this.viewfinderElement = this.galleryElement.getElementsByClassName("gallery-image-viewfinder")[0]; this.addViewfinderHandlers(); this.addObservers(); } viewfinderMouseEventCoordinates(event) { var viewfinderBounds = this.viewfinderElement.getBoundingClientRect(); var point = { "x" : event.clientX - viewfinderBounds.left, "y" : event.clientY - viewfinderBounds.top }; return point; } onMouseEventInViewfinder(event, handlerName) { try { //dumpMouseEvent(event); var point = this.viewfinderMouseEventCoordinates(event); this.viewfinderObserverArray.forEach(function (observer) { observer[handlerName](point); }); stopEventPropagation(event); } catch (error) { debugLogError(error); } } onMouseMoveInViewfinder(event) { this.onMouseEventInViewfinder(event, "onMouseMoveInViewfinder"); } onMouseEnterViewfinder(event) { this.onMouseEventInViewfinder(event, "onMouseEnterViewfinder"); } onMouseLeaveViewfinder(event) { this.onMouseEventInViewfinder(event, "onMouseLeaveViewfinder"); } onClickInViewfinder(event) { this.onMouseEventInViewfinder(event, "onClickInViewfinder"); } onPageShow() { this.viewfinderObserverArray.forEach(function (observer) { observer.onPageShow(); }); } onPageHide() { this.viewfinderObserverArray.forEach(function (observer) { observer.onPageHide(); }); } onCurrentItemChange(oldItemIndex, newItemIndex) { this.viewfinderObserverArray.forEach(function(observer) { observer.onCurrentItemChange(oldItemIndex, newItemIndex); }); } } class TouchManager { constructor(galleryObject) { this.galleryObject = galleryObject; this.viewfinderElement = galleryObject.viewfinderElement; //debugLog("Create TouchManager"); var element = this.viewfinderElement; //debugLog("viewfinderElement = " + element); element.addEventListener("touchstart", this.onTouchStart.bind(this), true); element.addEventListener("touchmove", this.onTouchMove.bind(this), true); element.addEventListener("touchend", this.onTouchEnd.bind(this), true); element.addEventListener("touchcancel", this.onTouchCancel.bind(this), true); } viewfinderTouchEventCoordinates(event) { var viewfinderBounds = this.viewfinderElement.getBoundingClientRect(); var point = { "x" : event.pageX - viewfinderBounds.left, "y" : event.pageY - viewfinderBounds.top }; //debugLog("touch point x:"+point.x+", y:"+point.y+""); return point; } onTouchEvent(event) { //dumpTouchEvent(event); stopEventPropagation(event); event.preventDefault(); } onTouchStart(event) { try { this.onTouchEvent(event); this.frameWidth = this.viewfinderElement.getBoundingClientRect().width; this.dragStartPoint = this.viewfinderTouchEventCoordinates(event); this.dragStartTime = new Date().getTime(); this.dragStartX = this.dragStartPoint.x; this.dragStartItemIndex = this.galleryObject.currentItemIndex; debugLog("onTouchStart: frameWidth:"+this.frameWidth+";dragStartItemIndex:"+this.dragStartItemIndex+";dragStartX:"+this.dragStartX); } catch (error) { debugLogError(error); } } onTouchMove(event) { try { this.onTouchEvent(event); var dragCurrX = this.viewfinderTouchEventCoordinates(event).x; var deltaX = dragCurrX - this.dragStartX; var relativeDeltaX = deltaX / this.frameWidth; var newItemIndex = this.dragStartItemIndex - relativeDeltaX; debugLog("onTouchMove: frameWidth:"+this.frameWidth+";dragStartItemIndex:"+this.dragStartItemIndex+";dragStartX:"+this.dragStartX+";dragCurrX:"+dragCurrX+";deltaX:"+deltaX+";relativeDeltaX:"+relativeDeltaX+";newItemIndex:"+newItemIndex+"this.galleryObject.currentItemIndex:" + this.galleryObject.currentItemIndex); if (newItemIndex >= 0 && newItemIndex <= this.galleryObject.itemCount - 1) { this.galleryObject.changeCurrentItemIndex(newItemIndex, false); } } catch (error) { debugLogError(error); } } onTouchEnd(event) { try { this.onTouchEvent(event); var dragEndPoint = this.viewfinderTouchEventCoordinates(event); var dragEndTime = new Date().getTime(); var endItemIndex = this.galleryObject.currentItemIndex; var intEndItemIndex = Math.round(endItemIndex); var deltaT = dragEndTime - this.dragStartTime; // If duration short enough. if (deltaT < 250) { // If it hasn't resulted in a current item change. if (intEndItemIndex == this.dragStartItemIndex) { var absDeltaX = Math.abs(dragEndPoint.x-this.dragStartPoint.x); var absDeltaY = Math.abs(dragEndPoint.y-this.dragStartPoint.y); // If absDeltaX is not trivially small // and absDeltaY is no larger than a fraction of absDeltaX. if (absDeltaX >= 50 && absDeltaY <= 0.4 * absDeltaX) { if (endItemIndex > intEndItemIndex) { if (intEndItemIndex < this.galleryObject.itemCount - 1) { intEndItemIndex++; } } else if (endItemIndex < intEndItemIndex) { if (intEndItemIndex > 0) { intEndItemIndex--; } } } } } debugLog("onTouchEnd: deltaT:"+deltaT+";deltaX="+(dragEndPoint.x-this.dragStartPoint.x)+";deltaY="+(dragEndPoint.y-this.dragStartPoint.y)+";endItemIndex="+endItemIndex+";intEndItemIndex="+intEndItemIndex); this.galleryObject.changeCurrentItemIndex(intEndItemIndex, true); this.dragStartPoint = undefined; this.dragStartTime = undefined; this.dragStartX = undefined; this.dragStartItemIndex = undefined; } catch (error) { debugLogError(error); } } onTouchCancel(event) { try { this.onTouchEvent(event); } catch (error) { debugLogError(error); } } } class Gallery { createImageRollElement() { this.viewfinderElement = this.galleryElement.getElementsByClassName("gallery-image-viewfinder")[0]; this.imageRollElement = this.viewfinderElement.getElementsByClassName("gallery-image-roll")[0]; var imageFrameElementArray = Array.prototype.slice.call(this.viewfinderElement.getElementsByClassName("gallery-image-cropper")); this.itemCount = imageFrameElementArray.length; } completeItemCaptionElements() { //this.itemCaptionRolodexElement = this.galleryElement.getElementsByClassName("gallery-item-caption-rolodex")[0]; //this.itemCaptionRolodexElement.onclick = stopEventPropagation; } addSelectionDots() { this.dotContainerElement = this.galleryElement.getElementsByClassName("gallery-dot-container")[0]; this.innerDotContainerElement = this.dotContainerElement.getElementsByClassName("gallery-dot-inner-container")[0]; if (this.innerDotContainerElement.getBoundingClientRect().width < this.dotContainerElement.getBoundingClientRect().width) { var dotExtenderElementArray = Array.prototype.slice.call(this.innerDotContainerElement.getElementsByClassName("gallery-dot-extender")); for (var itemIndex = 0; itemIndex < this.itemCount; itemIndex++) { var dotExtenderElement = dotExtenderElementArray[itemIndex]; dotExtenderElement.onclick = this.selectFrame.bind(this, itemIndex); var captionID = this.getCaptionElementIDForIndex(itemIndex); var dotElement = dotExtenderElement.getElementsByTagName("span")[0]; dotElement.setAttribute("aria-describedby", captionID); } } else { this.innerDotContainerElement.style.display = 'none'; } } completeTree() { this.createImageRollElement(); this.completeItemCaptionElements(); if (!this.isFullscreen()) { this.addSelectionDots(); } } addWindowEventListeners() { window.addEventListener("pageshow", this.onPageShow.bind(this)); window.addEventListener("pagehide", this.onPageHide.bind(this)); } createObservers() { this.currentItemObserverArray = []; if (this.galleryElement.getElementsByClassName("gallery-caption").length > 1) { this.currentItemObserverArray.push(new GalleryCaptionRollManager(this)); } if (!this.isFullscreen()) { this.currentItemObserverArray.push(new GalleryDotManager(this)); if (useMouselessButtons()) { this.currentItemObserverArray.push(new GalleryMouselessButtonsManager(this)); } } } startUp() { this.currentItemIndex = -1; var newItemIndex = parseInt(this.galleryElement.getAttribute("data-current-item-index")); this.changeCurrentItemIndex(newItemIndex, false); } constructor (galleryElement) { this.galleryElement = galleryElement; this.completeTree(); this.viewfinderManager = new GalleryViewfinderManager(this); this.addWindowEventListeners(); this.createObservers(); this.imageRollManager = new GalleryImageRollManager(this); if (!useMouselessButtons()) { this.touchManager = new TouchManager(this); } debugLog("Creating gallery " + galleryElement.id); this.startUp(); } isFullscreen() { return false; } changeCurrentItemIndex(newItemIndex, animate) { if (this.currentItemIndex != newItemIndex) { if (Math.abs(newItemIndex - this.currentItemIndex) > 1.0) { // Animation is supported only between neighbouring frames. animate = false; } this.imageRollManager.onCurrentItemChange(this.currentItemIndex, newItemIndex, animate); var intCurrentItemIndex = Math.round(this.currentItemIndex); var intNewItemIndex = Math.round(newItemIndex); if (intNewItemIndex != intCurrentItemIndex) { this.onCurrentItemChange(intCurrentItemIndex, intNewItemIndex, animate); this.galleryElement.setAttribute("data-current-item-index", intNewItemIndex); } this.currentItemIndex = newItemIndex; this.updateImagesAXVisibility(); } } updateImagesAXVisibility() { var currentIndex = this.currentItemIndex; var images = Array.prototype.slice.call(document.getElementsByClassName("gallery-full-image")); images.forEach(function(image, index) { image.setAttribute("aria-hidden", index == currentIndex ? "false" : "true"); }); } goToPrevFrame() { var currentItemIndex = this.currentItemIndex; this.changeCurrentItemIndex(currentItemIndex-1, true); } goToNextFrame() { var currentItemIndex = this.currentItemIndex; this.changeCurrentItemIndex(currentItemIndex+1, true); } selectFrame(newItemIndex) { this.changeCurrentItemIndex(newItemIndex, true); } maximizeFrame() { } onCurrentItemChange(oldItemIndex, newItemIndex, animate) { this.currentItemObserverArray.forEach(function(observer) { observer.onCurrentItemChange(oldItemIndex, newItemIndex, animate); }); this.viewfinderManager.onCurrentItemChange(oldItemIndex, newItemIndex); } onPageShow() { this.viewfinderManager.onPageShow(); } onPageHide() { this.viewfinderManager.onPageHide(); } getCaptionElementIDForIndex(index) { var captionIndex = index+1; return this.galleryElement.id + "-caption-" + captionIndex; } static setButtonVisibility(buttonElement, visible) { if (buttonElement) { buttonElement.style.opacity = visible ? 1.0 : 0.0; } } } class RegularGallery extends Gallery { static setDisplayToNoneForElementsOfClass(className) { var elementArray = Array.prototype.slice.call(document.getElementsByClassName(className)); elementArray.forEach( function(element) { element.style.display = 'none'; }); } static loadGalleries() { this.setDisplayToNoneForElementsOfClass("gallery-fallback"); this.setDisplayToNoneForElementsOfClass("gallery-fallback-separator"); var galleryElementArray = Array.prototype.slice.call(document.getElementsByClassName("gallery")); galleryElementArray.forEach(function(galleryElement) { galleryElement.style.display = ''; new RegularGallery(galleryElement); }); } } function Body_onLoad() { RegularGallery.loadGalleries(); }