TypeError: Cannot set properties of undefined (setting ‘FIRST_NAME’) in Google Apps Script

To send out language dependent emails from Google Sheets, we have the following:

const EMAIL = [
  {
    LANGUAGE : 'NL',
    HTML_TEMPLATE_FILE : 'MAIL_Invoice_NL',
  },
  {
    LANGUAGE : 'EN',
    HTML_TEMPLATE_FILE : 'MAIL_Invoice_EN',
  }
]

EMAIL.forEach((item)=> {
  item.html = HtmlService.createTemplateFromFile(item.HTML_TEMPLATE_FILE)
})

const customer = {
  language : 'EN'
}

const mail = EMAIL.filter((item) => {
  return item.LANGUAGE == customer.language
})

mail.html.FIRST_NAME = customer.firstname

Throws error:

TypeError: Cannot set properties of undefined (setting ‘FIRST_NAME’)

Things we’ve tried:

hardcoding works fine:

const html = HtmlService.createTemplateFromFile(EMAIL[0].HTML_TEMPLATE_FILE)
html.FIRST_NAME = customer.firstname

initializing the variables first fails too:

const EMAIL = [
  {
    LANGUAGE : 'NL',
    HTML_TEMPLATE_FILE : 'MAIL_Invoice_NL',
    html : '',
  },
  {
    LANGUAGE : 'EN',
    HTML_TEMPLATE_FILE : 'MAIL_Invoice_EN',
    html : '',
  }
]

What are we missing here?

How to make an HTTP request from my frontend to an internal private backend

I have a frontend server configured with nuxt (vue), and a backend configured with fastapi.
The frontend is exposed to the outside world on ports 80 and 443,
The backend is not exposed.

When a user makes a request to the frontend, the frontend responds in most cases.
But for some requests that require the backend, I need to create a new request from the frontend to the backend.

I tried to use axios, but the request was delivered with the frontend’s URL intact. Changing the baseURL doesn’t make sense because the backend URL is not exposed to the outside world. (it’s something like host.docker.internal)

How can I get the frontend to generate a new HTTP request to the backend to send data back and forth based on the user’s request?

Importing a Javascript Module is Throwing Errors in DotNet IIS

I’m having a strange problem when trying to do the basic Import of a Polyfill inside a .vbhtml File using DotNet (Referenced from : https://github.com/oddbird/css-anchor-positioning)

@Html.Raw("<script type='module'>if(!('anchorName' in document.documentElement.style)) { import('https://unpkg.com/@oddbird/css-anchor-positioning'); }</script>")

It seems to throw a bunch of Javascript Errors but it works fine when being used in a Regular
Local HTML File, I wonder if I have to do something differently when trying to do this in a .vbhtml File

Loading app.js correctly in my index.html [closed]

I’m currently building my website using HTML, CSS and JS. My JS file (app.js) doesn’t seem to be loading, as the animations are not showing on the website. Can someone help me? Am I loading my app.js file incorrectly? Let me know if you all need more details.

This is my index.html:

<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./styles.css"/>
<link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet'>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&family=Roboto:wght@400;500&display=swap" rel="stylesheet">
<title>HomePage</title>

<script
src="https://code.jquery.com/jquery-3.3.1.js"
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
crossorigin="anonymous">
</script>
<script> 
$(function(){
$("#header").load("header.html"); 
$("#footer").load("footer.html"); 
});
</script> 
</head>

<body>
<div class="page">
    <div id="header"></div>
    <div class="about">
        <div class="about-text">
            <h1 class="title">RITHVIK VADDADI</h1>
            <span class="Intro">Cyber Security Enthusiast | Toastmasters | Cardistry</span>
        </div>
        <div class="arrow-wrap">
            <div class="arrow-down arrow"></div>
            <div class="arrow-down arrow"></div>
        </div>
      </div>

      <div class="overview">
        <h2>About me</h2>
        <div class="OV">
            <img src="Images/My PFP.jpg" alt="Avatar" class="Avatar">
            <div class="text-buttons">
                <p class="description">Hello, I am Rithvik Vaddadi, a current NSF with a diploma in Cyber Security and Digital Forensics. Drawn to the world of computers, I aspire to make people's lives easier and protect them from cyber attacks with the help of technology around us. As a problem solver, I am known to use my creative and critical thinking skills when providing solutions in my past leadership roles and projects. When involved in projects, I tend to notice people's strengths and weaknesses and assign them to roles where their potential would be fully maximized in the project. When my mind is fixed on a goal, I dedicate my energy and focus to achieving the goal.</p>
                <div class="buttons">
                    <a href="https://docs.google.com/document/d/1ZjzHjOgWy2RH1Lz27aZAih7ZEqYFOU-0mNnstJ93LtU/edit?usp=sharing" target="_blank"></a>
                        <button>View My Resume</button>
                    </a>
                    <a href="https://www.linkedin.com/in/rithvik-vaddadi-8469471a9/" target="_blank">
                        <button>View My LinkedIn</button>
                    </a>
                </div>
            </div>
        </div>
        <section class="education-section">
          <h2>My Education Journey</h2>
          <div class="cards-container">
              <div class="card" id="army-card">
                  <div class="card-inner">
                      <div class="card-front">
                          <h3>Army</h3>
                      </div>
                      <div class="card-back">
                          <h3>SAF Singapore Armed Forces</h3>
                          <p>Vocation: 5SIR Infantry Soldier as a General Purpose Machine Gun (GPMG) Gunner and Platoon 2ic <br>
                            Rank: Corporal <br>
                            ORD Date: 2nd May 2025<br>
                            Overseas involvement: Brunei, Malaysia, Australia. <br>
                            Achievements: Due to my exceptional combat fitness and leadership, I was chosen to represent my battalion in a Joint Adventure Training (JAT) with the Malaysian Army Rangers. <br>
                            Skills: Proficient in handling GPMG, SAR21, and LMG. Trained in drone flying. (DJI Mavick Pro, Vesper, Cetus)
                          </p>
                          <div class="gallery-wrap">
                            <img src="Images/back.png" class="backBtn">
                            <div class="gallery">
                                <div>
                                    <span><img src="Images/Army1.jpg"></span>
                                    <span><img src="Images/Army2.jpg"></span>
                                    <span><img src="Images/Army4.jpg"></span>
                                </div>
                                <div>
                                    <span><img src="Images/Army3.jpg"></span>
                                    <span><img src="Images/Army5.jpg"></span>
                                    <span><img src="Images/My PFP.jpg"></span>
                                </div>
                            </div>
                            <img src="Images/front.png" class="nextBtn">
                          </div>
                          <span class="close-btn"><img src="Images/X.png" alt="close"></span>
                      </div>
                  </div>
              </div>
              <div class="card" id="poly-card">
                  <div class="card-inner">
                      <div class="card-front">
                          <h3>Polytechnic</h3>
                      </div>
                      <div class="card-back">
                          <h3>Ngee Ann Polytechnic</h3>
                          <p>Course: Cyber Security and Digital Forensics<br>
                            CCAs: Vice-President and Student Advisor of NP's Toastmasters Club, Head of Logistics for NP's ICTSociety, Tchoukball<br>
                            Achievements: I led a 2-hour group focus session with the Minister of Education, Mr Chan Chun Sing, about the future of Singapore's education, housing, etc. 
                            Showcased my capstone project at Singapore International Cyber Week X Govware (SICW 2022).
                            Spearheaded a YEP-GO overseas cross-cultural program with a school in Ladakh, India for a week.
                            </p>
                          <div class="gallery-wrap">
                            <img src="Images/back.png" class="backBtn">
                            <div class="gallery">
                                <div>
                                    <span><img src="Images/Dip2.jpg"></span>
                                    <span><img src="Images/Dip5.jpg"></span>
                                    <span><img src="Images/Dip6.jpg"></span>
                                </div>
                                <div>
                                    <span><img src="Images/Dip3.jpg"></span>
                                    <span><img src="Images/Dip1.jpg"></span>
                                    <span><img src="Images/Dip7.jpg"></span>
                                </div>
                            </div>
                            <img src="Images/front.png" class="nextBtn">
                          </div>
                          <span class="close-btn"><img src="Images/X.png" alt="close"></span>
                        </div>
                    </div>
              </div>
              <div class="card" id="school-card">
                  <div class="card-inner">
                      <div class="card-front">
                          <h3>Secondary School</h3>
                      </div>
                      <div class="card-back">
                        <h3>Bukit Batok Secondary School</h3>
                        <p>Stream: Express double science (Physics and Chemistry)<br>
                          O-Level L1R5: 10 L1R4: 7<br>
                          CCAs: Badminton (Vice-Captain), Student Council (Vice President), Lewis House Captain
                          Achievements: I attended a photoshoot with my school's principle for our school website and magazine. This event was a testament to the contributions and impact I made in the school's community. Involved in many volunteer programs such as donating rice, beach clean-ups, etc.

                        </p>
                        <div class="gallery-wrap">
                            <img src="Images/back.png" class="backBtn">
                            <div class="gallery">
                                <div>
                                    <span><img src="Images/Secondary1.jpg"></span>
                                    <span><img src="Images/Secondary2.jpg"></span>
                                    <span><img src="Images/Secondary3.jpg"></span>
                                </div>
                                <div>
                                    <span><img src="Images/Secondary4.jpg"></span>
                                    <span><img src="Images/Secondary5.jpg"></span>
                                    <span><img src="Images/Secondary6.jpg"></span>
                                </div>
                            </div>
                            <img src="Images/front.png" class="nextBtn">
                          </div>
                        <span class="close-btn"><img src="Images/X.png" alt="close"></span>
                      </div>
                  </div>
              </div>
          </div>
      </section>
      <div id="footer"></div>
      </div>
      
</div>
<script src="app.js"></script>
</body>
</html>

This is my app.js file:

const header = document.querySelector('.header');
window.addEventListener("scroll", () => {
if(window.scrollY >= 150){
    header.classList.add("scrolled");
} else if(window.scrollY <=100) {
    header.classList.remove("scrolled");
}
});

//Hamburger Toggle for mobile 
const menuIcon = document.getElementById('menu-icon');
const navMenu = document.getElementById('navMenu');

menuIcon.addEventListener('click', () => {
navMenu.classList.toggle('show');
});

window.addEventListener('load', function(){
this.document.querySelector('.arrow-wrap').computedStyleMap.display = 'block';
});

// Select all cards
const cards = document.querySelectorAll('.card');

// Add event listeners to each card
cards.forEach(card => {
const cardInner = card.querySelector('.card-inner');

// Only flip when you click the card front
const cardFront = card.querySelector('.card-front');
cardFront.addEventListener('click', function (e) {
    e.stopPropagation(); // Prevent the event from propagating to the document
    cardInner.classList.toggle('flip'); // Flip the card
    card.classList.toggle('expand'); // Expand the card
});

// Close button logic (for collapsing and un-flipping)
const closeButton = card.querySelector('.close-btn');
closeButton.addEventListener('click', function (e) {
    e.stopPropagation(); // Prevent clicking the card behind the button
    cardInner.classList.remove('flip'); // Remove the flip effect
    card.classList.remove('expand'); // Collapse the card
});
});



const nextButtons = document.querySelectorAll('.nextBtn');
const backButtons = document.querySelectorAll('.backBtn');
const galleries = document.querySelectorAll('.gallery');

// Function to scroll the gallery
function scrollGallery(direction, gallery) {
const scrollAmount = gallery.clientWidth;
gallery.scrollBy({ left: direction * scrollAmount, behavior: 'smooth' });
}

// Adding event listeners to each pair of buttons
nextButtons.forEach((btn, index) => {
btn.addEventListener('click', () => scrollGallery(1, galleries[index]));
});

backButtons.forEach((btn, index) => {
btn.addEventListener('click', () => scrollGallery(-1, galleries[index]));
});


window.addEventListener('scroll', function() {
const footer = document.querySelector('.footer');
const scrollable = document.documentElement.scrollHeight - window.innerHeight;
const scrolled = window.scrollY;

if (Math.ceil(scrolled) >= scrollable) {
    footer.classList.add('expanded'); // Expand footer when at the bottom
} else {
    footer.classList.remove('expanded'); // Hide footer when not at the bottom
}
});

How to stringify json object’s square brackets inside braces for http get?

I have question about good practise coding.
I have a chrome extension which is supposed to track tab events for dev purpose.
Then the service worker send the json.stringified string embedded in http get to server php code which writes those events to a file to be immediately read with PhpStorm.
On browser I can step debug the service worker and
all works nicely until the highlighted event produces a string that strigify cannot handle:

“{“name”:”highlighted”,”payload”:{“tabIds”:[1875383020],”windowId”:1875382695}}”

Next point I can monitor the string is on server’s php debugger which tells:

{“name”:”highlighted”,”payload”:{“tabIds”: => Array

So square brackets seem to brake the strigify in this case.
How would you formulate a service worker’s helper function to make the stringify work?

I see there is only one element in array but I’m looking for solution with possibly many of them for code to be reused.

Reverse an easing function

I’m trying to make an exponential slider where it increases values slowly at first and ramps up towards the end. I used an easing function to convert a linear value by applying a ease-in-quad function.

For example, say a slider starts at 200 and goes till 500 and user moves the slider to the center. The linear value at 50% would be 350. I calculate the percentage progress of the slider – in this case 50% and I apply my function on it

let t = 50,
    b = 200,
    c = 150, // 350 - 200
    d = 100;

return c * (t /= d) * t + b; // 237.5

This is all good. But the problem is, elsewhere I need to convert this value of 237.5 back to 350. I tried reversing the calculation but I need both t and c. If I have one, I’ll know the other.

I also tried running an ease-out-quad on it but that didn’t work either

let t = 18.75, // 200 + 18.75% = 237.5
    b = 200,
    c = 37.5, // 237.5 - 200
    d = 100;

return -c * (t /= d) * (t - 2) + b; // 212.74

The answer is not what I was expecting. Is this even possible to do?

How to Implement Adaptive Card Designer

Description:
I’m trying to integrate the Adaptive Card Designer with the Monaco Editor. However, I’m encountering some issues with module loading, such as:

Error: es.global-this.js:7 Uncaught TypeError: $ is not a function

Error: “Uncaught Error: Can only have one anonymous define call per script file.”

Error: “ACDesigner is not defined.”

Here’s my current setup. I’ve included all necessary scripts via CDNs or modules install
install modules => “adaptivecards-designer”: “2.4.4”
“monaco-editor”: “^0.29.1”
node version => 18.18.1

function setup() {
      const monaco = await loader.init();
      // ACDesigner.CardDesigner.onProcessMarkdown = (text, result) => {
      //   result.outputHtml = new markdownit().render(text);
      //   result.didProcess = true;
      // };
      ACDesigner.GlobalSettings.showVersionPicker = true;
      ACDesigner.GlobalSettings.enableDataBindingSupport = true;
      ACDesigner.GlobalSettings.showDataStructureToolbox = false;
      ACDesigner.GlobalSettings.showSampleDataEditorToolbox = true;

      // /* Configure toolbox titles */
      // ACDesigner.Strings.toolboxes.cardEditor.title = "WORKELEVAE";

      let designer = new ACDesigner.CardDesigner([
        new ACDesigner.WebChatContainer(
          "Bot Framework WebChat",
          "containers/webchat-container.css"
        ),
        new ACDesigner.TeamsContainer(
          "Teams Dark Container",
          "containers/teams-container.css"
        ),
        new ACDesigner.TeamsContainer(
          "Teams Light Container",
          "containers/teams-container.css"
        ),
        new ACDesigner.DefaultContainer(
          "Default Container",
          "containers/teams-container.css"
        )
      ]);

      // Modify the UI with custom elements
      // let wgButton = new ACDesigner.ToolbarButton(
      //   "Save",
      //   "Save",
      //   null,
      //   (sender) => {
      //     // alert("Workgrid says hi!");
      //     // console.log(designer.getBoundCard()) # To get the Card Value
      //     // console.log(designer.getCard())  # Same to get the Card Value
      //     console.log(designer.getCard())
      //     // var data1 = { domain: "progressive", Bot_name: botType, Channel: ChannelName, template: TemplateName, Notification: Notification, json: designer.getCard(), card_type: "Bot Notification" }
      //     // console.log(data1);
      //   }
      // );
      // wgButton.separator = true;
      // wgButton.style = "background-color: #2D7BB7";
      // designer.toolbar.insertElementAfter(
      //   wgButton,
      //   ACDesigner.CardDesigner.ToolbarCommands.HostAppPicker
      // );
      
      // Attach the designer into the DOM
      designer.bindingPreviewMode = ACDesigner.BindingPreviewMode.SampleData;
      designer.attachTo(document.getElementById("editor"));
      designer.monacoModuleLoaded(monaco); // :D
      // setmonocovalue(designer.monacoModuleLoaded(monaco))
      setCardjson(designer.getCard())
    }
    setup();

How can I listen to a form reset event in react-hook-form?

I’m using react-hook-form in my React project and I need to perform some actions when the form is reset.
However, I can’t find a way to listen to the form’s reset event and since I’m inside the child I don’t have direct access to the reset button event.

In this case I wanted to reset the check state that is not in the values to submit
Here is a simplified version of my form setup:

import { useState } from 'react';
import { FormProvider, useForm, useFormContext } from 'react-hook-form';

const initialValues = { firstName: "empty", lastName: "empty" };
function MyForm() {
    const methods = useForm({ defaultValues: { ...initialValues } });

    const onSubmit = data => {
        console.log(data);
    };

    return (
        <FormProvider {...methods}>
            <CustomContent />
            <button type="button" onClick={methods.handleSubmit(onSubmit)}>Submit</button>
            <button type="button" onClick={() => methods.reset({ ...initialValues })}>Reset</button>
        </FormProvider >
    );
}

function CustomContent() {
    const { register } = useFormContext();

    const [isChecked, setIsChecked] = useState(false);

    return (
        <div>
            <input {...register('firstName')} placeholder="First Name" />

            <input {...register('lastName')} placeholder="Last Name" />

            <label >
                <input type="checkbox" checked={isChecked} onChange={() => setIsChecked((prev) => !prev)} />

                <span>Check me</span>
            </label>
        </div>
    );
}

export default MyForm;

Is there an event, callback, or hook in react-hook-form that allows me to listen specifically to the form reset action so that I can perform additional tasks (like resetting other states or triggering side effects or changing fields not saved in the form)?

I tried the solution proposed here Is there a way to listen to a form reset? – React Hook Form.

useEffect(() => {
        if (isFirstRender.current) {
            isFirstRender.current = false;
            return;
        }
        if (!isSubmitted && !isDirty) {
            setIsChecked(false);
        }
    }, [isDirty]);

But it didn’t work because it only works if you change a field that has been registered and it doesn’t work for this case.

Any guidance or suggestions would be appreciated. Thank you!

Invalid AMP Due to Google AMP Cache

​​I have the url https://www.olx.co.id/amp/mobil-bekas_c198/q-pajero-sport-sunroof.

When I inspect the browser, the snippet below didn’t exist. But when I checked through Google Search Console (AMP), it exists. Is this because of AMP Cache process? This generated script causing the AMP is invalid. How to treat this?

<link rel="stylesheet" type="text/css"  href="/Op1-23tiJ/WAFl/Hrj7A/bz5w/fG81LQ/FVYMVy/YiLiJY">
 <script  src="/Op1-23tiJ/WAFl/Hrj7A/bz5w/fG81LQ/CE06Tx/1LC08o" async defer></script>

It can be reproduce at https://search.google.com/test/amp/result?id=CdGZ94BNzb614QiCmcxA2A, then compare it by inspect the element in the browser.

Scan Result 1
Scan Result 2

I’ve tried to add <meta name="robots" content="noarchive, nocache"> in my header file, but it didn’t work. I’ve also created the middleware to handle the DOM, but still it looks fine when I inspect the element in the browser, but when I validated it in Google Search Console, the injected script like in the desc column, exist.

/* eslint-disable no-console */
/* eslint-disable prefer-reflect */
/* eslint-disable prefer-rest-params */
const { JSDOM } = require('jsdom');

function stringifyQueryParam(url, cookies) {
  if (!url) {
    return '';
  }

  const result = { parameters: {} };

  try {
    // read cookie named 'onap'
    // split the cookie value by '-' and get the first part
    const onap = cookies.onap.split('-')[0];

    // add onap to the query parameters with 'sl' as the key
    result.parameters.sl = onap;
  } catch (error) {
    console.error('Error occurred while reading cookie:', error);
  }

  const queryString = url.split('?')[1];
  if (queryString) {
    const pairs = queryString.split('&');
    pairs.forEach(pair => {
      const [ key, value ] = pair.split('=');
      result.parameters[decodeURIComponent(key)] = decodeURIComponent(value);
    });
  }

  const jsonString = JSON.stringify(result);
  return jsonString; // return the stringified query parameter
}

const domManipulation = (req, res, next) => {
  const originalSend = res.send;

  res.send = function (content) {
    // Only process HTML responses
    if (typeof content === 'string' && content.includes('<!doctype html>')) {
      const dom = new JSDOM(content, {
        runScripts: 'outside-only',
        resources: 'usable'
      });
      const { document } = dom.window;

      const trackingPixel = document.querySelector('#trackingPixel');
      const src = trackingPixel.getAttribute('src');
      const stringifiedQueryParam = stringifyQueryParam(src, req.cookies);

      // Split the URL to separate the base URL and the query parameters
      const [ baseUrl ] = src.split('?');

      // Manually construct the new URL with the stringified query parameters
      const newUrl = `${baseUrl}?trackingevent=${encodeURIComponent(stringifiedQueryParam)}`;

      trackingPixel.setAttribute('src', newUrl);

      // Find and move AMP cache scripts from body to head, excluding those with type="application/json"
      const scripts = document.body.querySelectorAll('script');
      scripts.forEach(script => {
        if (script.type !== 'application/json') {
          const clonedScript = script.cloneNode(true);
          document.head.appendChild(clonedScript);
          script.remove();
        }
      });

      // Find and move AMP cache styles from body to head
      const styles = document.body.querySelectorAll('link');
      styles.forEach(style => {
        const clonedStyle = style.cloneNode(true);
        document.head.appendChild(clonedStyle);
        style.remove();
      });

      // Serialize the modified DOM back to HTML
      arguments[0] = dom.serialize();
    }

    originalSend.apply(res, arguments);
  };

  next();
};

module.exports = domManipulation;

I want to know the approach to handle this. Any config that I need to adjust in Google Search Console? Or I still need to adjust my codes (I’m using Express and Handlebars)?

Is there a Filepond event for the moment when the user has chosen their file and clicks Open?

I’m using the latest version of Filepond in native JS. Occasionally I see a long delay between when the user has chosen their file (clicked “Open”) and when the “initfile” event is triggered. Ideally I would like to show a spinner during this delay to inform the user to wait. I don’t see another event on the list that I could use to trigger this spinner.

Does anyone have a suggestion?

Can you log websockets request sent from a server to a client?

I am working on creating a Chrome extension that injects JavaScript code into my website to log the WebSocket requests that the user receives when they run the extension.

Let’s say I am connected to a WebSocket server on my website at wss://server.example.com, and it sends data to my client like {"message": "example"}.

I don’t want to create a new connection to log; instead, I want to log the connection that is automatically established when I connect to the site.

So, doing something like const ws = new WebSocket('wss://server.example.com'); and logging the requests it sends is not what I am trying to achieve. I want to log the requests from the connection that is automatically established when you connect to sites with a WebSocket server.

If I find a piece of code that works, shouldn’t I be able to put it in the console to check if it works?

I have tried using different scripts with const OriginalWebSocket = window.WebSocket; to create a copy of the WebSocket connections and log them myself in a script. However, it often returns undefined. Does anyone have any idea how I can log the requests?

‘GET’ request sent instead of ‘POST’ on http://localhost:5000/login

I am using Flask for routes and Vue js for UI. I am using Celery and Redis. Db is SQLITE
routes.py

hthttp://localhost:5000/login getting Method Not Allowed
The method is not allowed for the requested URL Error.

In VSCode terminal,
127.0.0.1 - - [26/Nov/2024 14:54:09] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [26/Nov/2024 14:54:09] "GET /static/main.js HTTP/1.1" 304 -
127.0.0.1 - - [26/Nov/2024 14:54:13] "GET /login HTTP/1.1" 405 -
These are backlogs.

Why is it sending get request, when POST is mentioned?

Login.js

export default {
  data() {
    return {
      username: "",
      password: "",
      errorMessage: "",
      loading: false,
    };
  },
  methods: {
    async login() {
      this.loading = true;
      this.errorMessage = "";

      try {
        const user = {
          username: this.username,
          password: this.password,
        };

        const response = await fetch('/login', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(user),
        });

        if (!response.ok) {
          throw new Error(response.statusText);
        }

        const data = await response.json();

        if (data.token) {
          localStorage.setItem('auth-token', data.token);
          localStorage.setItem('role', data.role);

          if (data.role === 'admin') {
            this.$router.push('/home_admin');
          } else if (data.role === 'professional') {
            this.$router.push('/home_professional');
          } else if (data.role === 'customer') {
            this.$router.push('/home_customer');
          }
        } else {
          this.errorMessage = data.message || 'Unknown error occurred';
        }
      } catch (error) {
        this.errorMessage = 'An error occurred. Please try again.';
      } finally {
        this.loading = false;
      }
    }
  },
  template: `
    <div class="login-container">
      <h3>Login</h3>
      
      <div v-if="errorMessage" class="error-message">{{ errorMessage }}</div>
      
      <form @submit.prevent="login" method='POST'>
        <div class="form-group">
          <label for="username">Username</label>
          <input v-model="username" type="username" id="username" class="form-control" required />
        </div>
        
        <div class="form-group">
          <label for="password">Password</label>
          <input v-model="password" type="password" id="password" class="form-control" required />
        </div>
        
        <button type="submit" class="btn btn-dark" :disabled="loading">
          {{ loading ? 'Loading...' : 'Login' }}
        </button>
      </form>

      <p>Don't have an account? <router-link to="/register">Register</router-link></p>
    </div>
  `,
};

Routes.py

@routes.get('/')
def index():
    return render_template('index.html')

@routes.route('/login',methods=['POST'])
def login():
    try:
        # Parse the incoming JSON data
        data = request.get_json()

        if not data:
            return jsonify({"error": "No data provided"}), 400

        username = data.get('username')
        password = data.get('password')

        if not username or not password:
            return jsonify({"error": "Missing username or password"}), 400

        # Query the database for the user
        user = User.query.filter_by(username=username).first()
        if user and check_password_hash(user.password, password):
            # Generate a token or set session if needed
            token = user.get_auth_token()  # Assume this method exists on your user model
            return jsonify({'token': token, 'user_id': user.id, 'role': user.role}), 200

        return jsonify({"error": "Invalid credentials"}), 401

    except Exception as e:
         return jsonify({"error": str(e)}), 500

ExtJS 6.2.0: STATUS_ACCESS_VIOLATION error on double mouseover of menu items

I’m currently working with an ExtJS-based menu system and encountering an issue where the error STATUS_ACCESS_VIOLATION occurs when I click on a menu item after initially clicking on the main menu and reopening the sub-menu.

Here’s the scenario in detail:

First Click: Clicking the main menu opens the submenu without issues.
Subsequent Click: After closing the submenu, clicking the main menu again and then selecting a submenu item causes the STATUS_ACCESS_VIOLATION error.

Below is the code that sets up the menu structure and listens for click events:

javascript

var menuStructure = [];

// Sample Menu Structure
menuStructure.push({
text: ‘Main Menu 1’, // Main menu item
baseCls: ‘gnb_menu_btn’,
margin: ‘0 15 0 0’,
hidden: false, // Controls the visibility of the menu item
id: ‘menu1’, // Main menu item ID
parentId: ‘0’,
padding: ’20 0 20 0′,
menuAlign: ‘t-b?’,
expanded: true,
menu: {
xtype: ‘menu’, // Menu xtype
cls: ‘gnb_sub_box’,
plain: true,
expanded: true,
padding: 0,
items: [
{
text: ‘Sub Menu 1’, // Sub menu item
id: ‘submenu1’,
listeners: {
click: function() {
console.log(‘Submenu 1 clicked’);
}
}
},
{
text: ‘Sub Menu 2’, // Another sub menu item
id: ‘submenu2’,
listeners: {
click: function() {
console.log(‘Submenu 2 clicked’);
}
}
}
]
}
});

var tb = Ext.create(‘Ext.toolbar.Toolbar’, {
cls: ‘nav_gnb’,
padding: ‘0’,
items: menuStructure
});

Problem:
When I click the main menu item (e.g., Main Menu 1), the sub-menu opens correctly. However, after closing the sub-menu and reopening it by clicking the main menu again, clicking on any submenu item (like Sub Menu 1 or Sub Menu 2) triggers a STATUS_ACCESS_VIOLATION error.

Steps Taken:
I’ve tried using showAt, destroy, and manually handling visibility, but the error still occurs when clicking submenu items after reopening the menu.
I checked if there are any issues with the menu’s configuration or event listeners but couldn’t resolve the error.

Questions:
Why does the error occur when clicking on submenu items after reopening the menu?
Are there any best practices for handling menu visibility and events in ExtJS to avoid this kind of error?
What might be causing the STATUS_ACCESS_VIOLATION error in this context?

Environment:
ExtJS Version: v6.2.0.981
Browser: Chrome 115
Operating System: Windows 10
Any guidance or suggestions on how to resolve this issue would be greatly appreciated!

anything.. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

How to refer an element of a dictionary in data binding when the key is a variable?

I’m using element UI as below:

<template>
    <el-table :data="DataList" >
      <el-table-column type="expand" >            
            <template #default="props">
              <div>
                <hr>
                <el-table :data="mydict[row.id]" >
                  <el-table-column label="Name" prop="name" />               
                </el-table>
                <hr>
              </div>
            </template>
      </el-table-column>
      
      <el-table-column label="ID">
        <template slot-scope="{row}">
          <span>{{ row.id }}</span>
        </template>
      </el-table-column>
      
    </el-table>
 </template>


export default {
    data() {
        return {
          DataList:[{"id": 1},{"id": 2}],
          mydict:{"1":[{"name": "name1"}, {"name": "name2"}], "2":[{"name": "name3"}, {"name": "name4"}]}
        }
      },
      ......
}  

I want to bind list from mydict by key. When row.id == 1, [{“name”: “name1”}, {“name”: “name2″}] is used. :data=”mydict[row.id]” didn’t work. I don’t know how to do.

Selector Returns Null in Headless Mode but Works in Non-Headless Mode

I’m working on a puppeteer-based scraper that extracts product details (image, title, and price) from a webpage. The scraper works perfectly in non-headless mode, but when I switch to headless mode, the .stdImg selector (used to extract the image) consistently returns null.

Here are the behaviors I observed:

  • Headless: true + User Agent: Title and price work fine, but .stdImg (image) returns null.
  • Headless: true + Empty User Agent: Title and price fail, and .stdImg also returns null.
  • Headless: false + Empty User Agent (empty string: Everything works perfectly.

In my application, I need to use headless mode because this scraper will eventually run as part of a Chrome extension, and I don’t want to open a browser window during the process.

I’ve tried:

  • Mimicking non-headless mode by removing navigator.webdriver and setting realistic user agents.
  • Scrolling through the page to handle lazy-loaded images.
  • Debugging the DOM structure in both modes using screenshots.
const { connect } = require("puppeteer-real-browser");

let browser = null;
let page = null;

//Configs
const connectOptions = {
    headless: false,
    devtools: true,
    args: [
        "--disable-features=site-per-process",
        "--no-sandbox",
        "--disable-setuid-sandbox",
        "--disable-gpu",
        "--hide-scrollbars",
        "--disable-extensions",
        "--disable-blink-features=AutomationControlled",
    ],
    customConfig: {},
    turnstile: true,
    connectOption: {},
    disableXvfb: false,
    ignoreAllFlags: false,
};

const viewPortOptions = { width: 1024, height: 768 };
const ExtraHTTPHeadersOptions = { "accept-language": "tr-TR,tr;q=0.9,en-US,en;q=0.8" };
const userAgent =
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";

//Load page
async function safeGoto(page, url, retries = 3) {
    for (let attempt = 1; attempt <= retries; attempt++) {
        try {
            await page.goto(url, { waitUntil: "domcontentloaded", timeout: 60000 });
            return;
        } catch (error) {
            console.error(`Attempt ${attempt} failed:`, error.message);
            if (attempt === retries) throw error;
        }
    }
}

//Extract data
async function safeEvaluate(page, selector, evaluateFn, errorMessage) {
    try {
        const element = await page.waitForSelector(selector, { timeout: 10000 });
        return await element.evaluate(evaluateFn);
    } catch (error) {
        console.error(errorMessage, error.message);
        return null;
    }
}

async function scrapeWebsite(url, selectors) {
    try {
        const { browser: connectedBrowser, page: connectedPage } = await connect(connectOptions);
        browser = connectedBrowser;

        const [page] = await browser.pages();
        await page.setUserAgent("");
        await page.setViewport(viewPortOptions);
        await page.setExtraHTTPHeaders(ExtraHTTPHeadersOptions);

        await page.waitForSelector("body", { timeout: 10000 });
        await safeGoto(page, url);
        await page.evaluate(() => {
            const imgs = document.querySelectorAll("img");
            imgs.forEach((img) => img.scrollIntoView({ behavior: "smooth", block: "center" }));
        });

        // Extract data
        const src = await safeEvaluate(
            page,
            selectors.image,
            (el) => el.src,
            `Failed to extract image from selector: ${selectors.image}`
        );

        const title = await safeEvaluate(
            page,
            selectors.title,
            (el) => el.textContent.trim().toLowerCase(),
            `Failed to extract title from selector: ${selectors.title}`
        );

        const value = await safeEvaluate(
            page,
            selectors.price,
            (el) => el.textContent.trim(),
            `Failed to extract price from selector: ${selectors.price}`
        );

        // Return extracted data
        const color = selectors.color;
        return { src, value, title, color, url };
    } catch (error) {
        console.error("Scraping failed:", error.message);
        throw error;
    } finally {
        if (page && !page.isClosed()) {
            try {
                await page.close();
            } catch (closeError) {
                console.error("Failed to close page:", closeError.message);
            }
        }
        if (browser && browser.isConnected()) {
            try {
                await browser.close();
            } catch (closeError) {
                console.error("Failed to close browser:", closeError.message);
            }
        }
        if (browser && browser.process() != null) browser.process().kill("SIGINT");
    }
}

const getFromDomain = (url) =>
    scrapeWebsite(url, {
        image: ".stdImg",
        title: ".classifiedDetailTitle h1",
        price: ".classified-price-wrapper",
        color: "#FFE800",
    });

.stdImg for the image
.classifiedDetailTitle h1 for the title
.classified-price-wrapper for the price

  • Why does the .stdImg selector fail in headless mode but work in non-headless mode(with no user agent)?
  • How can I fix this issue and reliably extract the image in headless mode?