How to export HTMLElement into

Hi I have a project in NextJs, where I use app router. In my public folder I have a file called chatbutton.js, I need this button to work as a web component that I can implement on external websites.

Implement like this:

<script>
window.embeddedChatbotConfig = {
chatId: "fUYYCegK9QYOtoGJ25Dv1",
domain: "www.chatai.com"
}
</script>
<script
src="https://www.chatai.com/chatbutton.min.js"
chatbotId="fUYYCegK9QYOtoGJ25Dv1"
domain="www.chatai.com"
defer>
</script>

public/chatbutton.min.js:

class ChatButton extends HTMLElement {
  constructor() {
    super();

    // Create shadow DOM
    this.attachShadow({ mode: "open" });

    // Initialize the component
    this.init();
  }

  init() {
    // Create chat button
    const chatButton = document.createElement("div");
    chatButton.setAttribute("id", "chatbase-bubble-button");
    chatButton.style.position = "fixed";
    chatButton.style.bottom = "20px";
    chatButton.style.right = "20px";
...
    chatButton.appendChild(chatButtonIcon);

    // Add click event listener
    chatButton.addEventListener("click", () => this.toggleChatWindow());

    // Append chat button to shadow DOM
    this.shadowRoot.appendChild(chatButton);

    // Create chat window
    const chat = document.createElement("div");
    chat.setAttribute("id", "chatbase-bubble-window");
    chat.style.position = "fixed";
    chat.style.flexDirection = "column";
    chat.style.justifyContent = "space-between";
    chat.style.bottom = "80px";
    chat.style.zIndex = 999999999;

    // Append iframe to chat window
    chat.innerHTML = `<iframe src="https://www.chatai.com/chatbot-iframe/${this.getAttribute(
      "data-chatbotId"
    )}" width="100%" height="100%" frameborder="0"></iframe>`;

    this.shadowRoot.appendChild(chat);

    const mediaQuery = window.matchMedia("(min-width: 550px)");

    function handleChatWindowSizeChange(t) {
      t.matches && ((chat.style.height = "600px"), (chat.style.width = "400px"));
    }

    mediaQuery.addEventListener("change", handleChatWindowSizeChange);
    handleChatWindowSizeChange(mediaQuery);
  }

  toggleChatWindow() {
    const chat = this.shadowRoot.getElementById("chatbase-bubble-window");
    chat.style.display = chat.style.display === "none" ? "flex" : "none";
  }

  get CHAT_BUTTON_ICON() {
    return `
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="M20 2H4C2.9 2 2 2.9 2 4V22L6 18H20C21.1 18 22 17.1 22 16V4C22 2.9 21.1 2 20 2ZM20 16H6L4 18V4H20V16Z" fill="#FFFFFF"/>
      </svg>
    `;
  }
}

customElements.define("chatbase-bubble", ChatBaseBubble);

I need this implementation to be able to add a button that shows an iframe with my chat. But when I add the url to my script, the botton and iframe are not displayed. How can I achieve this?

Thanks!

Is there a way of determining the “defined” vs. “computed” style property of an element?

I’m trying to determine if an absolutely-positioned element’s size is being determined by positioning or dimension.

E.g. an element with a left and width will have a computed right but getComputedStyle will simply report all three values. I want to be able to distinguish between an element whose width is computed from left and right vs. one whose width is defined, etc.

Now, I know that I can “experimentally” change a property, use getComputedStyle to see if something changes, and then restore the property, without the user seeing a “flicker” so this is one option.

E.g. if I want to see if an object’s width is defined I can try changing left and right independently to see whether changing on of them does not change computed width (in which case width is defined, but even this won’t tell me if the width is a result of the element’s content vs. a css rule

Using JavaScript to crop video in browser results in corrupted file on download

I’m attempting to crop a video playing in a video element and then download the video. However, when attempting to play the video following download I get: ‘We can’t open cropped video.mp4.This may be because the file type is unsupported, the file extension is incorrect, or the file is corrupt’. I should note that on replacing the playing video with the supposedly cropped video, nothing plays. As JavaScript is not my strongest language, I’d appreciate any guidance/advise. I’m not getting any errors showing in the console. The relevant code can be seen below:

        }else if(document.getElementById("crop-button").innerText == "CROP IT"){
            const rect = document.getElementById("video-element").getBoundingClientRect();
            const sqr = document.getElementById("draggable-square").getBoundingClientRect();

            const originalVideo = document.getElementById('video-element');
            const canvas = document.createElement('canvas');
            const canvasContext = canvas.getContext('2d');
            const croppedWidth = dim-10; // Adjust to your desired width
            const croppedHeight = dim-10; // Adjust to your desired height
            console.log('dim: '+dim)
            

            canvas.width = croppedWidth;
            canvas.height = croppedHeight;

            function processFrame() {
                canvasContext.drawImage(originalVideo, 0, 0, croppedWidth, croppedHeight);
                
                // Request the next animation frame
                requestAnimationFrame(processFrame);
            }

            function createDownloadLink(blob) {
                // Create a download link for the Blob


                const downloadLink = document.createElement('a');
                downloadLink.href = URL.createObjectURL(blob);
                originalVideo.src = URL.createObjectURL(blob);
                downloadLink.download = 'cropped_video.mp4';

                // Append the link to the document and trigger a click to start the download
                document.body.appendChild(downloadLink);
                downloadLink.click();

                // Clean up
                document.body.removeChild(downloadLink);
            }

            // Start the process by requesting the first animation frame
            requestAnimationFrame(() => {
                processFrame();
                canvas.toBlob(createDownloadLink, 'video/mp4');
            });

        }

Web page only works on Internet explorer IExplorer but not Chrome or Firefox [closed]

I have a main webpage that contains a Table of Contents, each element in the table of contents should open or navigate to a folder. In that folder, there are multiple htm files.

In other words, each element in the Table of Contents should be referencing a folder. The folder name should be the title of the element in the Table of Contents.

The webpage opens fine in IExplorer, but when opened in chrome/firefox it just errors out with: DOMException: Blocked a frame with origin “null” from accessing a cross-origin frame.

Filestructure:

Root/
    Directory 1/
               1.htm
               2.htm
    Directory 2/
               1.htm 
               2.htm
    JavascriptFile1.js
    JavascriptFile2.js
    MAIN_WEBPAGE.htm

In the main webpage it should have a table of contents and when clicked, it should open up the main page within the directory.

Show Hide Multiple Class

I’m building a dynamic page showing client logos. They could be web clients, print clients, logo clients etc. Clients can also be web and print, print & logo, etc etc.

Rather than building the syntax like this:

<h2>Web</h2>
<img src="/client1.jpg">
<img src="/client2.jpg">
<img src="/client3.jpg">
<h2>Print</h2>
<img src="/client2.jpg">
<img src="/client3.jpg">
<h2>Logo</h2>
<img src="/client1.jpg">
<img src="/client3.jpg">

…and wrapping web, print & logo with divs and showing and hiding each…

I’d like to build the syntax like this:

<img src="/client2.jpg" class="web print">
<img src="/client3.jpg" class="web logo">

And then have clickable elements that will show all web or all print or all logo, but none of the others.

I had tried this solution (which got me to the first iteration above)
https://www.sitepoint.com/community/t/toggle-hide-show-multiple-sections/381680/11

But my reasoning is that I currently have 8 categories and may add to it. Outputting 8 queries of whether a client is web or print or logo or one of the other 5 categories seems to be rather inefficient.

Hence if I could output it once with classes (or ids) for each category on each logo, the page would be up to 8 times smaller.

Edit and delete function for my app is not working

I am working in node js environment with handlebars and sequelize orm. Using method over ride module i am trying to edit and delete my project buckets for management system, which is not working. I read about the updates in handlebars security at text which helped me in fetching all my project buckets to page but i have no idea how will i use this solution for edit and delete as it requires me to pass the object first.

EDIT CONTROLLER

async function handleEditBucket(req,res){
  const bucketID = req.params.id;
  const {title,details} = req.body;

    const bucket = await bucketModel.findOne({
      where: {TM_BUCKET_ID: bucketID}
    });
    
    if(bucket){
      bucket.TM_BUCKET_NAME = req.body.title;
      bucket.TM_BUCKET_DESCRIPTION = req.body.details;
      await bucket.save();
      res.redirect('bucket',{bucket})
      }
    else {
      res.render('error', { message: 'Bucket not found' });
    }
}

ROUTE

router.get('/edit/:bucketID', (req,res)=>{
    res.render('../views/bucket/edit')
})
router.put('/edit/:bucketID', bucketController.handleEditBucket)

EDIT FORM BUTTON IN VIEWS

<form method="post" action="/bucket/{{bucketID}}?_method=PUT">
        <input type="hidden" name="_method" value="PUT">
        <a href="/bucket/edit/{{bucketID}}" type="button" class="btn btn-outline-secondary btn-small"><span class="material-icons small-icon">edit</span></a>
      </form>

I have tried to check if i had a problem with using the id in the models.

Why does a page create a scrollbar when browser is resized?

I am noticing a weird visual bug when a browser is resized and another element piece (Menu) is added based on a boolean variable. How the basic page is laid out:

<div className="mainDiv">
  {
    !isEnabled &&
    <Menu className="menuTab" style={{height: "60px"}} ... >
        {
          <MenuItem ... />
        }
    </Menu>
  }
  <Splitter className="splitter">
    <div>
    // More custom divs and such in here
    </div>
    <div className="graph">
      {
        isEnabled && <customD3Graph ... />
      }
      {
        !isEnabled && <customD3Graph2 ... />
      }
  </Spitter>

</div>

So, we basically have a Stepper at the top of the page to “route” to different views. This view shown above represents two “routes” that a user can click. They will generally click the first route where the Menu item is not displayed, then they will click the second route where the Menu displays.

The first view of the page without the menu does not create a scrollbar when resized, but when the user clicks to go to the second route of the same page just with different data and the menu, resizing creates a scrollbar. However, if the user manually reloads/refreshes the page and then resizes the browser, no scrollbar is created. This only happens when going from the first route view to the second view.

Below is some CSS we have applied to the above HTML code for layouts that may be useful.

.mainDiv {
  display: flex;
  flex-direction: column;
  align-items: stretch;

  // This calculation is done for some titles/banners above this shown in a different JS file.
  height: calc(100% - 85px - 50px);
  width: 100%;
}

.splitter {
  height: 100%;
  width: 100%;
  margin: auto;
  order: 1;
  flex-grow: 1;
}

.mainDiv:has(.menuTab) > .splitter {
  // Calculated to account for that 'Menu' that would appear
  height: calc(100% - 60px);
  width: 100%;
  margin: auto;
  flex-grow: 1;
  flex-basis: auto;
}

Another CSS file that controls the custom D3 graphs has the below CSS:

.graph {
  // Set this to less than 100% because 100% auto-created a scrollbar right away 
  height: 98%;
  width: 100%;
}

Then lastly, those custom D3 files both have JavaScript that returns:

<div style={{height: "100%", width: "100%", margin: "0px"}}>
  // custom components
</div>

I hope I have provided enough information but not too much for overload to help find what may be going on.

A screenshot of the error is below – the outer scrollbar should ideally not be there, as we have inner scrollbars for the Splitter contents to be individually scrolled.

Scrollbar Issue


Clarification:

I have noticed that the scroll issue is relevant to the custom D3 graph heights. For example, when I changed the height of the custom components from 98% to 50% or 75%, the scrollbar appeared when I shrunk the browser to that part. Because the graphs were smaller than the size of their container, their bottom cut-off was visible in the Splitter, so when the browser shrunk to that link or just higher, then the outer scrollbar appeared.

Why option filter in html multiselect dropdown is not accessible?

I have

@Html.DropDownList("chk", itemsList, null, new { multiple = "multiple", @class = "multi-select wizard-change", id = "add-demo-multiselect", onchange = "addDemoHandler()" })

on a .cshtml page.
When I open the menu I can select menu items (Check all and Uncheck all) but I cannot click on filter textbox and filter the menu options. Why?
enter image description here

How to use offscreen API of google to load webpages and run normal extension content script on them

I tried many options but could not find any useful resource of how to utilize this API in order to load web pages in background. What I want is that, I want to load a certain page for example facebook.com and then let the extension run on it but all in background without user noticing. I found this API but I tried many solutions but not working.
How to achieve that goal?
https://developer.chrome.com/docs/extensions/reference/api/offscreen

Django import problem, cant import myapp but i have installed it in setings

I’m working on a Django project and encountering an ImportError when trying to import a function from my app into the urls.py file. Despite the function being defined and the app added to INSTALLED_APPS, Django cannot seem to locate the function.
Project Structure:
myproject/
manage.py
dictionarapicol/
init.py
settings.py
urls.py
asgi.py
wsgi.py
statics/
find.js

myapp/
    migrations/
        __init__.py
    templates/
       base.htm
       index.html

    __init__.py
    text_processing.py
    admin.py
    apps.py
    models.py
    tests.py
    views.py
    urls.py

myapp/urls.py:

from django.urls import path
from myapp import views
from .text_processing import process_text

urlpatterns = [
    path('', views.home, name='index'),
    path('contact/', views.contact, name='contact'),
    path('stiri_apicole/', views.login, name='stiri_apicole'),
    path('text_processing/', process_text, name='text_processing'),
]

text_processing.py

from django.http import JsonResponse
import json
from nltk.stem.snowball import SnowballStemmer
import stanza
import spacy_stanza
from rowordnet import RoWordNet

# Load dictionary data
with open('staticdictionary.json', 'r', encoding='utf-8') as file:
    dictionary_data = json.load(file)

# Initialize NLTK, spaCy, Stanza, andin stall RoWordNet
stemmer = SnowballStemmer("romanian")
nlp = spacy_stanza.load_pipeline('ro')
import rowordnet as rwn
wn = RoWordNet()

def process_text(request):
    text = request.GET.get('text', '')
    stemmed_text = stemmer.stem(text)
    doc = nlp(text)
    lemmatized_text = ' '.join([token.lemma_ for token in doc])
    synset_ids = wn.synsets(literal=text)
    synsets = [wn.synset(synset_id).definition for synset_id in synset_ids]

    return JsonResponse({
        'stemmed_text': stemmed_text,
        'lemmatized_text': lemmatized_text,
        'RoWordNet_synsets': synsets
    })

views.py

from django.shortcuts import render

# Create your views here.
def home(request):
    return render(request, 'index.html')

def contact(request):
    return render(request, 'contact.html')

def login(request):
'stiri_apicole.html')

# views.py
from .text_processing import process_text

find.js

ocument.getElementById('searchInput').addEventListener('input', function (e) {
    const searchTerm = e.target.value;

    // Send the search term to Django backend for processing
    fetch(`text_processing.py/?text=${encodeURIComponent(searchTerm)}`)
        .then(response => response.json())
        .then(data => {
            // Use processed text (stemmed, lemmatized, etc.) from backend for Fuse.js search
            // Assuming the backend sends back a similar JSON structure
            const processedText = data.lemmatized_text; // Choose between stemmed_text or lemmatized_text
            const results = fuse.search(processedText);
            displayResults(results.map(result => result.item));
        })
        .catch(error => {
            console.error("Error processing text:", error);

enter image description here

I’ve verified that init.py exists in each directory, so Python should recognize them as packages.
I’ve tried importing process_text directly in views.py and then referencing it in urls.py, but the error persists.
The app is included in INSTALLED_APPS in settings.py.

Storing Auth0 user object in React Context in nextjs Typescript

I want to store Auth0 (Auth0) user object returned by useUser inside react context API.
Here’s my userContext.tsx, the goal is to be able to access the object inside user globally in my app:

import { createContext, useContext } from "react";
import { useUser, UserProfile } from "@auth0/nextjs-auth0/client";

type UserContextType = {
  user: UserProfile | undefined;
  error: Error | undefined;
  isLoading: boolean;
};

const UserContext = createContext<UserContextType | null>(null);

export const UserProvider = ({ children }: { children: React.ReactNode }) => {
  const { user, error, isLoading } = useUser();

  return (
    <UserContext.Provider value={{ user, error, isLoading }}>
      {children}
    </UserContext.Provider>
  );
};

export const useUserContext = () => useContext(UserContext);

and my _app.tsx below:

import { AppProps } from "next/app";
import "../styles/globals.css";
import { UserProvider } from "@src/components/common/userContext";

export default function App({ Component, pageProps }: AppProps) {
  return (
    <UserProvider>
      <Component {...pageProps} />
    </UserProvider>
  );
}

The error I keep getting is:

Unhandled Runtime Error
Error: You forgot to wrap your app in <UserProvider>

While I obviously did wrap my app with

wave function collapse ignores some adjacent tile entropys

I am having trouble finding the problem with my wfc program. I don’t know where the problem is, but I suspect it is because the options for the tiles are being reset after being spliced. I have tried to fix the problem on my own as well and trying to research the problem but have come up empty. I will only include code i think is most relevent,but my full code can be found here, but I am not sure if it works.

here is how I pick a random tile to collapse. it is messy, but I have not found a more efficient way to do it yet. I hope this is not too much of a problem.

var minEntropy = 1000;
      gameArea.clear();
    unsortedGrid = [];
    sortedGrid = [];
    //fill an array with all the values of the grid
    for(i = 0; i < size; i++) {
        for(j = 0; j < size; j++) {
            if(grid[i][j].collapsed == false) {
            unsortedGrid.push(grid[i][j]);
            }
        }
    }
    //find lowest entropy
    for(i = 0; i < unsortedGrid.length; i++) {
        //test if the entropy of the viewed tile is less than minEntropy
    if(unsortedGrid[i].options.length < minEntropy) {
        //if it is, set minEntropy to the tiles entropy
        minEntropy = unsortedGrid[i].options.length;
    }
    //get all the tiles of lowest entropy
    for(i = 0; i < unsortedGrid.length; i++) {
        //if a tiles entropy is == minEntropy, add it to sortedGrid
        if(unsortedGrid[i].options.length == minEntropy) {
            
            sortedGrid.push(unsortedGrid[i]);
           
        }
    }
    }
    
    //picka random tile
tilePick = Math.floor(Math.random() * sortedGrid.length);
  if(gameArea.keys && gameArea.keys[78] && buttonPressed == false) {
      let pickedTile = grid[sortedGrid[tilePick].x][sortedGrid[tilePick].y];
      //set the options of picked tile to a  random option of it
    pickedTile.options = [Math.floor(Math.random() * pickedTile.options.length)];
    buttonPressed = true;
   
    
 
  }

  if(gameArea.keys && !gameArea.keys[78]) {
      buttonPressed = false;
  }

this evauluates the entropy of adjacent tiles and removes options that are not valid

let newGrid = []
    for(i = 0; i < size; i++) {
        newGrid[i] = [];
        for(j = 0; j < size; j++) {
          newGrid[i][j] = grid[i][j];
            if(grid[i][j].collapsed == true) {
                newGrid[i][j] = grid[i][j];
                } else {
                    let options = [blank, up, down, left, right];
                    if(j > 0) {
                        let validOptions = [];
                    let northTile = grid[i][j - 1];
                    for(let option of northTile.options) {
                        let valid = connections[option][up];
                        validOptions = validOptions.concat(valid);
                    }
                    checkValid(option,validOptions);
                    }
                    
                    if(j < size) {
                        let validOptions = [];
                    let southTile = grid[i][j + 1];
                    for(let option of southTile.options) {
                        let valid = connections[option][down];
                        validOptions = validOptions.concat(valid);
                    }
                    checkValid(option,validOptions);
                    }
                    
                    if(i > 0) {
                        let validOptions = [];
                    let eastTile = grid[i - 1][j];
                    for(let option of eastTile.options) {
                        let valid = connections[option][left];
                        validOptions = validOptions.concat(valid);
                    }
                    checkValid(option,validOptions);
                    }
                    
                    if(i < size) {
                        let validOptions = [];
                    let westTile = grid[i + 1][j];
                    for(let option of westTile.options) {
                        let valid = connections[option][right];
                        validOptions = validOptions.concat(valid);
                    }
                    checkValid(option,validOptions);
                    }
                    
                newGrid[i][j].options = options;
            }
        }
    }
    //set the grid to the newGrid
    grid = newGrid;
}

this is the function that removes the tiles


function checkValid(options,allowed) {
    for(let i =  0; i < options.length; i++) {
        if(allowed.includes(connections[options[i]]) == true) {
            options.splice(0, 1);
        }
    }
}

this consists of the majoraty of my code, but not all of it. I hope this is not too much.

How do I create an empty Targetworksheet variable and update in the loop or is there better way than this?

I’m new to programming and was playing around with Office script. Basically I have 4 worksheets with the same first column but they have different lengths. I want to it to get the column with the most rows from that worksheet and paste it into three new worksheets. The problem here is that I don’t know how to create an empty targetworksheet variable and update in the loop. I also wonder if it can be updated through the loop. Is there a better way to do this?

function main(workbook: ExcelScript.Workbook) {
  
  let maxRows = 0;
  let targetWorksheet = workbook.getWorksheet('Sheet 1');
  
  let worksheets = workbook.getWorksheets();
  for (let worksheet of worksheets) {
    let columnRange = worksheet.getRange("A:A");
    let usedRowsInColumn = columnRange.getUsedRange().getRowCount();

    if (usedRowsInColumn > maxRows) {
      maxRows = usedRowsInColumn;
      targetWorksheet = worksheet;
      
    }
    
    
    let usedRange = targetWorksheet.getUsedRange()
    let sourceRange = usedRange.getColumn(1);
    let columnvalues = sourceRange.getValues();

    let targetsheet1 = workbook.addWorksheet("sheet A");
    let targetsheet2 = workbook.addWorksheet("sheet B");
    let targetsheet3 = workbook.addWorksheet("sheet C");
    let targetsheetarray = [targetsheet1, targetsheet2, targetsheet3];
    for (let sheet of targetsheetarray) {

      let targetRange = sheet.getRange("A1:A" + columnvalues.length);
      targetRange.setValues(columnvalues)
  }
  }

        
}

it does not allow me to have an empty variable so I put something in and hope it will be updated after the loop but it didn’t.