How to expand function calls imported from other modules using a Javascript bundler?

This is kind of strange requirement, but is it possible to expand functions calls inline by using a Javascript bundler or some other technology? I have zero experience with bundlers, but this is what I am looking for:

Suppose there are two file:

// print.js
export function showMessage(message) {
    console.log(message)
}
// hello.js
import { showMessage } from "./print.js"
export function hello(name) {
    showMessage(`Hello, ${name}`)
}

Is there a way to produce a file (say bundle.js) from hello.js that will export the hello function but looks something like this:

export function hello(name) {
    (function (message) {
        console.log(message)
    })(`Hello, ${name}`)
}

I want to do this so that I can import the hello function in another file and pass it along to the Selenium’s executeScript function. Something like:

import { hello } from "./bundle.js"
driver.executeScript(hello, 'Jane')

Error: Cannot Resolve type entity i10.MatLegacyDialogModule to symbol anuglar 17.3

I am upgrading my angular from version 16 to 17.3.8

I am ony getting this below issue after compile and not able to resolve.
enter image description here

Node version v18.14.1

my package.json

{
  "name": "project_name",
  "version": "2.13.34",
  "license": "https://themeforest.net/licenses/standard",
  "scripts": {
    "ng": "ng",
    "start": "node --max_old_space_size=8081 ./node_modules/@angular/cli/bin/ng serve --open",
    "start:mem": "node --max_old_space_size=8081 ./node_modules/@angular/cli/bin/ng serve --open",
    "analyze:mem": "node --max_old_space_size=8081 ./node_modules/@angular/cli/bin/ng run project_name:analyze --gzip",
    "build": "ng build && npm run move-static",
    "build:test": "node --max_old_space_size=6144 ./node_modules/@angular/cli/bin/ng build",
    "build:prod": "ng build --configuration production",
    "build:prod:mem": "node --max_old_space_size=6144 ./node_modules/@angular/cli/bin/ng build --configuration production",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "bundle:report": "source-map-explorer dist/project_name/browser/*.js",
    "dev:ssr:mem": "node --max_old_space_size=8081 ./node_modules/@angular/cli/bin/ng run project_name:serve-ssr",
    "dev:ssr": "ng run project_name:serve-ssr",
    "analyze:build": "ng build --configuration production --source-map true",
    "serve:ssr": "node --max_old_space_size=4096 dist/project_name/server/main.js",
    "pm2": "pm2 start dist/project_name/server/main.js",
    "build:ssr": "ng build && ng run project_name:server",
    "build:prod:ssr": "node --max_old_space_size=8081 ./node_modules/@angular/cli/bin/ng build --configuration production && ng run project_name:server",
    "build:prod:ssr:mem": "node --max_old_space_size=8081 ./node_modules/@angular/cli/bin/ng build --configuration production && ng run project_name:server",
    "build:ssr:mem": "node --max_old_space_size=8081 ./node_modules/@angular/cli/bin/ng build && ./node_modules/@angular/cli/bin/ng run project_name:server",
    "prerender": "ng run project_name:prerender",
    "compodoc:build": "compodoc -p tsconfig.doc.json",
    "compodoc:build-and-serve": "compodoc -p tsconfig.doc.json -s",
    "compodoc:serve": "compodoc -s",
    "move-static": "cp -a ./node_modules/@pdftron/webviewer/public/. ./dist/public/webviewer"
  },
  "private": true,
  "browser": {
    "fs": false,
    "path": false,
    "os": false
  },
  "resolutions": {
    "webpack": "^5.0.0-beta.30"
  },
  "dependencies": {
    "@angular-builders/custom-webpack": "^13.1.0",
    "@angular-material-components/datetime-picker": "^9.0.0",
    "@angular/animations": "^17.3.12",
    "@angular/cdk": "^17.3.10",
    "@angular/common": "17.3.12",
    "@angular/compiler": "17.3.12",
    "@angular/core": "17.3.12",
    "@angular/fire": "^7.2.1",
    "@angular/forms": "17.3.12",
    "@angular/material": "^17.3.10",
    "@angular/material-moment-adapter": "17.3.10",
    "@angular/platform-browser": "17.3.12",
    "@angular/platform-browser-dynamic": "17.3.12",
    "@angular/platform-server": "17.3.12",
    "@angular/router": "17.3.12",
    "@angular/ssr": "^17.3.8",
    "@aws-sdk/client-s3": "^3.582.0",
    "@aws-sdk/lib-storage": "^3.409.0",
    "@aws-sdk/s3-request-presigner": "^3.272.0",
    "@aws-sdk/signature-v4-crt": "^3.408.0",
    "@aws-sdk/util-user-agent-node": "^3.408.0",
    "@calumk/editorjs-columns": "^0.3.2",
    "@compodoc/compodoc": "^1.1.19",
    "@editorjs/attaches": "^1.3.0",
    "@editorjs/checklist": "^1.6.0",
    "@editorjs/code": "^2.9.0",
    "@editorjs/editorjs": "^2.29.1",
    "@editorjs/embed": "^2.7.0",
    "@editorjs/header": "^2.8.1",
    "@editorjs/image": "^2.9.0",
    "@editorjs/link": "^2.6.2",
    "@editorjs/list": "^1.9.0",
    "@editorjs/paragraph": "^2.11.4",
    "@editorjs/quote": "^2.6.0",
    "@editorjs/raw": "^2.5.0",
    "@editorjs/table": "^2.3.0",
    "@editorjs/underline": "^1.1.0",
    "@editorjs/warning": "^1.4.0",
    "@formio/angular": "^6.0.0",
    "@fortawesome/fontawesome-free": "^5.15.4",
    "@fullcalendar/angular": "^6.1.8",
    "@fullcalendar/core": "^6.1.8",
    "@fullcalendar/daygrid": "^6.1.8",
    "@fullcalendar/interaction": "^6.1.8",
    "@fullcalendar/list": "^6.1.8",
    "@fullcalendar/moment": "^6.1.8",
    "@fullcalendar/rrule": "^6.1.8",
    "@fullcalendar/timegrid": "^6.1.8",
    "@nguniversal/module-map-ngfactory-loader": "^8.2.6",
    "@pdftron/webviewer": "^8.0.0",
    "@types/jspdf": "^1.3.3",
    "@types/stripe": "^7.13.25",
    "algoliasearch": "^4.12.1",
    "angular-instantsearch": "^4.4.1",
    "angular-sanitize": "^1.8.3",
    "aos": "^2.3.4",
    "apexcharts": "^3.26.1",
    "archiver": "^5.3.1",
    "bootstrap": "^5.1.3",
    "crypto-browserify": "^3.12.0",
    "crypto-es": "^1.2.7",
    "crypto-js": "^4.0.0",
    "domino": "^2.1.6",
    "domino-ext": "^2.1.4",
    "dotenv": "^16.0.1",
    "editorjs-alert": "^1.1.3",
    "editorjs-html": "^3.4.3",
    "editorjs-style": "^3.0.3",
    "editorjs-text-color-plugin": "^2.0.4",
    "editorjs-toggle-block": "^0.3.15",
    "express": "^4.15.2",
    "firebase": "^9.23.0",
    "fs-extra": "^11.2.0",
    "gapi-script": "^1.2.0",
    "highlight.js": "10.7.2",
    "html2pdf.js": "^0.10.1",
    "i": "^0.3.7",
    "instantsearch.js": "^4.54.1",
    "jspdf": "^2.5.1",
    "jspdf-autotable": "^3.5.23",
    "leader-line": "^1.0.7",
    "lodash-es": "4.17.21",
    "material-steppers": "^2.0.0",
    "moment": "^2.29.1",
    "ng-apexcharts": "^1.7.4",
    "ng-quill": "^4.5.3",
    "ng-starrating": "^1.0.20",
    "ng-stripe-checkout": "^1.0.4",
    "ngx-device-detector": "^2.0.8",
    "ngx-mat-select-search": "^7.0.0",
    "node-fetch": "^2.6.1",
    "npm": "^10.1.0",
    "perfect-scrollbar": "1.5.0",
    "pm2": "^5.2.2",
    "quill": "1.3.7",
    "quill-emoji": "^0.2.0",
    "request": "^2.88.2",
    "rrule": "2.6.8",
    "rxjs": "^7.5.5",
    "rxjs-compat": "^6.6.7",
    "source-map-explorer": "^2.5.2",
    "split-file": "^2.3.0",
    "stripe": "^8.116.0",
    "stripe-angular": "^1.9.3",
    "sweetalert2": "^11.4.24",
    "title-editorjs": "^1.0.2",
    "ts-md5": "^1.3.1",
    "tslib": "2.2.0",
    "video.js": "^7.21.4",
    "videojs-logo": "^2.1.6",
    "videojs-markers": "^1.0.1",
    "videojs-playlist": "^5.1.0",
    "videojs-seek-buttons": "^3.0.1",
    "vis": "^4.21.0-EOL",
    "vis-data": "^7.1.9",
    "vis-network": "^9.1.9",
    "vjs": "^0.1.8",
    "web-animations-js": "2.3.2",
    "xlsx": "^0.18.5",
    "zone.js": "~0.14.10"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "17.3.8",
    "@angular/cli": "17.3.8",
    "@angular/compiler-cli": "17.3.12",
    "@angular/language-service": "17.3.12",
    "@formio/js": "^5.0.0-rc.48",
    "@ngx-builders/analyze": "^2.3.0",
    "@ngx-meta/core": "^9.0.0",
    "@types/crypto-js": "4.0.1",
    "@types/express": "^4.17.0",
    "@types/highlight.js": "9.12.4",
    "@types/jasmine": "3.6.10",
    "@types/jasminewd2": "2.0.8",
    "@types/lodash-es": "4.17.4",
    "@types/node": "15.0.1",
    "browser-sync": "^3.0.0",
    "bufferutil": "^4.0.3",
    "codelyzer": "6.0.2",
    "file-saver": "^2.0.5",
    "formiojs": "^4.18.2",
    "jasmine-core": "3.7.1",
    "jasmine-spec-reporter": "7.0.0",
    "karma": "6.3.2",
    "karma-chrome-launcher": "3.1.0",
    "karma-coverage-istanbul-reporter": "3.0.3",
    "karma-jasmine": "4.0.1",
    "karma-jasmine-html-reporter": "1.5.4",
    "ngx-infinite-scroll": "^16.0.0",
    "ngx-moment": "^6.0.2",
    "ngx-owl-carousel-o": "^16.0.0",
    "ngx-pagination": "^6.0.3",
    "ngx-quill": "^22.0.0",
    "protractor": "7.0.0",
    "tailwindcss": "2.1.2",
    "ts-node": "9.1.1",
    "tslint": "6.1.2",
    "typescript": "5.3.3",
    "utf-8-validate": "^5.0.5",
    "ws": "^8.2.2",
    "xhr2": "^0.2.1"
  }
}

Shopify money filter rendering raw codes

Im working on a shopify store where I encountered that when changing the sizes the price not only gets reseted to the default format but the ” tag that controls the snippet becomes visible like this:

<span class="money">Rs 4,000.00</span>

the code snippet that handles this

    <div class="product__price fs-body-base">
      <span data-price>{{ current_variant.price | money }}</span>
      <span class="visually-hidden" data-compare-text>{{ 'products.product.regular_price' | t }}</span>
      <s data-compare-price>
        {% if current_variant.compare_at_price > current_variant.price %}
          {{ current_variant.compare_at_price | money }}
        {% endif %}
      </s>
      {% render 'unit-price' item: current_variant %}
    </div>

    {% render 'product-form' with
      product: product,
      current_variant: current_variant,
      show_quantity: section.settings.show_quantity_input,
      show_dynamic_checkout: section.settings.enable_payment_button,
      show_swatches: section.settings.show_swatches,
    %}
  </div>

I tried using the filter money_without_currency but it didnt work.
Then i tried removing the logic that handles money variants for each size it didnt work either.

How do I calculate the width of multiple events in a calendar?

I am trying to implement a Calendar that manages schedules.
What I’m curious about is how can I clearly set the width value when showing the event?
Let’s assume there are events like below.

const events = [
  {begin: 1400, end: 1530, id:1},
  {begin: 1400, end: 1430, id:2},
  {begin: 1400, end: 1430, id:3},
  {begin: 1430, end: 1500, id:4},
]

Using the graph algorithm I implemented, all events overlap either directly or indirectly, resulting in each width value being 25%.

However, what I want is for Test 1, which overlaps with Tests 2, 3, and 4, to have a width value of 33% since Tests 2 and 3 occur at the same time. Similarly, I would like the width values for Tests 2 and 3 to be 33%, and for Test 4 to be 66%.

How can I resolve this? Please help.

enter image description here

How to convert multiple Files (as File[]) into a single Blob? [duplicate]

In Postman, it is possible to initiate a POST request with a body of form-data and the below key-value pairs:

Screenshot of Postman multi-files inside a single key-value pair


However, when I tried putting multiple files, as File[] into a single Blob (as the below sample shows):

const convertFilesToFormData = (files: File[]): FormData => {
  let formData = new FormData();
  formData.append("files", files);
  return formData;
} // REMARK: A simplified function of what I have.

It return the below error:

No overload matches this call.
  Overload 1 of 3, '(name: string, value: string | Blob): void', gave the following error.
    Argument of type 'File[]' is not assignable to parameter of type 'string | Blob'.
      Type 'File[]' is missing the following properties from type 'Blob': size, type, arrayBuffer, stream, text
  Overload 2 of 3, '(name: string, value: string): void', gave the following error.
    Argument of type 'File[]' is not assignable to parameter of type 'string'.
  Overload 3 of 3, '(name: string, blobValue: Blob, filename?: string | undefined): void', gave the following error.
    Argument of type 'File[]' is not assignable to parameter of type 'Blob'.ts(2769)

I would like to know if it is possible and the methods to convert to Blob type for later fetch requests.

Please (Really Please) Add a 0 Quantity Default to Products [closed]

When my customer goes to the Registration Page, all three of my products default to Quantity 1. So they get sticker shock. If they want to the Online product of $599, they go to the page and it’s already registered as $2397! This is the first thing they see. That’s not good at all.

Every other seminar I’ve ever signed up for has a Quantity of 0 as the default. This allows the customer to choose which product they want. When I tried to edit Quantity to 0 on the Payment Link-Edits page. It says “Quantity Must be between 1 and 999.” With all due respect, this is unacceptable.

I was told another option would be to have 3 Registration Buttons. Sorry, that’s too confusing for my customers. Please help.

See above. The payment page should default all products to Quantity 0. Your Edit page refuses to let me do that.

I love this service, but it’s quite obviously set up by computer programmers for computer programmers. I’m not one, so it’s not intuitive or easily navigable.

Even entering a question gives me a lot of error messages (Cannot use “!”) Why do you force me to use tags? And if I don’t do tags just right, it says (after I go to the trouble of adding them) “Creating the new tag ‘quantity’ requires at least 1500 reputation. Try something from the existing tags list instead.” How am I supposed to know what a 1500 reputation means?

Why doesn’t my section highlight when it’s in the viewport when all the others do?

I have several sections in my website and all of them highlighted when they’re in the viewport except for one. I want to know why that particular section won’t highlight and how to fix it. All relevant code snippets are provided below.

Here is the CSS that highlights a section when it is in the active state.

section.active-section {
  background: rgb(0, 0, 0);
  background: linear-gradient(
          0deg,
          rgba(0, 0, 0, 0.6) 0%,
          rgba(209, 198, 198, 0.185) 100%
  );
  backdrop-filter: blur(1px);
}

section.active-section .section-container::before {
  opacity: 1;
  animation: rotate 4s linear 0s infinite forwards;
}

section.active-section .section-container::after {
  opacity: 1;
  animation: rotate 5s linear 0s infinite forwards reverse;
}

@keyframes rotate {
  from {
    transform: rotate(0deg) translate(-1em) rotate(0deg);
  }
  to {
    transform: rotate(360deg) translate(-1em) rotate(-360deg);
  }
}

Below is the JavaScript that sets the CSS class of the particular section in the viewport to the active state. I don’t believe the issue lies here because all the other sections are highlighting just fine.

/**
 * @function addCSSActiveState
 * @desc set CSS class active state when the element is in the viewport
 * @param sections
 */
    const addCSSActiveState = (sections) => {
        sections.forEach((section, index) => {
            if (isVisible(section)) {
                section.classList.add('active-section');
            }
            else {
                section.classList.remove('active-section');
            }
        })
    }


/**
 * @function
 * @listens window#scroll
 * @desc upon scrolling, setting the CSS class active state to the section in the viewport
 */
    window.addEventListener('scroll', (e) => {
        addCSSActiveState(sections);
    });

And, lastly, here is the HTML for the section that doesn’t highlight.

    <section class="page-section" id="about">
        <div class="section-container">
            <div class="text-center">
                <h2 class="section-heading text-uppercase">About</h2>
            </div>
            <ul class="timeline">
                <li>
                    <div class="timeline-image"><img class="rounded-circle img-fluid" src="assets/img/timeline/timeline1.jpg" alt="university" /></div>
                    <div class="timeline-panel">
                        <div class="timeline-heading">
                            <h4>2001-2002</h4>
                            <h4 class="subheading">Our Cofounders Meet</h4>
                        </div>
                        <div class="timeline-body"><p class="text-muted">Our cofounders meet. </p></div>
                    </div>
                </li>
                <li class="timeline-inverted">
                    <div class="timeline-image"><img class="rounded-circle img-fluid" src="assets/img/timeline/timeline2.jpg" alt="computer" /></div>
                    <div class="timeline-panel">
                        <div class="timeline-heading">
                            <h4>August 2006</h4>
                            <h4 class="subheading">Our First Product was Released</h4>
                        </div>
                        <div class="timeline-body"><p class="text-muted">Our first product, an ERP system was released. It ended up getting purchased by a local business a few months later.</p></div>
                    </div>
                </li>
                <li>
                    <div class="timeline-image"><img class="rounded-circle img-fluid" src="assets/img/timeline/timeline3.jpg" alt="building" /></div>
                    <div class="timeline-panel">
                        <div class="timeline-heading">
                            <h4>May 2010</h4>
                            <h4 class="subheading">Our First Fortune 500 Client</h4>
                        </div>
                        <div class="timeline-body"><p class="text-muted">After landing several startup and small business clients, JP Morgan Chase became our first Fortune 500 client.</p></div>
                    </div>
                </li>
                <li class="timeline-inverted">
                    <div class="timeline-image"><img class="rounded-circle img-fluid" src="assets/img/timeline/timeline4.jpg" alt="business" /></div>
                    <div class="timeline-panel">
                        <div class="timeline-heading">
                            <h4>September 2015</h4>
                            <h4 class="subheading">Expanding our Agency</h4>
                        </div>
                        <div class="timeline-body"><p class="text-muted">We greatly expanded the size of our headquarters office, staff, and regional offices.</p></div>
                    </div>
                </li>
                <li class="timeline-inverted">
                    <div class="timeline-image">
                        <h4>
                            Get Involved
                            <br />
                            In Our
                            <br />
                            Journey!
                        </h4>
                    </div>
                </li>
            </ul>
        </div>
    </section>

Anyone see any issues?

Yahoo fantasy API oAuth2 not authenticating some users

I’ve been trying to help a friend fix an issue on his fantasy football website that collects data from a lot of places and gives you an all-in-one location. His issue is currently certain Yahoo accounts are able to get through and access the website while mine for example, can not. I click ‘log in via yahoo’ and it redirects me to the oAuth screen, I select yes, it redirects me back to the homepage and sends me 3 separate emails saying I logged in to his site. The problem is the log in wasn’t successful and it only stays there.

Other platforms such as ‘Sleeper’ work without a problem. Here’s the code:

`export const HandleYahooAuth2 = (code) =>
new Promise((resolve, reject) => {
const oauth2Client = new OAuth2(
YAHOO_CLIENT_ID,
YAHOO_CLIENT_SECRET,
‘https://api.login.yahoo.com/’,
‘oauth2/auth’,
‘oauth2/get_token’
);

// Exchange authorization code for access token
oauth2Client.getOAuthAccessToken(
  code,
  {
    grant_type: 'authorization_code',
    redirect_uri: OAUTH_REDIRECT_URL,
    scope: 'openid fspt-w'
  },
  async (error, accessToken, refreshToken, results) => {
    if (error) {
      console.error('Error getting access token:', error.data);
      reject(error);
      return;
    }
    console.log(accessToken)

    try {
      const resJSON = await MakeYahooRequest('users;use_login=1/games/teams', accessToken, refreshToken);
      const userArr = resJSON?.root?.fantasy_content?.users;
      const user = Array.isArray(userArr.user) ? userArr?.user[0] : userArr.user;

      const leagues = [];

      const yahooLeagues = Array.isArray(user.games.game) ? user.games?.game : [user.games?.game];

      for (const league of yahooLeagues) {
        if (league.code === 'nfl') {
          const teams = Array.isArray(league?.teams) ? league?.teams.team : [league?.teams?.team];
          const leagueId = teams[0]?.team_key.split('.t')[0];
          const leagueSettings = await GetYahooLeagueSettings(leagueId, accessToken, refreshToken);
          leagues.push(leagueSettings);
        }
      }
      console.log(leagues)
      resolve({leagues, accessToken, refreshToken});
    } catch (error) {
      console.error('Error after getting token', error.data);
      reject(error);
    }
  }
);

});`

Tried to adjust these settings with no luck

Getting this error as well when I attempt to log in with yahoo

He’s reached out to Yahoo and hasn’t been able to find documentation anywhere. How can I debug this more on my end for when the authentication doesn’t go through?

Setting a state based on another state which is updated using a callback

I’m using an event handler for a part of a component that needs to be removed afterwards, so the handler function can’t change, otherwise its reference would change and I wouldn’t be able to remove the listener.
Therefore, when setting a state inside the event handler, I must use an updater function to set the state, like so:

const handleMouseDown = () => {
    const handleMouseMove = () => {
        setValues((values) => {
             const newValue = calculateNewValue(values);
             const newValues = [...values, newValue];
             return newValues;
        });
    };

    const handleMouseUp = () => {
        document.removeEventListener("mousemove", handleMouseMove);
        document.removeEventListener("mouseup", handleMouseUp);
    };

    document.addEventListener("mousemove", handleMouseMove);
    document.addEvenetListener("mouseup", handleMouseUp);
}

The issue is that I need to set another state based on newValues, and I want to take advantage of React’s batching so everything gets updated after one re-render. The following code works but it triggers two re-renders:

const handleMouseDown = () => {
    const handleMouseMove = () => {
        setValues((values) => {
            const newValue = calculateNewValue(values);
            const newValues = [...values, newValue];

            setOtherValues(calculateOtherValues(newValues));

            return newValues;
        });
    };
    const handleMouseUp = () => {
        document.removeEventListener("mousemove", handleMouseMove);
        document.removeEventListener("mouseup", handleMouseUp);
    };

    document.addEventListener("mousemove", handleMouseMove);
    document.addEvenetListener("mouseup", handleMouseUp);
};

The following won’t work for my purposes:

Storing newValues before using setValues doesn’t work as this is wrapped inside an event handler that isn’t re-instantiated on every render, as I need to be able to remove it afterwards as I said in the beginning. This means that using values will reference its old contents (it will reference the state it had when the handler was created):

const handleMouseDown = () => {
    const handleMouseMove = () => {
        const newValue = calculateNewValue(values);
        const newValues = [...values, newValue];

        setValues(newValues);
        setOtherValues(calculateOtherValues(newValues));
    };

    const handleMouseUp = () => {
        document.removeEventListener("mousemove", handleMouseMove);
        document.removeEventListener("mouseup", handleMouseUp);
    };

    document.addEventListener("mousemove", handleMouseMove);
    document.addEvenetListener("mouseup", handleMouseUp);
};

Not using states. To simplify the problem I have used calculateOtherValues instead of pasting all of my logic. This immediately leads to the question: Why use a state when it can be calculated off of values ? Well, in this particular handler, otherValues can be and is calculated from values, but this isn’t the case in one of my other handlers, where values needs to be calculated off of otherValues, so I need to keep it store as a state.

I’m trying to find a way to get it working without using an extra re-render like in the second code example.

Detect left mouse click in message list area in Thunderbird via add-on extension

I am trying to write a Mozilla Thunderbird add-on extension that detects a left mouse click on any empty space of the message list area. My content_script.js file is the following:

document.addEventListener('click', (event) => {
    const messagePane = document.getElementById('messagepane');
    const messageList = document.getElementById('threadTree');
    if (messageList.contains(event.target) && !messagePane.contains(event.target)) {
        console.log('Clicked!');
    }
});

This does not work. That is, when I temporarily load the add-on in Thunderbird and inspect it, nothing is printed to the log when I left click on an empty space in the message list area.

What modifications does my code require to achieve my aim? Are any permissions required? Are the IDs correct?

How to Show Land Parcel lines in Hybrid (Satellite) View in Google Maps?

I’m working on a web application that uses the Google Maps API, and I need to display land parcels with custom styling when the map is in hybrid (satellite) view. I want to outline specific parcels with a distinct border color and possibly add a semi-transparent fill.

I can successfully apply styles to parcels in the normal map view, but when I switch to the hybrid view (which includes satellite imagery and map labels), my parcel styles disappear or don’t render as expected.

here’s the code

import { GoogleMapsOverlay } from '@deck.gl/google-maps';
import { PolygonLayer } from '@deck.gl/layers';
import axios from 'axios';

export const fetchBoundaryCoordinates = async (placeName) => {
  const nominatimUrl = `https://nominatim.openstreetmap.org/search.php?q=${placeName.formatted_address}&format=jsonv2&polygon_geojson=1`;
  //const nominatimUrl = `https://nominatim.openstreetmap.org/reverse?lat=${placeName.geometry.location.lat()}&lon=${placeName.geometry.location.lng()}&polygon_geojson=1&format=jsonv2`;
  
  try {
    const response = await axios.get(nominatimUrl);
    const data = response.data;
    if (data.length > 0 && data[0].geojson) {
      const geojson = data[0].geojson;
      let coordinatesArray = [];

      if (geojson.type === 'Polygon' || geojson.type === 'MultiPolygon') {
        coordinatesArray = geojson.coordinates[0].map(([lng, lat]) => [lng, lat]);

        // Calculate bounding box
        const lats = coordinatesArray.map(coord => coord[1]);
        const lngs = coordinatesArray.map(coord => coord[0]);
        const bounds = {
          north: Math.max(...lats),
          south: Math.min(...lats),
          east: Math.max(...lngs),
          west: Math.min(...lngs),
        };
        return [{ coordinates: coordinatesArray, type: 'Polygon', bounds }];
      } else if (geojson.type === 'Point') {
        coordinatesArray = [[geojson.coordinates[0], geojson.coordinates[1]]];
        return [{ coordinates: coordinatesArray, type: 'Point' }];
      }
    } else {
      console.error("Bounding box data not available for the selected location.");
      return [];
    }
  } catch (error) {
    console.error("Error fetching bounding box data from Nominatim:", error);
    return [];
  }
};
export const createPolygonOverlay = (boundaryData, lineWidth) => {
  const layers = [];
  
  boundaryData.forEach(data => {
    if (data.type === 'Polygon') {
      layers.push(
        new PolygonLayer({
          id: `polygon-layer-stroke-${Math.random()}`,
          data: [data],
          getPolygon: d => d.coordinates,
          getFillColor: [0, 0, 0, 0],
          getLineColor: [255, 255, 255, 255],
          getLineWidth: lineWidth * 2, // Stroke width
          stroked: true,
        }),
        new PolygonLayer({
          id: `polygon-layer-line-${Math.random()}`,
          data: [data],
          getPolygon: d => d.coordinates,
          getFillColor: [0, 0, 0, 0],
          getLineColor: [0, 0, 0, 255],
          getLineWidth: lineWidth, // Line width
          stroked: true,
        })
      );
    }
  });

  return new GoogleMapsOverlay({ layers });
};



export const containerStyle = {
  width: "100%",
  height: "calc(100vh - 149px)",
  transition: "transform 0.5s ease-in-out", // Smooth zoom transition
};


export const MAP_STYLE = [
  {
    "featureType": "administrative.land_parcel",
    "stylers": [
      {
        "visibility": "on"
      },
    ]
  },
  {
    "featureType": "administrative.land_parcel",
    "elementType": "geometry.stroke",
    "stylers": [
      {
        "color": "#000000"
      },
      {
        "visibility": "on"
      },
      {
        "weight": 5
      },
    ]
  },
  {
    "featureType": "landscape",
    "elementType": "labels",
    "stylers": [
      {
        "visibility": "off"
      }
    ]
  },
  {
    "featureType": "poi",
    "elementType": "labels",
    "stylers": [
      {
        "visibility": "off"
      }
    ]
  },
  {
    "featureType": "transit",
    "elementType": "labels",
    "stylers": [
      {
        "visibility": "off"
      }
    ]
  },
  {
    "featureType": "water",
    "elementType": "labels",
    "stylers": [
      {
        "visibility": "off"
      }
    ]
  }
]
import React, { useState, useEffect, useRef } from "react";
import {
  Map,
  useMap,
  useMapsLibrary,
  APIProvider,
} from "@vis.gl/react-google-maps";
import { useDispatch } from "react-redux";
import { forceUpdate } from "../../redux/reducers/appreducer";
import {
  containerStyle,
  fetchBoundaryCoordinates,
  MAP_STYLE,
} from "../../utils/constants";

function GoogleMap({ mapFunctionsRef }) {
  const [zoom, setZoom] = useState(13);
  const [center, setCenter] = useState({
    lat: 39.4396962,
    lng: -76.64871049999999,
  });
  const [mapInstance, setMapInstance] = useState(null);
  const polygonsRef = useRef([]);

  const dispatch = useDispatch();

  const handleZoomChanged = (e, Zoom = true) => {
    if (Zoom) {
      window.google.maps.event.trigger(mapInstance, "resize", {});
      setZoom(e.detail.zoom);
    }
  };

  const handleDrag = (e) => {
    setCenter(e.detail.center);
  };

  const MyComponent = () => {
    const map = useMap();
    const places = useMapsLibrary("places");

    const handleSuggestionClick = async (
      placeId,
      notCleared,
      zoomLevel = 13.2
    ) => {
      if (notCleared) {
        if (places && map) {
          const service = new places.PlacesService(map);
          service.getDetails({ placeId }, async (place, status) => {
            if (status === places.PlacesServiceStatus.OK) {
              const location = {
                lat: place.geometry.location.lat(),
                lng: place.geometry.location.lng(),
              };
              setCenter(location);
              handleZoomChanged({ zoom: zoomLevel }, false);
              setZoom(zoomLevel);
              const boundaryData = await fetchBoundaryCoordinates(place);

              if (
                boundaryData.length > 0 &&
                boundaryData[0].type === "Polygon"
              ) {
                drawPolygon(boundaryData[0].coordinates, map);
              } else {
                console.error("No polygon data available to draw.");
              }
            } else {
              console.error("Failed to get place details, status:", status);
            }
          });
        } else {
          console.error("PlacesService or map is not initialized yet.");
        }
      } else {
        polygonsRef.current.forEach((polygon) => polygon.setMap(null));
        polygonsRef.current = [];
        setCenter({ lat: 39.4396962, lng: -76.64871049999999 });
        setZoom(13.2);
        setMapInstance(null);
      }
    };

    const drawPolygon = (coordinates, map) => {
      const polygon = new window.google.maps.Polygon({
        paths: coordinates.map((coord) => ({ lat: coord[1], lng: coord[0] })),
        strokeColor: "#000000",
        strokeOpacity: 1.0,
        strokeWeight: 3.0,
        fillOpacity: 0.0,
      });

      polygon.setMap(map);

      polygonsRef.current.push(polygon);
    };
    useEffect(() => {
      if (!map || !places) return;

      mapFunctionsRef.current = {
        handleSuggestionClick,
      };
      map.setOptions({
        gestureHandling: "greedy",
        zoomControl: true,
        mapTypeControl: true,
        streetViewControl: true,
        fullscreenControl: false,
        scaleControl: false,
        rotateControl: false,
        clickableIcons: false,
        draggableCursor: "default",
        styles: MAP_STYLE,
      });
      setMapInstance(map);
      dispatch(forceUpdate());
    }, [map, places, dispatch, mapFunctionsRef]);

    return null;
  };
  return (
    <div>
      <APIProvider
        apiKey={process.env.REACT_APP_GOOGLE_API}
        libraries={["places", "geometry"]}
      >
        <Map
          style={containerStyle}
          defaultCenter={{ lat: 22.54992, lng: 0 }}
          mapTypeId={"hybrid"}
          scaleControl={false}
          gestureHandling={"greedy"}
          zoom={zoom ? zoom : 13}
          mapTypeControl={false}
          onZoomChanged={handleZoomChanged}
          center={center}
          tilt={0}
          defaultZoom={12}
          onDrag={handleDrag}
        ></Map>
        <MyComponent />
      </APIProvider>
    </div>
  );
}

export default GoogleMap;

In Javascript / Node.JS parse XML and extract attributes of the parent node

I’m using @xmldom/xmldom‘s DOMParser and xpath to process an XML document.

I locate a set of nodes that match an XPath expression e.g. //MyElement. I’m getting the expected elements back. I can print the values for attributes for those elements by calling node.getAttribute(attrName). So far so good… Now, I want to read attributes of the parent.

I call node.parentNode and I can print its contents using console.log. It contains (for instance):

    {
  _nsMap: {},
  attributes: {
    '0': Attr {
      ownerDocument: [Document],
      nodeName: 'myLocalName',
      name: 'myLocalName',
      namespaceURI: undefined,
      specified: true,
      localName: 'myLocalName',
      lineNumber: 1,
      columnNumber: 12828,
      nodeValue: 'someValue',     
      value: 'someValue',
      ownerElement: [Circular *1]
    },
    '1': Attr {
      ownerDocument: [Document],
      nodeName: 'someName',
      name: 'someName',
      namespaceURI: undefined,
      specified: true,
      localName: 'someName',
      lineNumber: 1,
      columnNumber: 12960,
      nodeValue: 'some value',
      value: 'some value',
      ownerElement: [Circular *1]
    },

But, for some reason I cannot call node.parentNode.attributes nor can I get access to any of the members of the attributes object unless I iterate over the keys of the parent node. What am I missing?

Code that works

    console.log("nNODEn");
    let ks = Object.keys(node.parentNode);
    ks.forEach((k)=>{
        if (k==='attributes'){
            let aks = Object.keys(node.parentNode['attributes']);
            console.log('Dealing with attributes');
            console.log(aks);
        }
    });

Output

NODE

Dealing with attributes
[ '0', '1', '2', '_ownerElement', 'length' ]

Code that fails

    console.log("nNODEn");
    let ks = Object.keys(node.parentNode);
    let aks = Object.keys(node.parentNode['attributes']);
    ks.forEach((k)=>{
        if (k==='attributes'){
            console.log('Dealing with attributes');
            console.log(aks);
        }
    });

Output

TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at parseBlocks (C:Usersdavidworkspacedomain-analyzerindex.js:30:26)

What am I missing?

Thanks