From db123a150860a9aa7b547289d3b2c61bc8f25f7b Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Tue, 14 Jan 2025 11:53:32 -0500 Subject: [PATCH] fix: Fix checking if `scope` is a jquery element Fixes rstudio/bslib#1159 --- srcts/src/shiny/bind.ts | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/srcts/src/shiny/bind.ts b/srcts/src/shiny/bind.ts index 93f9122a4..78c6181e7 100644 --- a/srcts/src/shiny/bind.ts +++ b/srcts/src/shiny/bind.ts @@ -12,6 +12,19 @@ import { shinyAppBindOutput, shinyAppUnbindOutput } from "./initedMethods"; import { sendImageSizeFns } from "./sendImageSize"; type BindScope = HTMLElement | JQuery; +type BindAllScope = HTMLElement | JQuery | Text; + +/** + * Type guard to check if a value is a jQuery object containing HTMLElements + * @param value The value to check + * @returns A type predicate indicating if the value is a jQuery + */ +function isJQuery(value: unknown): value is JQuery { + return ( + Object.prototype.hasOwnProperty.call(value, "jquery") && + typeof (value as any).jquery === "string" + ); +} // todo make sure allowDeferred can NOT be supplied and still work function valueChangeCallback( @@ -78,7 +91,11 @@ const bindingsRegistry = (() => { * @returns ShinyClientMessageEvent if current ID bindings are invalid, * otherwise returns an ok status. */ - function checkValidity(scope: BindScope): void { + function checkValidity(scope: BindAllScope): void { + if (scope instanceof Text) { + scope = scope.parentElement || document.documentElement; + } + type BindingCounts = { [T in BindingTypes]: number }; const duplicateIds = new Map(); const problems: Set = new Set(); @@ -146,7 +163,7 @@ const bindingsRegistry = (() => { }:\n${duplicateIdMsg}`; const event = new ShinyClientMessageEvent({ headline, message }); - const scopeElement = scope instanceof HTMLElement ? scope : scope.get(0); + const scopeElement = isJQuery(scope) ? scope.get(0) : scope; (scopeElement || window).dispatchEvent(event); }