Shadcn sidebar gap

I have created a sidebar in react router. When I place the side bar in other pages, it works fine. When I place it in the root file, it has a gap that I can’t seem to figure out. I have played around with CSS, both root and app sidebar but nothing helps. How can I fix this?

Screenshot of the account page

I have tinkered with the root.tsx and appsidebar.tsx but the gap still sticks, with or without the trigger, that gap is still there.

root.tsx

export function Layout({ children }: { children: React.ReactNode }) {
  return (
   <html lang="en">
   <head>
    <meta charSet="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <Meta />
    <Links />
    <script
     dangerouslySetInnerHTML={{
      __html: `
        (function() {
          try {
            const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
            const stored = localStorage.getItem('theme');
            const theme = stored || (prefersDark ? 'dark' : 'light');
            if (theme === 'dark') {
              document.documentElement.classList.add('dark');
            } else {
              document.documentElement.classList.remove('dark');
            }
          } catch (_) {}
        })();
      `,
     }}
    />
   </head>
   <body className="flex flex-col">
   {/* Top navigation always at the top */}
   <TopNav />
   
   {/* Sidebar + content below */}
   <SidebarProvider
    style={
     {
      "--sidebar-width": "21rem",
     } as React.CSSProperties
    }
   >
    <div className="flex flex-1">
     {/* Sidebar */}
     <AppSidebar />
     <SidebarTrigger className="sticky top-14 self-start z-50 " />
     {/* Main page content */}
     <main className="flex-1 overflow-y-auto">
      {children}
     </main>
    </div>
   </SidebarProvider>
   
   <ScrollRestoration />
   <Scripts />
   </body>
   </html>
  );
}

appsidebar.tsx

export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
  return (
   <Sidebar {...props} className="">
    <SidebarHeader>
     <SidebarMenu>
      <SidebarMenuItem>
       <SidebarMenuButton size="lg" asChild>
       <b/>
       </SidebarMenuButton>
      </SidebarMenuItem>
     </SidebarMenu>
    </SidebarHeader>
    <SidebarContent>
     <SidebarGroup>
      <SidebarMenu>
       {data.navMain.map((item, index) => (
        <Collapsible
         key={item.title}
         defaultOpen={index === 1}
         className="group/collapsible"
        >
         <SidebarMenuItem>
          <CollapsibleTrigger asChild>
           <SidebarMenuButton>
            {item.title}{" "}
            <Plus className="ml-auto group-data-[state=open]/collapsible:hidden" />
            <Minus className="ml-auto group-data-[state=closed]/collapsible:hidden" />
           </SidebarMenuButton>
          </CollapsibleTrigger>
          {item.items?.length ? (
           <CollapsibleContent>
            <SidebarMenuSub>
             {item.items.map((item) => (
              <SidebarMenuSubItem key={item.title}>
               <SidebarMenuSubButton
                asChild
                isActive={item.isActive}
               >
                <a href={item.url}>{item.title}</a>
               </SidebarMenuSubButton>
              </SidebarMenuSubItem>
             ))}
            </SidebarMenuSub>
           </CollapsibleContent>
          ) : null}
         </SidebarMenuItem>
        </Collapsible>
       ))}
      </SidebarMenu>
     </SidebarGroup>
    </SidebarContent>
    <SidebarRail />
   </Sidebar>
  )
}

How can I get Javascript to report the maximum possible width of the viewport of the browser on any device?

How can I get Javascript to read the maximum possible width of the viewport of any browser on any device when the browser window width is fully expanded on the device?

I have tried;

maxViewportWidth = window.screen.width;

But when I get Javascript to render this value in the browser it is less than window.innerWidth as I expand the browser window width.

Populate global js object during build of each astro page and do x when the build of page finishes

I am attaching astro to the stack of a company to facilitate the generation of all pages in a component-based way. The company uses a handy automation which auto-generates a single .ts module file per API endpoint of their API. Each of these endpoint .ts files exports an array variable called csrf of CSRF-Token identifiers (type string[]). How can I, at the end of each page build, access the aggregated array of all CSRF-Token identifiers imported via the bundled script tag of the built astro page, and do something with it / store the array in an external .json file?

As you may thought, the goal behind this is to auto-generate an array of the identifiers of all CSRF-Tokens needed on a prerendered astro page (according to the above-mentioned (recursive) resolution of all modules needed in the page).

The alternative to this is of course specifying manually at the top-level per astro page which CSRF-Tokens are needed on the page, but that’s how they do it currently, and it not rarely leads to a page running without all CSRF-Tokens it needs (utlimately resulting in failed requests).

Removing part of some text via JavaScript

I need to remove some text from an WordPress events plugin that displays events in a grid with full location name and address. I want to remove the address and leave the location name. However despite there being separate fields for these details in the back end, the name and address are displayed in the same HTML div. Is there a way, using JavaScript, of removing the address only? The code is as follows:

<script type="application/ld+json">
            {
                "@context": "http://schema.org",
                "@type": "Event",
                "eventStatus": "https://schema.org/EventScheduled",
                "startDate": "2025-08-27",
                "endDate": "2025-08-27",
                "eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
                "location":
                {
                    "@type": "Place",
                                        "name": "West and Wardlawhill Parish Church",
                    "image": "https://9jh.adb.myftpupload.com/wp-content/uploads/2025/08/placeholder-4-1.png",
                    "address": "1 Western Ave, Rutherglen, Glasgow G73 1JQ"
                                    },
                                "organizer":
                {
                    "@type": "Person",
                    "name": "",
                    "url": ""
                },
                                "offers":
                {
                    "url": "https://9jh.adb.myftpupload.com/events/daily-each-3-days/",
                    "price": "0",
                    "priceCurrency": "GBP",
                    "availability": "https://schema.org/InStock",
                    "validFrom": "2025-08-27T00:00"
                },
                "performer": "",
                "description": "Join us for a fun walk from West and Wardlawhill Parish Church through Malls Mire. Bring the kids, bring a friend, all welcome! Come along and meet new friends.  If you have any questions, call 0141 646 0123.    By registering to an event, you consent to Healthy n Happy processing your information as per our Privacy Policy.  We will only keep information that is relevant to the type of involvement you have with us.  You can withdraw your consent at any time by contacting [email protected]",
                "image": "https://9jh.adb.myftpupload.com/wp-content/uploads/2025/08/walks.jpg",
                "name": "Walk Way Us Wednesday",
                "url": "https://9jh.adb.myftpupload.com/events/daily-each-3-days/?occurrence=2025-08-27"
            }
            </script>

<p class="mec-grid-event-location">West and Wardlawhill Parish Church, 1 Western Ave, Rutherglen, Glasgow G73 1JQ</p>

The plugin support advised me to use JavaScript to remove the address, but I don’t know how.

I can render a component using routes without having to declare that component in ngModule?

I created a separate component, then added it to the routes array, then I ran the url and saw that the component still rendered in as usual without having to declare that component in any ngModule. The angular version I’m using is v17 and as far as I know, when ng build and ng serve, the routes will work differently.

    //app-routing.module.ts


        import { NgModule } from '@angular/core';
        import { RouterModule, Routes } from '@angular/router';
        import { LoggerComponent } from './no-stand-alone/logger.component';
        import { NoStandAlone1Component } from './no-stand-alone/no-stand-alone-1/no-stand-alone-1.component';
        import { NoModuleComponent } from './no-module/no-module.component';
        
        const routes: Routes = [
          {
            path: "no-module",
            component: NoModuleComponent
          }
        ];
        
        @NgModule({
          imports: [RouterModule.forRoot(routes)],
          exports: [RouterModule]
        })
        export class AppRoutingModule { }

------------------------------------------------------------------------------------
    //no-module.component.ts
    
    
    import { Component } from "@angular/core";
    
    @Component({
      standalone: false,
      selector: "app-no-module",
      template: `<h1>active no module</h1>`,
      styles: []
    })
    export class NoModuleComponent{}

textarea auto-resize and controlled input causes flicker and cursor jump

I am working on a chat input box in React that should behave like a ChatGPT textarea:

  1. expand automatically as the user types
  2. wrap long lines without horizontal scroll
  3. Submit message on Enter, insert newline on shift+enter

My Code:

Parent component:

import { useEffect, useState } from "react";
import ChatInput from "./ChatInput";

export default function App() {
  const [tick, setTick] = useState(0);
  useEffect(() => {
    const id = setInterval(() => setTick(t => t + 1), 1000);
    return () => clearInterval(id);
  }, []);

  return (
    <div style={{ padding: 24 }}>
      <p>Parent tick: {tick}</p>
      <ChatInput onSubmit={(m) => console.log("submit:", m)} />
    </div>
  );
}

Child Component:

export default function ChatInput({ onSubmit }) {
  const [message, setMessage] = useState("");
  const ref = useRef(null);
  const handleChange = (e) => {
    setMessage(e.target.value);
    const el = ref.current;
    if (el) {
      el.style.height = "0px";                  
      el.style.height = `${el.scrollHeight}px`; 
    }
  };
  const handleKeyDown = (e) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      onSubmit(message);
      setMessage("");
      if (ref.current) ref.current.style.height = "0px";
    }
  };
  return (
    <textarea
      ref={ref}
      value={message}
      onChange={handleChange}
      onKeyDown={handleKeyDown}
      rows={1}
      placeholder="Write your message..."
      style={{
        width: "100%",
        resize: "none",
        overflow: "hidden",
        whiteSpace: "pre-wrap",
        wordBreak: "break-word"
      }}
    />
  );
}

Issue:
Sometimes the textarea flickers when resizing. In some browsers (especially Chrome), the cursor jumps to the end of the text if I try to edit in the middle of the message. This occurs more when the component re renders (example:- parent state updates).

Steps to reproduce:

  1. Type multiple lines so the textarea grows.

  2. Click in the middle of the text and edit.

  3. Observe flicker/caret jump, especially when app’s tick forces a parent re-render.

What I tried:

  1. Using onChange instead of onInput same issue.
  2. Moving the resize logic into a useEffect() still flickers.
  3. Wrapping height reset in requestAnimationFrame reduces flicker but cursor jump still happens.

How to exclude some class or pages using .offset().top

I’m using this part of code on my website and it works very well:

$(document).ready(function() {
  setTimeout(function() {
    var scroll = $('.restaurant, .mention, .politique, .condition').offset().top;    
    $('html, body').animate({ scrollTop: scroll }, 2000);
  }, 2500); 
});

But I don’t want to use it in all pages, so I’ve this error:

Uncaught TypeError: can’t access property “top”, $(…).offset() is undefined

In pages where these class aren’t used:

$('.restaurant, .mention, .politique, .condition')

My problem is that I don’t know how to use this part of code only for some pages with class I mentioned not others. I tried to add .not('.links-body') like this:

$(document).ready(function() {
  setTimeout(function() {
    var scroll = $('.restaurant, .mention, .politique, .condition').not('.links-body').offset().top;    
    $('html, body').animate({ scrollTop: scroll }, 2000);
  }, 2500); 
});

Or replace $('html, body').animate by $('.home-video').animate like this, to apply this part of code only for pages who use .home-video class :

$('.home-video').animate({ scrollTop: scroll }, 2000); 

But it does not work, I still have the error in the page. Do you have an idea on how to exclude some pages or class for this part of code?

I’m new to HTML and I can’t figure out this problem

    </td>
    </tr>

    <!-- Menu -->
    <tr>
      <td colspan="2" align="center">
        <a href="#">Trang chủ</a> | 
        <a href="#">Giới thiệu</a> | 
        <a href="#">Sản phẩm</a> | 
        <a href="#">Tin tức</a> | 
        <a href="#">Liên hệ</a>
      </td>
    </tr>

    <!-- Banner quảng cáo -->
    <tr>
      <td colspan="2" align="center">
        <img src="banner.png" alt="Banner quảng cáo" height="40">
      </td>
    </tr>

    <!-- Nội dung chính với 3 cột -->
    <tr valign="top">
      <!-- Danh mục (trái) -->
      <td width="15%">
        <b>Danh mục</b><br>
        <a href="#">Danh mục 1</a><br>
        <a href="#">Danh mục 2</a><br>
        <a href="#">Danh mục 3</a><br>
      </td>

      <!-- Nội dung chính (giữa) -->
      <td width="70%">
        <h2>Nội dung chính</h2>
        Đây là khu vực nội dung chính: bài viết nổi bật hoặc sản phẩm.
        <br><br>
        <table border="1" width="90%" cellspacing="0" cellpadding="5" align="center">
          <tr align="center">
            <td><b>Hình</b></td>
            <td><b>Tên sản phẩm</b></td>
            <td><b>Giá</b></td>
          </tr>
          <tr align="center">
            <td><img src="spA.png" alt="Sản phẩm A" height="30"></td>
            <td>Sản phẩm A</td>
            <td>100.000đ</td>
          </tr>
          <tr align="center">
            <td><img src="spB.png" alt="Sản phẩm B" height="30"></td>
            <td>Sản phẩm B</td>
            <td>150.000đ</td>
          </tr>
        </table>
      </td>

      <!-- Tin mới + Quảng cáo (phải) -->
      <td width="15%">
        <b>Tin mới</b>
        <ul>
          <li><a href="#">Tin 1</a></li>
          <li><a href="#">Tin 2</a></li>
        </ul>
        <b>Quảng cáo nhỏ</b><br>
        <img src="qc.png" alt="QC nhỏ" height="40">
      </td>
    </tr>

    <!-- Footer -->
    <tr>
      <td colspan="3" align="center">
        © 2025 Công ty ABC | Liên hệ: [email protected]
      </td>
    </tr>
  </table>
</body>
</html>

I am currently working on a simple HTML project where I am building a page layout using only a table element because I am still very new to web development and have not yet started learning CSS, and my intention is to divide the page into different sections such as a header, a menu row, a banner row, and then a content row where the left column is supposed to act as a small sidebar for categories or links, the middle column is supposed to be the main content area, and the right column is supposed to contain a small news or advertisement section, but the problem I keep running into is that when I try to set the left sidebar cell (which I labeled ‘Danh mục’ or ‘Categories’) to a fixed percentage width like 15% of the whole table using the width attribute directly on the element, it does not appear to actually shrink or respect that percentage, because instead it expands and takes up way more horizontal space than expected, almost like 300 pixels wide or more, which completely throws off the alignment and makes the whole layout look unbalanced, and I have already tried several different adjustments such as changing the width attribute to 10% or even smaller values, trying to put the width on the or itself, and testing with or without other attributes like cellpadding or cellspacing, but no matter what I do the table cell for the category list still ends up being far larger than I want it to be, and I just cannot figure out why the browser is forcing that cell to be so wide, and it is becoming very frustrating because I only want to use HTML here without any CSS, and since I am a complete beginner who is still learning how HTML tables behave, this unexpected behavior is really bugging me and making me wonder if I am missing some fundamental rule about how table cell widths are calculated in HTML, so I would really appreciate if someone could explain in detail why the third row cell in particular seems to take so much space even when I explicitly put the width at 15%, and what exactly is causing this behavior in pure HTML without resorting to CSS.
(sr for the long paragraph to bypass the posting issue, i know it easy but i need an answer)

How can I convert existing data in Google Sheets into a Table from Google Apps Script?

New to Google sheets and Javascript after 3 years away from computers.

I have some data:

enter image description here

I want to make it look a little nicer, so I click Format, Convert to Table.

enter image description here

And it spits out a fancy table like this:

enter image description here

Is there a way to replicate this from within the Apps Script? Something like this would be really handy if it worked:

const sheet = SpreadsheetApp.getActiveSheet();
const lastRow = sheet.getLastRow();
const lastColumn = sheet.getLastColumn();
const dataRange = sheet.getRange(1, 1, lastRow, lastColumn);

dataRange.convertToTable();

Is there something like this I can do?

Nativewind classes being removed with Storybook

I am using nativewind for a UI library I am working on. I am using Storybook for React Native web with Vite as the bundler. The problem is my styles are not applying. Not the tailwind variables or the default ones. However, the same configuration works fine with expo even on the web.

Here is my tailwind.config.js file:

/** @type {import('tailwindcss').Config} */
export default {
  darkMode: "class",
  content: [
    "./.storybook/**/*.{js,jsx,ts,tsx}",
    "../registry/**/*.{js,jsx,ts,tsx}",
    "./.stories/**/*.{js,jsx,ts,tsx}",
  ],
  // eslint-disable-next-line
  presets: [require("nativewind/preset")],
  theme: {
    extend: {
      colors: {
        border: "var(--border)",
        input: "var(--input)",
        ring: "var(--ring)",
        background: "var(--background)",
        foreground: "var(--foreground)",
        primary: {
          DEFAULT: "var(--primary)",
          foreground: "var(--primary-foreground)",
        },
        secondary: {
          DEFAULT: "var(--secondary)",
          foreground: "var(--secondary-foreground)",
        },
        destructive: {
          DEFAULT: "var(--destructive)",
          foreground: "var(--destructive-foreground)",
        },
        success: {
          DEFAULT: "var(--success)",
          foreground: "var(--success-foreground)",
        },
        warning: {
          DEFAULT: "var(--warning)",
          foreground: "var(--warning-foreground)",
        },
        muted: {
          DEFAULT: "var(--muted)",
          foreground: "var(--muted-foreground)",
        },
        accent: {
          DEFAULT: "var(--accent)",
          foreground: "var(--accent-foreground)",
        },
        popover: {
          DEFAULT: "var(--popover)",
          foreground: "var(--popover-foreground)",
        },
        card: {
          DEFAULT: "var(--card)",
          foreground: "var(--card-foreground)",
        },
        sidebar: {
          DEFAULT: "var(--sidebar-background)",
          foreground: "var(--sidebar-foreground)",
          primary: "var(--sidebar-primary)",
          "primary-foreground": "var(--sidebar-primary-foreground)",
          accent: "var(--sidebar-accent)",
          "accent-foreground": "var(--sidebar-accent-foreground)",
          border: "var(--sidebar-border)",
          ring: "var(--sidebar-ring)",
        },
      },
      borderRadius: {
        xl: "calc(var(--radius) + 4px)",
        lg: "var(--radius)",
        md: "calc(var(--radius) - 2px)",
        sm: "calc(var(--radius) - 4px)",
        full: "100%",
      },
    },
  },
  plugins: [],
};

My global.css file:

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --radius: 0.625rem;
    --background: #ffffff;
    --foreground: #252525;
    --card: #ffffff;
    --card-foreground: #252525;
    --popover: #ffffff;
    --popover-foreground: #252525;
    --primary: #343434;
    --primary-foreground: #fbfbfb;
    --secondary: #f7f7f7;
    --secondary-foreground: #343434;
    --success: #22c55e;
    --warning: #eab308;
    --muted: #f7f7f7;
    --muted-foreground: #8e8e8e;
    --accent: #f7f7f7;
    --accent-foreground: #343434;
    --destructive: #ef4444;
    --border: #ebebeb;
    --input: #ebebeb;
    --ring: #b5b5b5;
    --chart-1: #f97316;
    --chart-2: #06b6d4;
    --chart-3: #3b82f6;
    --chart-4: #84cc16;
    --chart-5: #f59e0b;
    --sidebar: #fbfbfb;
    --sidebar-foreground: #252525;
    --sidebar-primary: #343434;
    --sidebar-primary-foreground: #fbfbfb;
    --sidebar-accent: #f7f7f7;
    --sidebar-accent-foreground: #343434;
    --sidebar-border: #ebebeb;
    --sidebar-ring: #b5b5b5;
  }

  .dark:root {
    --background: #252525;
    --foreground: #fbfbfb;
    --card: #343434;
    --card-foreground: #fbfbfb;
    --popover: #444444;
    --popover-foreground: #fbfbfb;
    --primary: #ebebeb;
    --primary-foreground: #343434;
    --secondary: #444444;
    --secondary-foreground: #fbfbfb;
    --muted: #444444;
    --muted-foreground: #b5b5b5;
    --accent: #5f5f5f;
    --accent-foreground: #fbfbfb;
    --destructive: #dc2626;
    --success: #16a34a;
    --warning: #ca8a04;
    --border: rgba(255, 255, 255, 0.1);
    --input: rgba(255, 255, 255, 0.15);
    --ring: #8e8e8e;
    --chart-1: #8b5cf6;
    --chart-2: #10b981;
    --chart-3: #f59e0b;
    --chart-4: #ec4899;
    --chart-5: #dc2626;
    --sidebar: #343434;
    --sidebar-foreground: #fbfbfb;
    --sidebar-primary: #8b5cf6;
    --sidebar-primary-foreground: #fbfbfb;
    --sidebar-accent: #444444;
    --sidebar-accent-foreground: #fbfbfb;
    --sidebar-border: rgba(255, 255, 255, 0.1);
    --sidebar-ring: #707070;
  }
}

Then for storybook I have the following config:


import {join, dirname} from "path";
import type {StorybookConfig} from "@storybook/react-native-web-vite";
import {createRequire} from "module";
import {createBuildStoriesPlugin} from "../plugins/buildStories";

const require = createRequire(import.meta.url);

/**
 * This function is used to resolve the absolute path of a package.
 * It is needed in projects that use Yarn PnP or are set up within a monorepo.
 */
function getAbsolutePath(value) {
  return dirname(require.resolve(join(value, "package.json")));
}

const config: StorybookConfig = {
  stories: [
    "../.stories/**/*.mdx",
    "../.stories/**/*.stories.@(js|jsx|mjs|ts|tsx)",
  ],
  addons: ["@storybook/addon-docs"],
  framework: {
    name: getAbsolutePath("@storybook/react-native-web-vite"),
    options: {
      modulesToTranspile: [
        "react-native",
        "react-native-web",
        "solito",
        "moti",
        "react-native-reanimated",
        "react-native-css-interop",
        "nativewind",
        "react-native-gesture-handler",
      ],
      pluginReactOptions: {
        jsxImportSource: "nativewind",
        babel: {
          presets: [
            ["nativewind/babel", {mode: "transformOnly", postcss: true}],
          ],
          plugins: ["react-native-reanimated/plugin"],
        },
      },
    },
  },
  async viteFinal(viteConfig) {
    viteConfig.plugins = viteConfig.plugins || [];
    viteConfig.plugins.push(createBuildStoriesPlugin());

    // Configure CSS processing for Tailwind
    viteConfig.css = {
      ...viteConfig.css,
      postcss: {
        plugins: [
          require("tailwindcss")({
            config: "./tailwind.config.js",
          }),
        ],
      },
    };

    if (!viteConfig.optimizeDeps) {
      viteConfig.optimizeDeps = {};
    }
    if (!viteConfig.optimizeDeps.esbuildOptions) {
      viteConfig.optimizeDeps.esbuildOptions = {};
    }
    if (!viteConfig.optimizeDeps.esbuildOptions.loader) {
      viteConfig.optimizeDeps.esbuildOptions.loader = {};
    }
    viteConfig.optimizeDeps.esbuildOptions.loader[".js"] = "jsx";
    viteConfig.optimizeDeps.esbuildOptions.loader[".mjs"] = "jsx";

    return viteConfig;
  },
};
export default config;

Finally my preview.ts:

import type {Preview} from "@storybook/react-native-web-vite";
import "../output.css";
import React from "react";
import {NavigationContainer} from "@react-navigation/native";


const preview: Preview = {
  parameters: {
    backgrounds: {
      options: {
        light: {
          name: "Light",
          value: "#ffffff",
        },
        dark: {
          name: "Dark",
          value: "#0a0a0a",
        },
      },
    },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
  initialGlobals: {
    backgrounds: {value: "dark"},
  },
  decorators: [
    (Story) => (
      <>
        <NavigationContainer>
          <Story />
        </NavigationContainer>
      </>
    ),
  ],
};

export default preview;

The issue is not tailwind generating the classes. As my output file does have the correct classes in it my I did a test. Additionally, the stylesheet does load in the head with the correct styles yet they do not apply.

[![Styles load][1]][1]

However, the elements themselves do not seem to have the correct classes. So it seems babel is stripping away my tailwind classes. How do I prevent this?

Invalid left-hand side in assignment of x.style =

Background: I have an ordinary HTML DIV box. which contains some text and a table.
It’s a wide table, too wide for cell phones, so there is an option to hide some less significant columns to reduce the width.

    CSS  dv {margin:0 auto; background-color:#ffffff; max-width:100%; padding:8px 5px 3px 9px; border:1px solid #eb4; border-radius:12px; display:table;}    
    HTML <div id="dv1" class="dv" style="padding:0 2px 4px 0; max-width:850px; overflow:hidden;">

I have Javascript to service the option to alter the div max-width (trying to match the div to the table width):

    function show_all_columns(show) {   //show or hide first 5 years of columns
        let x = Obj.tbl1.rows;
        for (let row = Obj.rowcnt; row >= 0; row--) {   
            let cells = x[row].cells;
            for (let col = 1; col <= 5; col++) {
                cells[col].style.display = show ? "table-cell" : "none";
            }                           //all this works
        }
        Obj.all_cols_are_shown = show;

        x = document.getElementById("dv1");             //more  detail than necessary,
        x.style.max-width = (show)? "850px" : "600px";  // <----<<  but this x is the problem

        x = 0;   //just to stop debugger here so I can read x
    }

But the Chrome debugger reports this error about x: Invalid left-hand side in assignment

In the debugger, if I comment out the troubled line (x.style.max-width which halts everything), then I can drill into the x variable, which shows:

    style: CSSStyleDeclaration 
    0: "padding-top"
    1: "padding-right"
    2: "padding-bottom"
    3: "padding-left"
    4: "max-width"
    5: "overflow-x"
    6: "overflow-y"

My diligence sees nothing wrong with the format of the max-width, but something blows up, and I have no clue. Any help appreciated.

I assume 600 px width is appropriate for cell phones, but am not sure if I just made that up or not?

Using JavaScript for Qualtrics: make options for question 2 dependent on question 1 selection

So I have been assigned with making a survey in Qualtrics.

  • The first question is “Which county do you live in”
  • The second question is “which zip code do you use”

Right now, I am trying to make all of the options in the dropdown menu for question 2 (Q2) dependent on the answer to question 1 (Q1). For example, if someone selects “Smith County” for Q1, I only want zip codes in Smith County to appear as options for Q2.

After making several different Q2s that display based on conditional logic, I have decided that there must be a better way, and I have resorted to looking into Qualtrics’ Java Encoding capabilities.

Would anybody know how to code something like this? I am aware that it would likely require uploading embedded data- that is a non-issue.

Thanks!

How to add FPS-like controls (WASD movement + mouse rotation) to a Plotly 3D scatter plot in HTML?

I need to create a Plotly 3D scatter plot in Python, save it as a self-contained HTML file (e.g., via fig.write_html), and open it in any browser for offline viewing. The plot should have FPS-like controls: WASD keys for camera movement (forward/back/left/right) and mouse for rotation (around the camera).

This would allow “flying” through the data points like in an FPS game, rather than just orbiting a fixed center.

I’m using Python to generate the plot and export to HTML, but I’m open to JavaScript modifications since Plotly.js handles the rendering. Here’s a minimal example of my current setup using Plotly Express:

import plotly.express as px

# Sample data (Iris dataset for 3D scatter)
df = px.data.iris()

# Create 3D scatter plot
fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_length',
                    color='species', title='Interactive 3D Scatter Plot')

# Save as interactive HTML
fig.write_html("3d_scatter.html")

This generates an HTML file with basic interactivity, but no FPS controls. I’ve seen hints in Plotly docs about customizing the camera (e.g., via scene.camera.eye, center, and up in the layout), and I know Plotly supports relayout for updates.

However, I’m stuck on how to:

  1. Capture keyboard (WASD) and mouse events in the browser.
  2. Update the camera position/rotation dynamically without breaking the plot.
  3. Handle pointer lock for mouse rotation to mimic FPS mouse-look.
    Is there a way to achieve this by extending the generated HTML with JavaScript (e.g., event listeners and Plotly.react/relayout)? Or do I need to use Plotly.js directly? Any code examples or tutorials would be greatly appreciated—bonus if it works with large datasets without performance issues.

Environment: Python 3.10, Plotly 5.17, testing in Chrome.

How to prevent text highlight while keeping drag functional

I’m following this tutorial:

https://learnvue.co/articles/vue-drag-and-drop

The final result is that I can drag the elements once I’ve highlighted the text that they contain. (e.g. if I highlight the text “Item A”, I can then drag it to the other drop zone)

I want to disable text highlighting and make the text unselectable. Several answers here recommend the CSS tag user-select: none; but this makes it so the user cannot drag the element either.

I’ve created a sandbox showing both the original code (have to highlight the text to drag the element) and the code with user-select: none;. I’m at a loss for what to try next.

Sandbox Link