Using vue charts js I’m having problems with line charts that have a lot of data, such as a 30-day report with each point in the line chart being one minute of each day, that is (43800 points). This way the chart takes a long time to assemble and after assembly the zoom functionality of the same get
Apexcharts line and area charts only showing tooltips if grid is enabled
I’m using vue-apexcharts wrapper (tried both 1.6.x and 1.7.0 versions) and apexcharts 4.4.0 / 4.5.0 (also tried both versions). I was able to do extensive customizations to chart visuals, but I’m stuck for days trying to show the default tooltip when the chart contents are hovered without enabling the grid option.
Here’s the desired result, except for the horizontal lines in chart’s content:

So I believed that setting chart option tooltip.enabled to true was enough for rendering that beautiful tooltip in the chart, close to the place I’m hovering, but in my charts it is not. There’s probably other settings preventing my chart from working as desired.
What I found out is that I need to set grid.show to true for tooltip to appear. If I try to set grid.yaxis.lines.show to false, to try to trick the settings to show my tooltip and not to render the grid horizontal lines, the tooltip does not show up. If I disable the yaxis lines but enable grid.xaxis.lines.show my tooltip also works, but then I have to deal with undesired vertical lines, same problem as before.
Here are the objects that I feed to my vue-apexcharts wrapper, except that I anonymized my data:
series = [
{
"name": "my y axis title",
"data": [
[
1659236400000,
"74.83"
],
[
1659841200000,
"83.75"
],
[
1660446000000,
"318.74"
],
...
[
1665284400000,
"296.60"
],
[
1665889200000,
"200.08"
],
[
1666494000000,
"192.09"
],
]
}
]
options = {
"colors": [
"#9C27B0"
],
"chart": {
"type": "line",
"toolbar": {
"show": false
},
"zoom": {
"enabled": false
}
},
"fill": {
"colors": [
"#9C27B0"
],
"opacity": 0.8,
"type": "solid"
},
"grid": { //if I disable grid, or disable both axis, my tooltip stops working
"show": true,
"xaxis": {
"lines": {
"show": false
}
},
"yaxis": {
"lines": {
"show": true
}
}
},
"legend": {
"show": false
},
"tooltip": { //I can delete tooltip object and the grid tooltip keeps working
"enabled": true,
"intersect": false
},
"annotations": {
"yaxis": [],
"xaxis": [],
"points": []
},
"stroke": {
"width": 2,
"curve": "straight",
"lineCap": "round"
},
"xaxis": {
"axisTicks": {
"show": true
},
"labels": {
"show": true,
"rotate": 0,
"hideOverlappingLabels": true
},
"convertedCatToNumeric": true
},
"yaxis": {
"max": 700,
"min": 0,
"title": {
"text": "my axis title"
},
"labels": {}
}
}
How can I access the ${orderId} and ${payment} which is present in the method chaining of the promise to my last block of promise?
const cart = ["shoes","shirts","boxers","pants"]
function creatOrder(cart){
return new Promise((resolve,reject)=>{
if(!ValidateCart(cart)){
const err = new Error('Cart is not valid')
reject(err)
}
const orderId = 'MK899'
if(orderId){
resolve(orderId)
}
})
}
function ProceedtoPayment(orderId){
return new Promise((resolve,reject)=>{
if(!orderId){
reject("Payment has failed.Please try again after some time")
}
const payment = "$500"
if(payment){
resolve(payment)
}
})
}
function UpdateWalletBalance(payment){
return new Promise((resolve,reject)=>{
if(!payment){
reject("Balance did not change since Payment failed")
}
const remaningBalance = "$100"
if(remaningBalance){
resolve(remaningBalance)
}
})
}
creatOrder(cart)
.then((orderId)=>{
console.log(orderId, "OrderId verified.Please move on to the payment")
return orderId
})
.catch((err)=>{
console.log(err.message)
})
.then((orderId)=>{
return ProceedtoPayment(orderId)
})
.then((payment)=>{
console.log(`Payment of ${payment} has been received`)
return payment
})
.catch((payment)=>{
console.log(payment)
})
.then((payment)=>{
return UpdateWalletBalance(payment)
})
.then((remaningBalance)=>{
console.log(`your remaining money is ${remaningBalance}`)
})
.catch((remaningBalance)=>{
console.log(remaningBalance)
})
function ValidateCart(){
return true
}
Method chaining: I want to access the orderId and payment which is present at the topmost of the .then in the last .then of promise. I am unable to so it is throwing me an error of ReferenceError: payment is not defined.
I tried returning the parameter and returning the function inside then block but it did not work. What could be wrong or am I missing something
Highlight new text in ckeditor 5
I’m trying to create a plugin that insert text and highlight it. This is my execute command:
execute: (label) => {
const selection = editor.model.document.selection;
if (!selection.isCollapsed) {
return;
}
const text = label || "missing placeholder";
editor.model.change((writer) => {
const insert = writer.createText(text);
// insert.setAttribute("highlight", true);
const range = editor.model.insertContent(insert);
writer.setAttribute("highlight", true, range);
});
},
The text is inserted right, but when it comes to hightlight it, browser console print this error:
Uncaught CKEditorError: optionsMap[whichHighlighter] is undefined
Read more: https://ckeditor.com/docs/ckeditor5/latest/support/error-codes.html#error-optionsMap[whichHighlighter] is undefined
getActiveOption highlightui.ts:263
_addDropdown highlightui.ts:206
updateBoundObservableProperty observablemixin.ts:728
attachBindToListeners observablemixin.ts:763
attachBindToListeners observablemixin.ts:762
fire emittermixin.ts:240
set observablemixin.ts:139
refresh highlightcommand.ts:42
Command command.ts:111
fire emittermixin.ts:240
Actually I have this configuration of CkEditor:
const editorConfig = {
toolbar: {
items: [
...
"highlight",
...
],
shouldNotGroupWhenFull: true,
},
plugins: [
...
Essentials,
...
Highlight,
...
],
extraPlugins: [MyPlugin],
I need some other configuration?
How to make vertical scrolling like Instagram Reel or Youtube Shorts
I have implemented a vertical scroll feature on my website using scroll-snap-type. The problem is, when scrolling quickly, DIVs are skipped. Can I prevent this?
It works pretty well with normal scrolling, on smartphones the scroll movement is quicker than on desktops, so its mainly a mobile friendly problem.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scrolling</title>
<style>
html {
background-color: #f5f5f5;
}
/* Der Header bleibt immer oben sichtbar */
.header {
position: fixed;
top: 0;
left: 0;
width: 100%;
background: rgba(255, 255, 255, 0.9);
padding: 15px;
text-align: center;
font-size: 1.5rem;
font-weight: bold;
z-index: 1000;
}
.videos {
margin-top: 60px; /* Platz für den fixierten Header */
}
.video-box {
display: flex;
align-items: center;
scroll-snap-align: start;
}
.video-box .inner {
box-sizing: border-box;
padding: 8px;
margin: 0 auto;
height: 100vh;
max-width: 100%;
}
</style>
</head>
<body>
<div class="header">Das ist ein Beispiel für den Header</div>
<section class="videos">
<div class="video-box">
<div class="inner">Hallo 1</div>
</div>
<div class="video-box">
<div class="inner">Hallo 2</div>
</div>
<div class="video-box">
<div class="inner">Hallo 3</div>
</div>
<div class="video-box">
<div class="inner">Hallo 4</div>
</div>
</section>
<script>
document.documentElement.style.scrollSnapType = "y mandatory";
</script>
</body>
</html>
Why am I getting 403 Forbidden Error in fetching API?
I’m using React and from getting the user’s playlist id from Spotify, I received an error of
- Failed to load resource: the server responded with a status of 403 ()
- Error fetching (the Spotify playlist id): 403
- The access token is working
- The refresh token is working
- The stored access and refresh token in local storage is working
My Code:
async function refreshAccessToken(refreshToken) {
try {
const response = await fetch("https://accounts.spotify.com/api/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: `Basic ${btoa("(client id):(client secret)")}`,
},
body: new URLSearchParams({
grant_type: "refresh_token",
refresh_token: refreshToken,
}),
});
const data = await response.json();
console.log("Spotify API Response:", data);
const accessToken = data.access_token;
const playlistResponse = await fetch("https://api.spotify.com/v1/me/playlists", {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
const playlists = await playlistResponse.json();
console.log(playlists)
if (data.access_token) {
localStorage.setItem("spotifyAccessToken", data.access_token);
return data.access_token;
}
} catch (error) {
console.error("Error refreshing token:", error);
}
}
function Token() {
const [accessToken, setAccessToken] =
useState(localStorage.getItem("spotifyAccessToken") || "");
const [refreshToken, setRefreshToken] =
useState(localStorage.getItem("spotifyRefreshToken") || "");
useEffect(() => {
console.log("Updated access token:", accessToken);
}, [accessToken]);
useEffect(() => {
const storedAccessToken = localStorage.getItem("spotifyAccessToken");
const storedRefreshToken = localStorage.getItem("spotifyRefreshToken");
console.log("Stored Access Token:", localStorage.getItem("spotifyAccessToken"));
console.log("Stored Refresh Token:", localStorage.getItem("spotifyRefreshToken"));
if (!storedAccessToken || !storedRefreshToken) {
const token = "(my access token)";
const refresh = "(my refresh token)";
localStorage.setItem("spotifyAccessToken", token);
localStorage.setItem("spotifyRefreshToken", refresh);
setAccessToken(token);
setRefreshToken(refresh);
}
if (storedRefreshToken) {
const fetchNewToken = async () => {
const newToken = await refreshAccessToken(storedRefreshToken);
if (newToken) {
setAccessToken(newToken);
localStorage.setItem("spotifyAccessToken", newToken);
}
};
fetchNewToken();
}
}, []);
useEffect(() => {
const interval = setInterval(async () => {
const newToken = await refreshAccessToken(refreshToken);
if (newToken) setAccessToken(newToken);
}, 1000 * 60 * 50);
return () => clearInterval(interval);
}, [refreshToken]);
return null;
}
export default Token;
My Home Component to access the data:
const [playlists, setPlaylists] = useState([]);
const [accessToken, setAccessToken] =
useState(localStorage.getItem("spotifyAccessToken") || "");
useEffect(() => {
const handleStorageChange = () => {
const newToken = localStorage.getItem("spotifyAccessToken");
if (newToken) setAccessToken(newToken);
};
window.addEventListener("storage", handleStorageChange);
return () => window.removeEventListener("storage", handleStorageChange);
}, []);
console.log("Access Token:", accessToken);
const playlistIds = useMemo(() => [
"2TA2qT9p2e91lGZEozyGlI",
"4Ap2xIU37l1NAShncyota",
"0Y44bc2Fd2IfbhqSPnNlTC",
"6jA8JKtuPrsNCTbnvgYkBt",
"4GX8ccKz938Q2BtF8NMdX2",
"37i9dQZF1DZ06evO2yXXGB"
], []);
useEffect(() => {
if (!accessToken) {
console.warn("No access token available. Cannot fetch playlists.");
return;
}
const fetchPlaylists = async () => {
try {
const responses = await Promise.all(
playlistIds.map(async (id) => {
const response = await fetch(`https://api.spotify.com/v1/playlists/${id}`,
{
headers: { Authorization: `Bearer ${accessToken}` },
});
if (!response.ok) {
console.warn(`Error fetching ${id}: ${response.status}
${response.statusText}`);
if (response.status === 403) return { error: "Forbidden: Check your
Spotify scopes." };
if (response.status === 401) return { error: "Unauthorized: Your token
may be expired." };
if (response.status === 429) return { error: "Rate limit exceeded. Try
again later." };
return { error: `HTTP ${response.status}` };
}
const contentType = response.headers.get("content-type");
if (!contentType || !contentType.includes("application/json")) {
console.error(`Invalid JSON response for ${id}:`, await
response.text());
return { error: "Invalid response format (Not JSON)" };
}
return await response.json();
})
);
setPlaylists(responses);
} catch (error) {
console.error("Error fetching playlists:", error);
}
};
console.log("Playlist IDs:", playlistIds);
fetchPlaylists();
setTimeout(() => fetchPlaylists(), 2000);
}, [accessToken, playlistIds]);
Failed to load resource: the server responded with a status of 403 ()
Error fetching (the Spotify playlist id): 403
How to display Portable Text block content images in SvelteKit
I’m trying to render a blog post from Sanity Studio in my SvelteKit project.
Currently, all of the text etc is being displayed, but images within the block content aren’t. Below is what I have tried so far:
Here is my /blog/[slug]/+page.svelte file currently:
<script lang="ts">
import { PortableText } from "@portabletext/svelte";
import BodyImage from "$lib/components/BodyImage.svelte";
export let data;
const { post } = data;
</script>
<article>
<h1>{post.title}</h1>
<PortableText
value={ post.body }
components={{
image: BodyImage
}}
/>
</article>
The /blog/[slug]/+page.ts file:
import client from "$lib/sanity/client";
export async function load({ params }) {
const { slug } = params;
const post = await client.fetch(
/* groq */ `
*[_type == "post" && slug.current == $slug][0]{
title,
body[]{
...,
_type == "image" => {
asset,
alt
}
},
author,
publishedAt,
_updatedAt
}
`,
{ slug }
);
return { post };
}
The BodyImage.svelte component:
<script lang="ts">
import client from '$lib/sanity/client';
import imageUrlBuilder from '@sanity/image-url';
export let value;
const builder = imageUrlBuilder(client);
const imageUrl = builder.image(value.asset).width(800).url();
</script>
<img src="{imageUrl}" alt="{value.alt}" />
How can I get the images to render? There’s no errors in my console or anything, and the block content object being retrieved in the main +page.svelte file definitely has the images inside as when I console.log(post), I can see images within the portable text object, along with their asset and alt values. I think the issue may be to do with getting those values to BodyImage.svelte? When I update BodyImage.svelte with these console logs:
<script lang="ts">
import client from '$lib/sanity/client';
import imageUrlBuilder from '@sanity/image-url';
export let value;
console.log("Alt: " + value.alt); // Added this
const builder = imageUrlBuilder(client);
const imageUrl = builder.image(value).width(800).url();
console.log("Image URL:" + imageUrl); // Added this
</script>
<img src="{imageUrl}" alt="{value.alt}" />
Nothing is logged to the console, but I do get this error message:
Unknown block type "image", specify a component for it in the 'components.types' prop, although I’m not sure what to do next.
Thanks 🙂
How to get React app that works in Sandbox to work on desktop?
I created a React app on Windows 10 localhost but couldn’t get it to work, so created same app on Sandbox and got it to work. Now I want to port that code back to desktop, but still not working.
Here is the Sandbox working app:
https://codesandbox.io/p/sandbox/toolpad-dashboard-d5p6c6
What I was trying to do was to navigate to child pages without them also being in the left navigation bar, but to have the path still show up in the Breadcrumbs. If you append
/about/contact
to the url, you’ll see it successfully does that.
But now how to get it working on desktop localhost? I copy the code over but first problem is something like
“A required html file in the public folder is missing“
So I add index.html file to public folder which ends in
<body>
<div id="root"></div>
<script type="module" src="/src/index.js"></script>
</body>
Why is it not needed in Sandbox?
But the next error says
Failed to load module script: Expected a JavaScript module script but
the server responded with a MIME type of “text/html”. Strict MIME type
checking is enforced for module scripts per HTML spec.
So I replace type=”module” with type = “text/html” which gets rid of that error.
Now the next error is:
Uncaught Error: useLocation() may be used only in the context of a
component.
The useLocation hook is used only once in the code, and it is within a Router component. It’s in the BasicBreadcrumbs() function.
If I comment out that code and replace with a hardcoded pathnames array like this:
/*
const location = useLocation();
console.log("location=", location);
const pathnames = location.pathname.split("/").filter((x) => x);
console.log("pathnames=", pathnames);
*/
const pathnames = ['about', 'contact'];
which is the same output from the console in the Sandbox, it still produces the same useLocation error.
What am I doing wrong? How do other people get their Sandbox code to work on desktop?
What is the simplest way to make JS generate the same, file-name-friendly datetime format that my C# is generating? [closed]
I currently have C# code that generates a file name containing a datetime pulled from an object property. I am happy with the formatting of this file name.
Elsewhere, I have JavaScript code that needs to find that file on the server, so it needs to be able to generate the same file name string based on the same object property.
I have been mostly successful, but not completely…
I have found that I have to manually add leading zeroes in the JavaScript version. It seems a bit tedious, but if it’s necessary, so be it.
However, I have also found that the JavaScript version is inconsistent: when I debug the code on my computer, it returns the local time, but when I deployed the code and someone else used the feature on a live site, the JavaScript returned the UTC time! How is it even possible for it to be inconsistent in that way?! [Note: Yes, this person is in the same time zone as me.]
Here is my C# code:
fileName += obj.ActualStartTime.Value.DateTime.ToString("yyyyMMdd_HH'h'mm'm'ss's'");
And here is my JS code:
let dto = obj.ActualStartTime;
let monthValue = addLeadingZeroIfNeeded((dto.getMonth() + 1).toString());
let dayValue = addLeadingZeroIfNeeded(dto.getDate().toString());
let hourValue = addLeadingZeroIfNeeded(dto.getHours());
let minValue = addLeadingZeroIfNeeded(dto.getMinutes());
let secValue = addLeadingZeroIfNeeded(dto.getSeconds());
let modifiedDto = dto.getFullYear().toString() + monthValue + dayValue
+ "_" + hourValue + "h" + minValue + "m" + secValue + "s";
fileName += modifiedDto;
function addLeadingZeroIfNeeded(numericString) {
return ("0" + numericString).slice(-2);
}
Please let me know the simplest way to get the JavaScript code to generate a string that matches the C# string, ensuring the JavaScript always uses local time.
Note: The data comes to JavaScript by way of an ajax call to an API, so the ActualStartTime property of an object is received like this:
"ActualStartTime": "2025-03-20T12:12:07.4854532-04:00"
Wait for a loop to complete before fs.writeFile
I try to write a chapter syntax converter in nodejs (I’m beginner)
How to wait for first bloc to complete (output exist) before execute fs.writeFile.
Because this way, I have an unwanted “undefined” in my output.
"use strict";
const fs = require('fs');
try {
var data = fs.readFileSync('./chap_source.txt', {encoding: 'utf8'});
var index, name, chap_int, chap_string, output;
data = data.trim();
data = data.split("rn");
for (let i=0; i<data.length; i++) {
data[i] = data[i].split(/(?<=^.{8})/);
index = data[i][0];
name = data[i][1].slice(1);
chap_int = i+1;
chap_string = chap_int.toLocaleString('en-US', { minimumIntegerDigits: 2, useGrouping: false });
output += "CHAPTER" + chap_string + "=" + index + ".000nCHAPTER" + chap_string + "NAME=" + name + "n";
}
}
catch (err) {
console.log("Error: ", err.stack);
}
fs.writeFile('./chap_ok.txt', output, err => {
if (err) { console.error(err); }
else { }
});
Can I handle failure when it does not find an element?
Basically I want to check for the existence of an specific element,
If it finds it, do someting, if it doesn’t find do something else.
try {
cy.get('[role="alert"] span', { timeout: 3000 }).should('not.exist');
return false;
} catch (error) {
return true;
}
But it seems Cypress handles errors internally and it does not reach my return statements.
Is there a way that I can do this, and without overriding all error using Cypress.on(“fail”)?
I tried handling in using try/catch, with then, checking the element length..
return cy.get('[role="alert"] span', { timeout: 5000 }).then(($el) => {
if ($el.length > 0) {
cy.log('Element found');
return true;
} else {
cy.log('Element not found');
return false;
}
});
Flask appears to automatically add a nonce to my CSP directives. Can this be disabled?
Goal:
From a Flask server, I wish to use the url_for() function inside javascript files to calculate the proper URL.
Problem:
Flask.render_template() only touches the HTML template file, so Flask recommends you use inline <script> blocks (Flask Render Template Documenation) and call url_for() to save a script base variable which you can then access in other pure javascript modules that aren’t processed by render_template().
Unfortunately, without CSP enabled, modern browsers will completely ignore inline <script> tags. It is therefore necessary to create a Content Security Profile, which I did as follows, trying to make the most permissive policy ever:
@app.after_request
def add_csp(response):
response.headers['Content-Security-Policy'] = ("default-src * data: blob: filesystem: about: "
"ws: wss: 'unsafe-inline' 'unsafe-eval' 'unsafe-dynamic'; script-src * "
"'unsafe-inline' 'unsafe-eval' 'unsafe-hash'; connect-src * 'unsafe-inline'; "
"img-src * data: blob: "'unsafe-inline'; frame-src *; style-src * data: "
"blob: 'unsafe-inline';font-src * data: blob: 'unsafe-inline';")
return response
That should work. I’ve allowed everything. (Everything I can find, anyway) Unfortunately, when running my script, I see this:
Content-Security-Policy: The page’s settings blocked an inline script (script-src-elem) from being executed because it violates the following directive: “script-src * 'unsafe-inline' 'unsafe-eval' 'unsafe-hash' 'nonce-bW96LWV4dGVuc2lvbjovL2E0ZTMxZmFjLTI5NjQtNDUxMC1iNDhjLTExOTYyODdkMWMzZC8='” index.html:14:36
This is the script it is complaining about:
<script type="text/javascript">
const GRAY_LIGHT = {{ url_for('static',filename='images/gray.png') }};
const RED_LIGHT = {{ url_for('static',filename='images/red.png') }};
console.log("RED_LIGHT = "+RED_LIGHT+", GRAY_LIGHT = "+GRAY_LIGHT);
</script>
How can something not match * and ‘unsafe inline’? After struggling for many hours, I came upon this page: (Mozilla CSP documentation)
If a directive contains a nonce and unsafe-inline, then the browser ignores unsafe-inline.
Now, since I didn’t add the nonce value that Firefox is complaining about, it seems that Flask must have put it there. But I can find no documentation that describes this behavior, nor how to disable it.
Is anyone familiar with Flask and know how to prevent it from adding a nonce to my CSP?
Or is Flask just no longer compatible with modern browsers? All I really wanted to do was use the url_for() function, and I’ve spent over 2 days trying to make that simple thing happen.
Any advice appreciated. I’ve never dealt with CSP issues before.
Slight curve in text CSS or JS [closed]
I want to use dynamic javascript (innerhtml) in a form to send data via POST to another file
I currently working on a pizza-ordering-website. Right now I’m on the page where you can change the pizzas, change the prices or delete or add toppings. My current problem is the add toppings. I have a dropdown which when the user chooses a topping dynamically add a position for it.
HTML:
<form action="includes/edithandler.inc.php" method="POST" enctype="multipart/form-data">
[...]
<div class="edit-mode" style="display:none;">
[...]
Neue Beläge hinzufügen:
<select class="belag">
<option value="">-</option>
<?php foreach ($belaege as $belag) { ?>
<option value="<?php echo htmlspecialchars($belag['ID']); ?>">
<?php echo htmlspecialchars($belag['Belagbezeichnung']); ?>
</option>
<?php } ?>
</select>
<div id="selected-belaege-<?php echo $index; ?>"></div>
</div>
[...]
</form>
My Javascript:
document.addEventListener("DOMContentLoaded", function () {
document.querySelectorAll(".belag").forEach(selectElement => {
selectElement.addEventListener("change", function () {
const selectedValue = this.value;
const selectedText = this.options[this.selectedIndex].text;
const containerId = this.closest("td").querySelector('[id^="selected-belaege"]').id;
const selectedContainer = document.getElementById(containerId);
if (selectedValue && !selectedContainer.querySelector(`[data-id="${selectedValue}"]`)) {
const item = document.createElement("div");
item.setAttribute("data-id", selectedValue);
item.innerHTML = `<input type="hidden" name="belaege-gewaehlt[]" value="${selectedValue}">
<span class="trash-icon"><button type="button" class="remove-belag">🗑</button>
<span class="trash-icon">🗑</span>
<span class="belag-text">${selectedText}</span>`;
selectedContainer.appendChild(item);
item.querySelector(".remove-belag").addEventListener("click", function () {
item.remove();
});
}
this.value = ""; // Setzt das Dropdown zurück
});
});
});
The screenshot from my page before submitting:
Screenshot from my browser showing the hidden input
My Output for my POST:
“Array ( [index] => 1 [pizza_name] => Margherita [price] => 11.00 [description] => Ein Klassiker der italienischen Küche! Unsere traditionelle Pizza Margherita überzeugt mit einem knusprig-dünnen Boden, fruchtiger Tomatensauce aus sonnengereiften Tomaten, zart schmelzendem Mozzarella und frischem Basilikum. Verfeinert mit einem Hauch von nativem Olivenöl extra – einfach köstlich! )”
The “belaege-gewaehlt[]” from innerHTML are completely ignored.
Is my approach completely wrong and this combination “JS with POST” simply doesn’t work?
I tried changing “belaege-gewaehlt[]” to “belaege-gewaehlt” also doesn’t show up in the POST.
How to Automatically Detect User’s Language in Botpress WebChat Before Initialization?
I am integrating Botpress WebChat on our WordPress site and want to automatically detect the user’s language based on the website’s attribute.
What I Have Tried So Far:
- Passed Language Directly in
init()
I attempted to detect the language using JavaScript before callinginit()
let siteLang = document.documentElement.lang || "en";
siteLang = siteLang.split("-")[0];
window.botpressWebChat.init({
"botId": "XXX",
"clientId": "XXX",
"host": "https://cdn.botpress.cloud/webchat",
"config": {
"locale": siteLang,
"extra": { "lang": siteLang },
"session": { "lang": siteLang }
}
});
Expected: The chatbot should start in the detected language.
Isue: Botprss WebChat always defaults to (en), even when siteLang is “de”.
- Used
webchat:onLoadEvent (Suggested on Botpress Discord)
To ensure WebChat was fully ready before setting the language
window.botpressWebChat.onEvent(
function () {
console.log("✅ Botpress WebChat Loaded! Detecting language...");
let selectedLang = document.documentElement.lang.split("-")[0] || "en";
window.botpressWebChat.init({
"botId": "xxx",
"clientId": "xxx",
"host": "https://cdn.botpress.cloud/webchat",
"config": {
"locale": selectedLang,
"extra": { "lang": selectedLang },
"session": { "lang": selectedLang }
}
});
console.log("✅ Sent to Botpress:", selectedLang);
},
"webchat:onLoad"
);
- Passed Language in
session.extraBefore Initialization
I attempted to store the language before callinginit():
window.botpressWebChat.init({
"botId": "xxx",
"clientId": "xxx",
"host": "https://cdn.botpress.cloud/webchat",
"config": {
"session": { "extra": { "lang": document.documentElement.lang.split("-")[0] || "en" } },
"locale": document.documentElement.lang.split("-")[0] || "en"
}
});
The chatbot should recognize session.extra.lang and start in the correct language. But id doesn’t.
Questions:
- How does Botpress WebChat determine its default language?
- What is the correct way to pass the detected language to WebChat so it uses
it correctly? - Is there a way to update the language dynamically
after initialization? - Does Botpress require additional configuration
(e.g., within the Botpress Studio) to recognize session.extra.lang?
Any help or insights would be greatly appreciated!
