{
- if (
- !this.state.ignorePhonyClick && // if we're dragging, that isn't a click we want to propagate
- this.props.onContentClick &&
- !this.activityManager.getActivityAbsorbsClicking() &&
- // clicks in video containers are probably aimed at the video controls.
- // I tried adding another click handler to the video container with stopPropagation,
- // but for some reason it didn't work.
- !(e.target as HTMLElement).closest(
- ".bloom-videoContainer",
- )
- ) {
- this.props.onContentClick(e);
- }
- this.setState({
- ignorePhonyClick: false,
- });
- }}
+ onClick={(e) => this.handlePageClick(e)} // Changed this line
>
{/* This is a huge performance enhancement on large books (from several minutes to a few seconds):
Only load up the one that is about to be current page and the ones on either side of it with
@@ -2471,8 +2405,38 @@ export class BloomPlayerCore extends React.Component
{
}
return result;
}
-}
+ private handlePageClick(e: React.MouseEvent): void {
+ if (
+ // Check for special circumstance that should prevent normal click handling. That is,
+ // we're not processing a phony click from touching a nav button
+ !this.state.ignorePhonyClick &&
+ // this page isn't an activity that needs to handle all clicks itself
+ !this.activityManager.getActivityAbsorbsClicking() &&
+ // the click isn't in a video container
+ // (clicks in video containers are probably aimed at the video controls.
+ // I tried adding another click handler to the video container with stopPropagation,
+ // but for some reason it didn't work. (JT: probably a capturing handler on an outer element))
+ !(e.target as HTMLElement).closest(".bloom-videoContainer")
+ ) {
+ const newLocation = checkClickForBookOrPageJump(
+ e.nativeEvent as MouseEvent,
+ this.bookInfo.bookInstanceId,
+ () => this.getPageIdFromIndex(this.state.currentSwiperIndex),
+ );
+ if (newLocation) {
+ this.navigate(newLocation.bookUrl, newLocation.pageId);
+ e.stopPropagation(); // Stop click from propagating up
+ e.preventDefault(); // Prevent default link behavior
+ } else if (this.props.onContentClick) {
+ this.props.onContentClick(e);
+ }
+ }
+ this.setState({
+ ignorePhonyClick: false,
+ });
+ }
+}
function htmlEncode(str: string): string {
return str.replace("%23", "#").replace(/[\u00A0-\u9999<>\&]/gim, (i) => {
return "" + i.charCodeAt(0) + ";";
diff --git a/src/navigation.ts b/src/navigation.ts
index bddd013..e2b01cb 100644
--- a/src/navigation.ts
+++ b/src/navigation.ts
@@ -33,20 +33,20 @@ export function checkClickForBookOrPageJump(
const linkElement = (event.target as HTMLElement).closest(
"[href], [data-href]",
) as HTMLElement;
- if (!linkElement) return {};
+ if (!linkElement) return undefined;
event.preventDefault(); // don't let a link click become a drag
event.stopPropagation();
- const href: string =
+ const href: string | undefined =
(linkElement.getAttribute("href") ||
linkElement.getAttribute("data-href")) ??
- "";
-
+ undefined;
+ if (!href) return undefined;
if (href.startsWith("http://") || href.startsWith("https://")) {
// This is a generic external link. We open it in a new window or tab.
// (The host possibly could intercept this and open a browser to handle it.)
window.open(href, "_blank", "noreferrer");
- return {};
+ return undefined;
}
let targetBookId: string | undefined = undefined;
diff --git a/src/stories/BloomPlayerIframe.tsx b/src/stories/BloomPlayerIframe.tsx
index 5342d0f..35d498b 100644
--- a/src/stories/BloomPlayerIframe.tsx
+++ b/src/stories/BloomPlayerIframe.tsx
@@ -2,7 +2,12 @@ import React, { useState, useEffect } from "react";
// Use this in stories where you need to more closely simulate what a host will see as they use bloomplayer.htm.
-export function BloomPlayerIframe({ bookUrl, bookPageIndex, showBackButton }) {
+export function BloomPlayerIframe({
+ bookUrl,
+ bookPageIndex,
+ showBackButton,
+ allowToggleAppBar,
+}) {
if (!useBuildIsReady()) {
return (
@@ -12,9 +17,12 @@ export function BloomPlayerIframe({ bookUrl, bookPageIndex, showBackButton }) {
}
const backButtonParam = showBackButton ? "&showBackButton=true" : "";
+ const allowToggleAppBarParam = allowToggleAppBar
+ ? "&allowToggleAppBar=true"
+ : "";
return (
);
diff --git a/src/stories/books.stories.tsx b/src/stories/books.stories.tsx
index 328ea7c..976f892 100644
--- a/src/stories/books.stories.tsx
+++ b/src/stories/books.stories.tsx
@@ -250,6 +250,12 @@ export const canvasGame = AddBloomPlayerStory(
);
canvasGame.storyName = "Activity/Canvas Game - Snake (local)";
+export const dragNDropGames = AddBloomPlayerStory(
+ "drag and drop games",
+ "testBooks/drag and drop games/index.htm",
+);
+dragNDropGames.storyName = "Activity/drag and drop games (local)";
+
export const widgetControlledNavigation = AddBloomPlayerStory(
"Activity/Test widget-controlled navigation",
"testBooks/test-widget-message-activity/index.htm",
diff --git a/src/stories/multiBook.stories.tsx b/src/stories/multiBook.stories.tsx
index 17c44a0..f5f50b6 100644
--- a/src/stories/multiBook.stories.tsx
+++ b/src/stories/multiBook.stories.tsx
@@ -19,6 +19,11 @@ const meta: Meta = {
"Show back button in the player that will send a message to the host when the local history is empty and the user clicks it.",
defaultValue: false,
},
+ allowToggleAppBar: {
+ control: "boolean",
+ description: "Allow the user to toggle the app bar in the player.",
+ defaultValue: true,
+ },
},
};
export default meta;
@@ -30,6 +35,7 @@ export const UsePageIndex: Story = {
bookUrl: "testBooks/multibook-index/index.htm",
bookPageIndex: "4",
showBackButton: false,
+ allowToggleAppBar: true,
},
// doesn't work storyName: "Use `bookPageIndex` to specify the starting page",
};
@@ -41,6 +47,7 @@ export const UsePageId: Story = {
bookUrl:
"testBooks/multibook-index/index.htm#653f29c1-665b-4d63-a061-086401abc106",
showBackButton: false,
+ allowToggleAppBar: true,
},
};
UsePageId.storyName =
diff --git a/src/stories/navigation.stories.tsx b/src/stories/navigation.stories.tsx
index ca5fd1c..a54f3d2 100644
--- a/src/stories/navigation.stories.tsx
+++ b/src/stories/navigation.stories.tsx
@@ -19,6 +19,11 @@ const meta: Meta = {
"Show back button in the player that will send a message to the host when the local history is empty and the user clicks it.",
defaultValue: false,
},
+ allowToggleAppBar: {
+ control: "boolean",
+ description: "Allow the user to toggle the app bar in the player.",
+ defaultValue: true,
+ },
},
};
export default meta;
@@ -30,6 +35,7 @@ export const Default: Story = {
bookUrl:
"testBooks/multibook-index/index.htm#653f29c1-665b-4d63-a061-086401abc106",
showBackButton: false,
+ allowToggleAppBar: true,
},
play: async ({ canvasElement, step }) => {
const tester = new BloomPlayerTester(canvasElement);