Django guest user cart functionality? Is it safe?

Creating an e-commerce website project to try and learn Django and more about Javascript, so I have been going over a tutorial for the past week. In the tutorial, there is a guest user cart feature. It works by storing user and product data into the cookies. Though, I am having trouble getting it to add multiple of the same item. If I were to login as a user the website works fine. The remove feature works fine for deleting an item out of the cart as guest. In the JavaScript console, the items in the cart get deleted, but the cookies retain the same information before the website reloads. Don’t know the cause for this issue. I would really like this feature to work out.
JavaScript Console Log
cart.js

var updateBtns = document.getElementsByClassName('update-cart')

for(var i = 0; i < updateBtns.length; i++) {
    updateBtns[i].addEventListener('click', function() {
        //sets variable to add to the dictionary.
        var productId = this.dataset.product
        var action = this.dataset.action
        console.log('productId:', productId, 'action:', action)

        //checks to see if the user is logged in.
        console.log('USER:', user)
        if (user === 'AnonymousUser') {
            addCookieItem(productId, action)
        } else {
            updateUserOrder(productId, action)
        }
    })
}

function addCookieItem(productId, action) {
    console.log('Not logged in.')

    //add quantity to the cart by 1
    if (action == 'add') {
        if(cart[productId] == undefined) {
            cart[productId] = {'quantity':1}
        } else {
            cart[productId]['quantity'] += 1
        }
    }
    //removes quantity to the cart by 1
    if (action == 'remove') {
        cart[productId]['quantity'] -= 1

        if(cart[productId]['quantity'] <= 0){
            console.log('Remove Item')
            delete cart[productId]
        }
    }
    console.log('Cart:', cart)
    //
    document.cookie = 'cart=' + JSON.stringify(cart) + ";domain=;path=/"
    location.reload()
}

function updateUserOrder(productId, action) {
    console.log('User is logged in, sending data...')

    var url = '/update_item/'

    fetch(url, {
        method: 'POST',
        headers: {
            'Content-Type':'application/json',
            'X-CSRFToken':csrftoken,
        },
        body: JSON.stringify({
            'productId':productId,
            'action':action,
        })
    })

    .then((response) =>{
        return response.json()
    })

    .then((data) =>{
        console.log('data:', data)
        location.reload()
    })
}

main.html

var user = '{{request.user}}';

      function getToken(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie !== '') {
          var cookies = document.cookie.split(';');
          for (var i=0; i<cookies.length; i++) {
            var cookie = cookies[i].trim();
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
              cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
              break;
            }
          }
        }
        return cookieValue;
      }
      var csrftoken = getToken('csrftoken');

      function getCookie(name) {
        var cookieArr = document.cookie.split(";")

        for(var i=0;i<cookieArr.length; i++) {
          var cookiePair = cookieArr[i].split("=");

          if(name == cookiePair[0].trim()) {
            return decodeURIComponent(cookiePair[1]);
          } 
        }
        return null;
      }
      var cart = JSON.parse(getCookie('cart'))

      if (cart == undefined) {
        cart = {}
        console.log('Cart was created', cart)
        document.cookie = 'cart=' + JSON.stringify(cart) + ";domain=;path=/"
      }

      console.log("Cart:", cart);

utils.py

import json
from .models import *

def cookieCart(request):
    if request.user.is_authenticated:
        customer = request.user.customer
        order, created = Order.objects.get_or_create(customer=customer, complete=False)
        items = order.orderitem_set.all()
        cartItems = order.get_cart_items
    else:
        try:
            cart = json.loads(request.COOKIES['cart'])
        except:
            cart = {}
        print('Cart:', cart)
        items = []
        order = {
            'get_cart_total':0,
            'get_cart_items':0,
            'shipping':False,
        }
        cartItems = order['get_cart_items']

        for i in cart:
            try:
                cartItems += cart[i]['quantity']

                product = Product.objects.get(id=i)
                total = (product.price * cart[i]['quantity'])

                order['get_cart_total'] += total
                order['get_cart_items'] += cart[i]['quantity']

                item = {
                    'product': {
                    'id':product.id,
                    'name':product.name,
                    'price':product.price,
                    'imageURL':product.imageURL
                    },
                    'quantity':cart[i]['quantity'],
                    'get_total':total,
                }
                items.append(item)

                if product.digital == False:
                    order['shipping'] = True
            except:
                pass
    return {'cartItems':cartItems, 'order':order, 'items':items}

def cartData(request):
    if request.user.is_authenticated:
        customer = request.user.customer
        order, created = Order.objects.get_or_create(customer=customer, complete=False)
        items = order.orderitem_set.all()
        cartItems = order.get_cart_items
    else:
        cookieData = cookieCart(request)
        cartItems = cookieData['cartItems']
        order = cookieData['order']
        items = cookieData['items']
    return {'cartItems':cartItems, 'order':order, 'items':items}

def guestOrder(request, data):
    print('User is not logged in..')

    print('COOKIES:', request.COOKIES)
    name = data['form']['name']
    email = data['form']['email']

    cookieData = cookieCart(request)
    items = cookieData['items']

    customer, created = Customer.objects.get_or_create(
        email=email,
    )
    customer.name = name
    customer.save()

    order = Order.objects.create(
        customer=customer,
        complete=False,
        
    )
    for item in items:
        product = Product.objects.get(id=item['product']['id'])

        orderItem = OrderItem.objects.create(
            product=product,
            order=order,
            quantity=item['quantity'],
        )
    return customer, order

views def cart(request):

if request.user.is_authenticated:
        customer = request.user.customer
        order, created = Order.objects.get_or_create(customer=customer, complete=False)
        items = order.orderitem_set.all()
        cartItems = order.get_cart_items
    else:
        cookieData = cookieCart(request)
        cartItems = cookieData['cartItems']
        order = cookieData['order']
        items = cookieData['items']

    context = {'items':items, 'order':order, 'cartItems':cartItems}
    return render(request, 'store/cart.html', context)

Help would be greatly appreciated! This is my first stack overflow post, so if you are reading this and know what I am doing wrong please let me know!

Error: Cannot destructure property ‘title’ of ‘(0 , react__WEBPACK_IMPORTED_MODULE_1__.useContext)(…)’ as it is undefined (Next.js Chat App)

I’m encountering the error “Cannot destructure property ‘title’ of ‘(0 , react__WEBPACK_IMPORTED_MODULE_1__.useContext)(…)’ as it is undefined” while building a chat application using Next.js and Solidity. I’m following a YouTube tutorial, but despite having the same code, I’m getting this error.

below is my code and error:

getting this error in browser :

Server Error
TypeError: Cannot destructure property 'title' of '(0 , react__WEBPACK_IMPORTED_MODULE_1__.useContext)(...)' as it is undefined.

This error happened while generating the page. Any console logs will be displayed in the terminal window.
Source
pages/index.js (5:9) @ title

  3 | import { ChatAppContext } from "../context/ChatAppContext";
  4 | const ChatApp =() =>{
> 5 |  const {title} = useContext(ChatAppContext);
    |         ^
  6 |  return <div>{title}</div>;
  7 | };
  8 |   

context>ChatAppContext.js :

import React, {useState,useEffect} from "react";
import {useRouter} from "next/router";

//Internal  import 
import {
    CheckIfWalletConnected,
    connectWallet ,
     connectingWithContract,
}  from "../utils/apiFeature";

export const ChatAppContext = React.createContext();

export const ChatAppProvider = ({children}) =>{
    const title = "Hey welcome to blockchain chatApp";

    return   (
        <ChatAppContext.Provider value= {{title}}>
            {children}
        </ChatAppContext.Provider>
    );

}; 

pages>app.js


import React from 'react';
import "../styles/globals.css";
import { ChatAppProvider } from "../context/ChatAppContext";
import { NavBar } from "../components/index";

const MyApp = ({ Component, pageProps }) => (
  <div>
    <ChatAppProvider>  {/* Wrap the app with the provider */}
      <NavBar />
      <Component {...pageProps} />
    </ChatAppProvider>
  </div>
);

export default MyApp;

pages>index.js:


import React, { useEffect, useState, useContext } from "react"; // Correct import
import { ChatAppContext } from "../context/ChatAppContext";
const ChatApp =() =>{
 const {title} = useContext(ChatAppContext);
 return <div>{title}</div>;
};
  
  export default ChatApp;

utils> apiFeature.js:

import {ethers} from  "ethers";
import Web3Modal from "web3modal";

import {ChatAppAddress,ChatAppABI} from "../context/constants";

export const CheckIfWalletConnected =  async () =>{
    try {
        if(!window.ethereum) return console.log("Install MetaMask");
         const accounts = await window.ethereum.request({
      method:"rth_accounts",
         });
         const firstAccount = accounts[0];
         return firstAccount;
    }catch (error){
        console.log("error");
    }
};
export const connectWallet = async ()=>{

try {
    if(!window.ethereum) return console.log("Install MetaMask");
    const accounts = await window.ethereum.request({
    method: "eth_requestAccounts",
    });
    const firstAccount = accounts[0];
} catch (error) {
    console.log(error);
}

};

const fetchContract = (signerOrProvider)=>
new ethers.Contract(ChatAppABI,ChatAppAddress,signerOrProvider);

export const connectingWithContract =async () =>{
    try {
const web3modal = new Web3Modal();
const connection = await web3modal.connect();
const provider = new ethers.providers.Web3Provider(connection);
const signer = provider.getSigner();
const contract = fetchContract(signer);
 return contract;
    } catch(error){
        console.log(error);
    }

}
export const convertTime = (time)=>{
      const newTime = new Date (time.toNumber());
      const realTime = newTime.getHours()+"/" +
      newTime.getMinutes() + "/" + 
      newTime.getSeconds() + "Date:"+
      newTime.getDate() +
      "/"  +
    (  newTime.getMonth() + 1  ) +
    "/" + 
    newTime.getFullYear();
    return realTime;

      

}

Blazor Server JS interop DotNetObjectReference keeps state longer then wanted

I have several Blobs in a DB. These are displayed in an IFrame on a Popup, after the user clicks the button for a file on one of several possible components (.razor files). This works fine as long as I stay on the first component where I opened the Popup, but if I leave the component and reenter it i will always have null or empty on the IFrameSrc. This will also happen if I go to another component that could open a PDF. Reloading the page or opening it in a new Tab always fixes the problem. I noticed that when I dispose of the DotNetObjectReference at the end of HandelWantedFile further opening of PDFs will always throw an Excpetion and it will display the first file I opend on that component. This could be due to me not revoking the URL, but I still do not get how the old IFrameSrc is served instead.

Exception:

blazor.server.js:1 Uncaught (in promise) Error:
System.ArgumentException: There is no tracked object with id ‘5’.
Perhaps the DotNetObjectReference instance was already disposed.
(Parameter ‘dotNetObjectId’) at Microsoft.JSInterop.…64
dotNetObjectId) at
Microsoft.JSInterop.Infrastructure.DotNetDispatcher.BeginInvokeDotNet(JSRuntime
jsRuntime,…fo, String argsJson)
at y.endInvokeDotNetFromJS (blazor.server.js:1:3502)
at Xt._invokeClientMethod (blazor.server.js:1:61001)
at Xt._processIncomingData (blazor.server.js:1:58476)
at Xt.connection.onreceive (blazor.server.js:1:52117)
at s.onmessage (blazor.server.js:1:80262)

Does anybody have a idead on how to fix this or is able to point me in the right direction? I am currently unable to fix this myself. I need to display files from several components without forcing a reload upon first entering a component that could call the popup.

@* PdfPopUp.razor *@
@namespace Project.Pages
        
<MudDialog Style="width: 100%; height: 100%;">
 <DialogContent>
  @if (!string.IsNullOrEmpty(IframeSrc))
  {
    <iframe id="pdfIframe" src="@IframeSrc" style="width: 100%; height: 100vh; border: none;"
      frameborder="0"></iframe>
  }
  else
  {
    <p>Error: IFrameSrc is not set.</p>
  }
 </DialogContent>
</MudDialog>
        
@code {
 [Parameter] public string IframeSrc { get; set; } = string.Empty;
}

I call the PopUp like this

private async Task HandleWantedFile()
{
  byte[] file;
  file = await whaterver();//db call
  var dotNetReference = DotNetObjectReference.Create(this);
  await javaScript.InvokeVoidAsync("initializeBlobUrlCreation", dotNetReference);
  await javaScript.InvokeVoidAsync("createAndSetBlobUrl", "pdfIframe",
    file, "application/pdf", dotNetReference);
  var options = new DialogOptions { FullWidth = true, MaxWidth = MaxWidth.Large, CloseButton = true};
  dialogService.Show<PdfPopUp>(currentBlob.FileName, 
    new DialogParameters { ["IFrameSrc"] = this.IFrameSrc }, options);
}
      
[JSInvokable]
public async Task SetIframeSource(string url)
{
  IFrameSrc = url;
  await InvokeAsync(StateHasChanged);
}

my JavaScript:

function initializeBlobUrlCreation(dotNetRef) {
    window.createAndSetBlobUrl = function(iframeId, byteArray, mimeType) {
        var blob = new Blob([new Uint8Array(byteArray)], { type: mimeType });
        var url = URL.createObjectURL(blob);
        dotNetRef.invokeMethodAsync('SetIframeSource', url);
        var iframeElement = document.getElementById(iframeId);
        if (iframeElement) {
            iframeElement.src = url;
        }
    };
}

function createAndSetBlobUrl(iframeId, byteArray, mimeType) {
    var blob = new Blob([new Uint8Array(byteArray)], { type: mimeType });
    var url = URL.createObjectURL(blob);
    DotNet.invokeMethodAsync('Project', 'SetIframeSource', dotNetReference, url);
    var iframeElement = document.getElementById(iframeId);
    if (iframeElement) {
        iframeElement.src = url;
        scalePDF(iframeId);
    }
}

function scalePDF(iframeId) {
    var iframe = document.getElementById(iframeId);
    if (iframe) {
        iframe.onload = function () {
            var pdfContent = iframe.contentWindow.document.getElementsByTagName('body')[0];
            pdfContent.style.zoom = "100%";
        };
    }
}

I have a question about setState in React, specifically when it’s inside a callback function of a fetch and when it’s not

why in the first code when the setAllMemes is called the component wait for all the code to finish before re-rendering and in the second code it re-render before the code has finished

first code

import React from "react"

export default function Meme() {
    console.log("react render")
    const [allMemes, setAllMemes] = React.useState([])

    console.log("allMemes outside the use effect" , allMemes)    

    React.useEffect(() => {
    
        console.log("before setAllMemes")
        setAllMemes(["string1","string2"]);
        console.log("after setAllMemes");
            
        console.log("allMemes inside the use effect" , allMemes);
    }, [])

    return (
        <main>
        
        </main>
    )
}

the output in the console

›react render
›allMemes outside the use effect,[]
›before setAllMemes
›after setAllMemes
›allMemes inside the use effect,[]
›react render
›allMemes outside the use effect,["string1", "string2"]

second code

import React from "react"

export default function Meme() {
     console.log("react render")
     const [allMemes, setAllMemes] = React.useState([])

     console.log("allMemes outside the use effect" , allMemes)    

     React.useEffect(() => {
        fetch("https://api.imgflip.com/get_memes")
            .then(res => res.json())
            .then(data => {
                console.log("before setAllMemes")
                setAllMemes(data.data.memes);
                console.log("after setAllMemes");
                })
        console.log("allMemes inside the use effect" , allMemes);
        }, [])

        return (
            <main>
        
            </main>
        )
    }

the output in the console

›react render
›allMemes outside the use effect,[]
›allMemes inside the use effect,[]
›before setAllMemes
›react render
›allMemes outside the use effect [array of object from the api]
›after setAllMemes

Apple pay button in WooCommerce product page not working

enter image description hereI am trying to display and load the Apple Pay payment sheet on the product detail page using Apple Pay JS API. I am trying to create features so that customers can pay from the product page. My code can display the Apple Pay button but it is not loading the payment sheet means the event is not triggering.

here is the test code :

add_action( 'woocommerce_after_add_to_cart_button', 'mish_before_add_to_cart_btn' );

function mish_before_add_to_cart_btn(){
    global $product;
    $id = $product->get_id(); // Get the product ID
    $price = $product->get_price(); // Get the product price
    
    ob_start(); // Start output buffering
    ?>
    < html>
    <html >
    <head>
      
        <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
        <style>
       
            .apple-pay-button {
                width: 250px;
                height: 40px;
                display: inline-block;
                -webkit-appearance: -apple-pay-button;
                cursor: pointer;
            }
            .apple-pay-button-with-text>* {
                display: none;
            }
            .apple-pay-button-black-with-text {
                -apple-pay-button-style: black;
            }
            .apple-pay-button-white-with-text {
                -apple-pay-button-style: white;
            }
            .apple-pay-button-white-with-line-with-text {
                -apple-pay-button-style: white-outline;
            }
            .apple-pay-button-text-book {
                -apple-pay-button-type: book;
            }
            .apple-pay-button-text-buy {
                -apple-pay-button-type: buy;
            }
            .apple-pay-button-text-check-out {
                -apple-pay-button-type: check-out;
            }
            .apple-pay-button-text-donate {
                -apple-pay-button-type: donate;
            }
            @media only screen and (max-width: 600px) {
                .apple-pay-button {
                    width: 90%;
                    height: 50px;
                }
            }
        </style>
    </head>
    <body>
        <h1>Hello</h1>
        <div id="ckoApplePay" class="apple-pay-button apple-pay-button-text-buy" lang="en"></div>
        <p style="display:none" id="ckoApplePayError">ApplePay is not available in this environment.</p>
        <script>
           


document.getElementById("apple-pay-btn").onclick = function (evt) {

    if (window.ApplePaySession) {
        var merchantIdentifier = '';
        var promise = ApplePaySession.canMakePaymentsWithActiveCard(merchantIdentifier);
        promise.then(function (canMakePayments) {
            if (canMakePayments) {
                document.getElementById("applePay").style.display = "block";
                logit('hi, I can do ApplePay');
            } else {
                document.getElementById("got_notactive").style.display = "block";
                logit('ApplePay is possible on this browser, but not currently activated.');
            }
        });
    } else {
        logit('ApplePay is not available on this browser');
        document.getElementById("notgot").style.display = "block";
    }



    var runningAmount = 42;
    var runningPP = 0; getShippingCosts('domestic_std', true);
    var runningTotal = function () { return runningAmount + runningPP; }
    var shippingOption = "";

    var subTotalDescr = "Test Goodies";

    function getShippingOptions(shippingCountry) {
        logit('getShippingOptions: ' + shippingCountry);
        if (shippingCountry.toUpperCase() == "<?=PRODUCTION_COUNTRYCODE?>") {
            shippingOption = [{ label: 'Standard Shipping', amount: getShippingCosts('domestic_std', true), detail: '3-5 days', identifier: 'domestic_std' }, { label: 'Expedited Shipping', amount: getShippingCosts('domestic_exp', false), detail: '1-3 days', identifier: 'domestic_exp' }];
        } else {
            shippingOption = [{ label: 'International Shipping', amount: getShippingCosts('international', true), detail: '5-10 days', identifier: 'international' }];
        }

    }

    function getShippingCosts(shippingIdentifier, updateRunningPP) {

        var shippingCost = 0;

        switch (shippingIdentifier) {
            case 'domestic_std':
                shippingCost = 3;
                break;
            case 'domestic_exp':
                shippingCost = 6;
                break;
            case 'international':
                shippingCost = 9;
                break;
            default:
                shippingCost = 11;
        }

        if (updateRunningPP == true) {
            runningPP = shippingCost;
        }

        logit('getShippingCosts: ' + shippingIdentifier + " - " + shippingCost + "|" + runningPP);

        return shippingCost;

    }

    var paymentRequest = {
        currencyCode: '',
        countryCode: '',
        requiredShippingContactFields: ['postalAddress'],
        //requiredShippingContactFields: ['postalAddress','email', 'name', 'phone'],
        //requiredBillingContactFields: ['postalAddress','email', 'name', 'phone'],
        lineItems: [{ label: subTotalDescr, amount: runningAmount }, { label: 'P&P', amount: runningPP }],
        total: {
            label: '',
            amount: runningTotal()
        },
        supportedNetworks: ['amex', 'masterCard', 'visa'],
        merchantCapabilities: ['supports3DS', 'supportsEMV', 'supportsCredit', 'supportsDebit']
    };

    var session = new ApplePaySession(1, paymentRequest);

    // Merchant Validation
    session.onvalidatemerchant = function (event) {
        logit(event);
        var promise = performValidation(event.validationURL);
        promise.then(function (merchantSession) {
            session.completeMerchantValidation(merchantSession);
        });
    }


    function performValidation(valURL) {
        return new Promise(function (resolve, reject) {
            var xhr = new XMLHttpRequest();
            xhr.onload = function () {
                var data = JSON.parse(this.responseText);
                logit(data);
                resolve(data);
            };
            xhr.onerror = reject;
            xhr.open('GET', 'apple_pay_comm.php?u=' + valURL);
            xhr.send();
        });
    }

    session.onshippingcontactselected = function (event) {
        logit('starting session.onshippingcontactselected');
        logit('NB: At this stage, apple only reveals the Country, Locality and 4 characters of the PostCode to protect the privacy of what is only a *prospective* customer at this point. This is enough for you to determine shipping costs, but not the full address of the customer.');
        logit(event);

        getShippingOptions(event.shippingContact.countryCode);

        var status = ApplePaySession.STATUS_SUCCESS;
        var newShippingMethods = shippingOption;
        var newTotal = { type: 'final', label: '<?=PRODUCTION_DISPLAYNAME?>', amount: runningTotal() };
        var newLineItems = [{ type: 'final', label: subTotalDescr, amount: runningAmount }, { type: 'final', label: 'P&P', amount: runningPP }];

        session.completeShippingContactSelection(status, newShippingMethods, newTotal, newLineItems);


    }

    session.onshippingmethodselected = function (event) {
        logit('starting session.onshippingmethodselected');
        logit(event);

        getShippingCosts(event.shippingMethod.identifier, true);

        var status = ApplePaySession.STATUS_SUCCESS;
        var newTotal = { type: 'final', label: '<?=PRODUCTION_DISPLAYNAME?>', amount: runningTotal() };
        var newLineItems = [{ type: 'final', label: subTotalDescr, amount: runningAmount }, { type: 'final', label: 'P&P', amount: runningPP }];

        session.completeShippingMethodSelection(status, newTotal, newLineItems);


    }

    session.onpaymentmethodselected = function (event) {
        logit('starting session.onpaymentmethodselected');
        logit(event);

        var newTotal = { type: 'final', label: '<?=PRODUCTION_DISPLAYNAME?>', amount: runningTotal() };
        var newLineItems = [{ type: 'final', label: subTotalDescr, amount: runningAmount }, { type: 'final', label: 'P&P', amount: runningPP }];

        session.completePaymentMethodSelection(newTotal, newLineItems);


    }

    session.onpaymentauthorized = function (event) {

        logit('starting session.onpaymentauthorized');
        logit('NB: This is the first stage when you get the *full shipping address* of the customer, in the event.payment.shippingContact object');
        logit(event);

        var promise = sendPaymentToken(event.payment.token);
        promise.then(function (success) {
            var status;
            if (success) {
                status = ApplePaySession.STATUS_SUCCESS;
                document.getElementById("applePay").style.display = "none";
                document.getElementById("success").style.display = "block";
            } else {
                status = ApplePaySession.STATUS_FAILURE;
            }

            logit("result of sendPaymentToken() function =  " + success);
            session.completePayment(status);
        });
    }

    function sendPaymentToken(paymentToken) {
        return new Promise(function (resolve, reject) {
            logit('starting function sendPaymentToken()');
            logit(paymentToken);

            logit("this is where you would pass the payment token to your third-party payment provider to use the token to charge the card. Only if your provider tells you the payment was successful should you return a resolve(true) here. Otherwise reject;");
            logit("defaulting to resolve(true) here, just to show what a successfully completed transaction flow looks like");
            if (debug == true)
                resolve(true);
            else
                reject;
        });
    }

    session.oncancel = function (event) {
        logit('starting session.cancel');
        logit(event);
    }

    session.begin();



    function logit(data) {

        if (debug == true) {
            console.log(data);
        }

    };
};

        </script>
    </body>
    </html>
    <?php
    $output = ob_get_clean(); // Get the buffer contents and clean the buffer
    echo $output; // Output the captured content
}

I am expecting when the Apple Pay button is clicked it should trigger the payment sheet and produce a payment token to process the payment further. I have attached an image of my current output.

Why passing array from livewire info js code I got error?

On laravel 10 site using docs at https://dev.to/koossaayy/laravel-livewire-multiple-selection-with-virtual-select-1f87
I try to make multiselection,
but copypasting code of the project I got “Uncaught SyntaxError: Unexpected token ‘:’ “error on blade code :

<div>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/virtual-select.min.js" integrity="sha256-Gsn2XyJGdUeHy0r4gaP1mJy1JkLiIWY6g6hJhV5UrIw=" crossorigin="anonymous"></script>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/virtual-select.min.css" integrity="sha256-KqTuc/vUgQsb5EMyyxWf62qYinMUXDpWELyNx+cCUr0=" crossorigin="anonymous">

    resources/views/livewire/admin/users-permissions-editor.blade.php

    <div>

        <div id="permissions"></div>

            <script>
                const permissions = [
                    @foreach ($permissions as $permission)
                    {
                        label : '{{ $permission->name }}' , // ERROR POINTING THIS LINE
                        value : '{{ $permission->id }}'
                    },
                    @endforeach
                ];
                VirtualSelect.init({
                    ele: '#permissions',
                    multiple: true,
                    options: permissions,
                });
            </script>

    </div>
</div>

I replaced all symbols in code ‘{{ $permission->name }}’ and tried to wrap keys with ” symbol :

@foreach ($permissions as $permission)
{
    "label" : '{{ $permission->name }}' ,
    "value" : '{{ $permission->id }}'
},
@endforeach

I which way have I to pass an array here ?

"laravel/framework": "^10.48.4",
"livewire/livewire": "^3.4.9",

Thanks in advance!

Why is V8 anonymouse function context keeping unused variables?

I am debugging memory leaks in an Electron app with Chromium DevTools > Memory. The page uses DoJo dgrid and it has a class using event listener hooked on document object, see ColumnHider.js#L232. E.g. something like:

var activeGrid, bodyListener; // Global variables.

return declare(null, { // DoJo class definition (not important).
  // ...
  renderHeader: function () {
    var grid = this, ...; // These are kept in the listener context.
    // ...
    if (!bodyListener) {
       bodyListener = listen.pausable(document, 'mousedown', function (e) {
         activeGrid && activeGrid._toggleColumnHiderMenu(e); 
       });
       bodyListener.pause();
    }   
  }

When a grid is created and destroyed multiple times, DevTools > Memory snapshow shows a reference to the first instance is held by the var grid variable definition inside the renderHeader() method, i.e. bodyListener anonymous function context hold this reference even when it does not use it. (Note: the global variable activeGrid === null when I have taken the the memory snapshot.)

I always though JavaScript engine should keep used variables inside anonymous functions only in their context, so this kind of memory leak cannot occur. Or, is that influenced by DevTools somehow?

Image doesnt load from JSON file into HTML [closed]

When i run the code everyuthing turns up but the image, then it only the image icon appears where it should be

this is my script

let http = new XMLHttpRequest();
http.open('get', 'data.json', true);
http.send();
http.onload = function(){
   if(this.readyState == 4 && this.status == 200){
      let event = JSON.parse(this.responseText);
      let output = "";
      for(let events of event){
         output += `
            <div class="event">
               <img src="${events.eventImage}">
               <p class="title">${events.title}</p>
               <p class="description">${events.description}</p>
               <p class="price">
                  <span>${events.price}</span>
                  <span>€</span>
               </p>
               <p class="cart">See more<i class="bx bx-cart-alt"></i></p>
            </div>
         `;
      }
      document.querySelector(".events").innerHTML = output;
   }
}

snippet of json file

        "eventImage": {
            "url": "https://www.trumba.com/i/DgCtqtxj-SAcugHu%2AUYTldPI.jpg",
            "size": {
                "width": 1290,
                "height": 775
            }
        },

i tried changing into but then all the data dissapeared, the image did appear when i deleted the descriptions below eventImage and left only the url, but io cant manually intervene with all the json files manually

User Prompt to Login when not authenticated

I have given a task that when the user is trying the features of a website, they need to continue by logging in their account like all what other websites do. I’ve exhausted all options and don’t know how to implement this. Is there a way to solve this? If so, what are the steps and what do I need. I used Vue, Pinia, and Tailwind.

they must access a login modal in a NavBar.vue

<div v-if="showLoginModal" class=" fixed inset-0 flex items-center justify-center bg-gray-800 bg-opacity-75">
      <div class="relative bg-white lg:w-[70vw] w-[90vw] h-fit rounded-3xl">
        <img src="@/assets/images/Modal/Intersect.png" alt="" class="w-full absolute rounded-t-xl">

        <!-- Modal Content -->
        <div class="relative top-0 flex justify-end">
          <button class="absolute  pr-4 pt-4">
            <svg @click="closeOTP" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="5"
              stroke="black" class="w-7 h-7">
              <path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
            </svg>
          </button>
        </div>

        <div class="relative z-10 flex flex-col items-start justify-center h-fit lg:mt-[5rem] mt-[5rem] lg:ml-[6%] m-8">
          <div class="mt-5 mb-5">
            <h2 class="text-2xl lg:text-3xl font-bold">Welcome!</h2>
            <p class="text-xs lg:text-sm">Please log in to your account.</p>
          </div>

          <form @submit.prevent="login" class=" lg:w-[40%] h-fit md:w-[40%] w-full mr-8">
            <!-- username -->
            <div class="relative mb-4 w-full md:w-365">
              <label for="username" class="block text-gray-700">Enter Username</label>
              <div class="relative">
                <img src="@/assets/images/Modal/profile.png" class="absolute inset-y-0 left-0 mx-5 my-3"
                  style="width: 15px;" alt="Username Icon" />
                <input type="text" id="username" v-model="username" @input="validateUsername"
                  class="w-full h-8 py-5 pl-10 border border-black rounded-xl" placeholder="Username">
                <span v-if="usernameError" class="text-red-500 text-xs">{{ usernameError }}</span>
              </div>
            </div>
            <!-- login password -->
            <div class="relative mb-4">
              <label for="lpassword" class="w-full text-gray-700">Enter Password</label>
              <div class="relative w-full">
                <img src="@/assets/images/Modal/profile.png" class="absolute inset-y-0 left-0 mx-5 my-3"
                  style="width: 15px;" alt="Username Icon" />
                <img v-if="showPassword" src="@/assets/images/Modal/view.png"
                  class="absolute inset-y-0 right-0 mx-3 my-3" style="width: 15px; cursor: pointer;" alt="Eye Icon"
                  @click="togglePasswordVisibility">
                <img v-else src="@/assets/images/Modal/hidden.png" class="absolute inset-y-0 right-0 mx-3 my-3"
                  style="width: 15px; cursor: pointer;" alt="Eye Icon" @click="togglePasswordVisibility">
                <input id="lpassword" v-model="lpassword" @input="validateLPassword"
                  :type="showPassword ? 'text' : 'password'"
                  class="w-full h-8 py-5 pl-10 border border-black rounded-xl" placeholder="Password">
                <span v-if="lpasswordError" class="text-red-500 text-xs">{{ lpasswordError }}</span>
              </div>
            </div>

            <div class="hidden lg:block lg:flex items-center justify-between mb-4">
              <p class="text-xs">Don't have an account? <button @click="openPrivacyModal"
                  class="text-xs font-bold text-blue-600">Sign Up</button></p>
              <button @click="openForgotModal" class="text-xs text-blue-600 font-bold">Forgot Password?</button>
            </div>

            <div class="hidden lg:block lg:mt-10 text-center">
              <button type="submit"
                class="lg:w-[8rem] w-full lg:px-4 py-2 text-white disabled:bg-blue-400 bg-blue-600 rounded-md"
                :disabled="!isLoginFormValid" @click="login">Login</button>
            </div>

            <div class="lg:hidden lg:mt-10 text-center">
              <button type="submit" :disabled="!isLoginFormValid" @click="login"
                class="lg:w-[8rem] w-full lg:px-4 py-2 lg:mb-10 text-white disabled:bg-blue-400  bg-blue-600 rounded-md">Login</button>
              <button @click="openForgotModal" class="text-xs text-blue-600 mt-1">Forgot Password?</button>
              <button @click="openPrivacyModal"
                class="w-full mt-8 py-2 border border-blue-400 text-blue-600 bg-white rounded-md">Sign Up</button>
            </div>
          </form>
        </div>
      </div>
    </div>

Why can’t connect to my websocket handler

I am developing a SPA with vuejs + vite

I have a websocket endpoint in my back-end.

And I can connect to that websocket via cli tool websocat.

but when try to connect in javascript, both firefox and chrome show connection error.

the vite developement server was proxying my backend using configs below:

server: {
      // 允许IP访问
      host: "portal-local.itps.xxx.com",
      // 应用端口 (默认:3000)
      port: Number(env.VITE_APP_PORT),
      // 运行是否自动打开浏览器
      open: true,
      https: {
        key: fs.readFileSync(
          "/home/ggfan/2-work/git/itps/1A-IaaS-Manifests/kubernetes/1.27/ssl/certs/itps.xxx.com/privkey.pem"
        ),
        cert: fs.readFileSync(
          "/home/ggfan/2-work/git/itps/1A-IaaS-Manifests/kubernetes/1.27/ssl/certs/itps.xxx.com/fullchain.pem"
        ),
      },
      proxy: {
        /**
         * 反向代理解决跨域配置
         * http://localhost:3000/dev-api/users (F12可见请求路径) => http://localhost:8989/users (实际请求后端 API 路径)
         *
         * env.VITE_APP_BASE_API: /dev-api
         * env.VITE_APP_API_URL: http://localhost:8989
         */
        /*
        [env.VITE_APP_BASE_API]: {
          changeOrigin: true,
          target: "http://localhost:8080",
          rewrite: (path) =>
            path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""),
        },
        */
        ["/oauth2"]: {
          changeOrigin: true,
          target: "https://api.itps.xxx.com",
          // secure: false,
          rewrite: (path) => path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""),
          /*
          cookieDomainRewrite: {
            "itps.xxx.com": "localhost",
          },
          */
        },
        ["/pus"]: {
          changeOrigin: true,
          target: "http://localhost:8080",
          // secure: false,
          rewrite: (path) => path.replace(/^/pus/, ""),
          /*
          cookieDomainRewrite: {
            "itps.xxx.com": "localhost",
          },
          */
          configure: proxyConfig,
        },
        ["/ws"]: {
          changeOrigin: true,
          target: "http://localhost:8080",
          ws: true,
          secure: false,
          rewrite: (path) => path.replace(/^/ws/, ""),
          configure: proxyConfig,
        },
      },
    }

connecting with websocat:
enter image description here

my typescript code:

  const ws = new WebSocket("wss://portal-local.itps.xxx.com:3000/ws/export/sea/users")
  ws.onopen = () => {
    ws.send("{}")
  }
  ws.onmessage = async (event) => {
    console.log(event.data)
    await writable.write(event.data)
  }
  ws.onclose = async (event) => {
    await writable.close()
  }

Chrome error:

SEAExportDialog.vue:104 WebSocket connection to 'wss://portal-local.itps.xxx.com:3000/ws/export/sea/users' failed: 

the certs was obtained from let’s encrypt, if that matters.

Using gtag dataLayer in Google Tag Manager

Although I started using Google Tag Manager log times ago, I have my legacy tracking (gtag) still available on my website.
So, in my GTM container, I can see all events(gtag and GTM dayaLayer) in the summary. That being said I have two different dataLayer on my website as follows:
1- gtag (dataLayer)
2- gtm (mainDataLayer)

Almost 100% of my e-commerce data is available in gtag dataLayer, and I can see all dataLayer push coming to the GTM from gtag with appropriate e-commerce data. Unfortunately, I can’t use them because the name of dataLayer is different. I thought there might be another solution to use the gtag datacenter in Google Tag Manager. I need to set my eCommerce triggers based on gtag dataLayer push in GTM.
Is it feasible?

enter image description here
enter image description here

enter image description here

How to upload folders to react with special characters in the name

I have a problem with my javascript uploading:
I am using this code:

const handleParameterSearchUpload = async (event) => {
    const files = event.target.files;
    console.log(files);
    const folders = {};

    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      const filePath = file.webkitRelativePath;
      const pathParts = filePath.split('/');

      // If the file is in a subfolder, add the file to the folder's list
      if (pathParts.length > 2) {
        const folderName = encodeURIComponent(pathParts[1]);
        if (!folders[folderName]) {
          folders[folderName] = [];
        }
        folders[folderName].push(file);
      }
    }
    console.log(folders.length);
    // Call processFiles for each folder
    for (const folderName in folders) {
      const folderFiles = folders[folderName];
      await processFiles(folderFiles, true);
      console.log("Processed", folderName);
    }
    parameterSearchInputRef.current.value = "";
  };

to process the files in a folder.

This code is used here:

<input
  type="file"
  webkitdirectory="true"
  style={{ display: 'none' }
  ref={parameterSearchInputRef} 
  onChange={handleParameterSearchUpload} 
/>

Now in this folder there are files and subfolders which are not empty.
Unfortunately I have a problem.
When I upload the folder the files are uploaded, but not the subfolders.
The code is not the problem, because when I rename the folder it works fine, but with this folder name which I upload:

20240118-165159[param.defaults]CombinationParamSearch{sheets.l4_cortex_inh.params.cell.params.v_thresh_[-57.5, -58],sheets.l4_cortex_exc.AfferentConnection.base_weight_[0.0013, 0.0016, 0.0018]}

it doesn’t work.

Unfortunately I will always upload these types of folders to the webpage, how to resolve the issue?
The subfolders have the following name:
SelfSustainedPushPull_ParameterSearch_____base_weight_0.0013_v_thresh_-57.5
SelfSustainedPushPull_ParameterSearch_____base_weight_0.0013_v_thresh_-58

and so on

Unfortunately the base problem is that the subfolders seem like are not getting uploaded, because if I log the console, the subfolders nor the contents inside them are not getting logged.
I really don’t know how to resolve this issue, without using packages like fs or path. Any ideas? Unfortunately I can’t just ask the users to rename the folders, because these folder names are generated from another software.

Overlay area not Cropping when crop function is clicked on it getting error in console

When i click on crop function getting and error message – Failed to execute ‘drawImage’ on ‘CanvasRenderingContext2D’: The image argument is a canvas element with a width or height of 0.

Tried many ways got stuck here need to get the cropped image in base64 url.
I am building a standalone JavaScript image cropper added a overlay to crop the image but facing issue while cropping the image getting some error message in console when called crop function.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Image Cropper</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" />
  <style>
    body,
    html {
      margin: 0;
      padding: 0;
      height: 95vh;
      background-color: #222;
      color: #fff;
    }

    canvas {
      object-fit: contain;
      width: 100vw;
      height: 90vh;
      cursor: crosshair;
      display: block;
      background-color: #222;
      margin-top: 3vh;
    }

    .button-container {
      position: relative;
      margin-top: 10px;
    }

    .left-buttons {
      float: left;
      margin-left: 10px;
    }

    .right-buttons {
      float: right;
      margin-right: 10px;
    }

    .image-container {
      display: flex;
      justify-content: center;
      align-items: center;
      background-color: #222;
      position: relative;
    }

    .bottom-buttons {
      position: absolute;
      bottom: 10px;
      left: 10px;
      margin-bottom: 8px;
    }

    select {
      margin: 0 10px;
      background-color: #444;
      color: #fff;
    }

    /* Modal styles */
    .modal {
      display: none;
      position: fixed;
      z-index: 1;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      overflow: auto;
      background-color: rgba(0, 0, 0, 0.5);
    }

    .modal-content {
      background-color: #333;
      margin: 0 auto;
      padding: 20px;
      border: 1px solid #888;
      width: 80%;
      max-width: 700px;
      position: relative;
      border-radius: 8px;
      color: #fff;
    }

    .close {
      position: absolute;
      top: 10px;
      right: 10px;
      color: #aaa;
      font-size: 28px;
      font-weight: bold;
      cursor: pointer;
    }

    .close:hover,
    .close:focus {
      color: #fff;
      text-decoration: none;
    }

    .modal-content img {
      max-width: 100%;
      height: auto;
      display: block;
      margin: auto;
    }

    .zoom-buttons {
      position: absolute;
      bottom: 10px;
      right: 10px;
    }

    .zoom-buttons button {
      margin-left: 5px;
      background-color: #fff;
      color: black;
      border: none;
      padding: 5px;
      cursor: pointer;
    }

    .zoom-buttons button:hover {
      background-color: #666;
    }

    #overlay {
      position: absolute;
      width: 200px;
      height: 200px;
      background-color: rgba(0, 0, 0, 0.5);
      border: 2px solid yellow;
      cursor: move;
    }

    #overlay div {
      position: absolute;
      width: 10px;
      height: 10px;
      background-color: white;
    }

    #overlay div.top-left {
      top: -5px;
      left: -5px;
      cursor: nwse-resize;
    }

    #overlay div.top-right {
      top: -5px;
      right: -5px;
      cursor: nesw-resize;
    }

    #overlay div.bottom-left {
      bottom: -5px;
      left: -5px;
      cursor: nesw-resize;
    }

    #overlay div.bottom-right {
      bottom: -5px;
      right: -5px;
      cursor: nwse-resize;
    }


    /* Crosshair style */
    #crosshair {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 0;
      height: 0;
      border-left: 1px solid white;
      border-right: 1px solid white;
      border-top: 1px solid white;
      border-bottom: 1px solid white;
      pointer-events: none;
    }
  </style>
</head>

<body>
  <div class="button-container">
    <div class="left-buttons">
      <img id="brookImage" src="rope41.png" style="display: none;" onload="loadImage()">
      <select id="shapeSelect" onchange="selectShape()">
        <option value="rectangle" selected>Rectangle</option>
        <option value="circle">Circle</option>
      </select>
    </div>
    <div class="right-buttons">
      <button onclick="cropImage()"><i class="fas fa-check"></i></button>
      <button onclick="resetImage()"><i class="fas fa-x"></i></button>
    </div>
  </div>
  <div class="image-container">
    <canvas id="canvas"></canvas>
    <div id="overlay">
      <div id="crosshair"></div>
      <div class="top-left"></div>
      <div class="top-right"></div>
      <div class="bottom-left"></div>
      <div class="bottom-right"></div>
    </div>
  </div>
  <div class="bottom-buttons">
    <button onclick="rotateLeft()"><i class="fas fa-rotate-left"></i></button>
    <button onclick="rotateRight()"><i class="fas fa-rotate-right"></i></button>
  </div>

  <div class="zoom-buttons bottom-right">
    <button onclick="zoomIn()"><i class="fas fa-search-plus"></i></button>
    <button onclick="zoomOut()"><i class="fas fa-search-minus"></i></button>
  </div>

  <!-- The Modal -->
  <div id="myModal" class="modal">
    <!-- Modal content -->
    <div class="modal-content">
      <span class="close" onclick="closeModal()">&times;</span>
      <img id="croppedImagePreview" src="" alt="Cropped Image" />
    </div>
  </div>

  <script>
    let canvas = document.getElementById("canvas");
    let ctx = canvas.getContext("2d");
    let imageObj = null;
    let startX, startY, endX, endY;
    let isDragging = false;
    let selectedShape = "rectangle";
    let shapes = [];
    let croppedCanvas = document.createElement("canvas");
    let croppedCtx = croppedCanvas.getContext("2d");
    let scale = 1; // Initial scale
    let overlay = document.getElementById("overlay");
    let offsetX, offsetY;
    let resizingCorner = null;

    function loadImage() {
      let imageElement = document.getElementById("brookImage");
      imageObj = new Image();
      imageObj.onload = function () {
        canvas.width = imageObj.width;
        canvas.height = imageObj.height;
        ctx.drawImage(imageObj, 0, 0);
      };
      imageObj.src = imageElement.src;
    }

    function selectShape() {
      selectedShape = document.getElementById("shapeSelect").value;
    }

    function cropImage() {
      let shape = {
        type: selectedShape,
        startX: parseInt(overlay.style.left),
        startY: parseInt(overlay.style.top),
        endX: parseInt(overlay.style.left) + parseInt(overlay.style.width),
        endY: parseInt(overlay.style.top) + parseInt(overlay.style.height),
      };
      shapes.push(shape);

      let width = parseInt(overlay.style.width);
      let height = parseInt(overlay.style.height);

      let cropX = parseInt(overlay.style.left);
      let cropY = parseInt(overlay.style.top);

      // Use overlay position and size for cropping
      let tempCanvas = document.createElement("canvas");
      let tempCtx = tempCanvas.getContext("2d");

      tempCanvas.width = width;
      tempCanvas.height = height;

      if (shape.type === "rectangle") {
        tempCtx.drawImage(
          canvas,
          cropX, cropY,
          width, height,
          0, 0,
          width, height
        );
      } else if (shape.type === "circle") {
        // Circle cropping remains the same
      }

      // Clear the canvas and draw the cropped image
      croppedCtx.clearRect(0, 0, croppedCanvas.width, croppedCanvas.height);
      croppedCanvas.width = width;
      croppedCanvas.height = height;
      croppedCtx.drawImage(tempCanvas, 0, 0);

      // Display the cropped image
      document.getElementById("croppedImagePreview").src = croppedCanvas.toDataURL();
      document.getElementById("myModal").style.display = "block";

      console.log(croppedCanvas.toDataURL());
    }

    function updateOverlayPosition() {
      let overlayWidth = Math.abs(endX - startX);
      let overlayHeight = Math.abs(endY - startY);
      let overlayX = Math.min(startX, endX);
      let overlayY = Math.min(startY, endY);

      overlay.style.width = overlayWidth + "px";
      overlay.style.height = overlayHeight + "px";
      overlay.style.left = overlayX + "px";
      overlay.style.top = overlayY + "px";

      // Update crosshair position
      let crosshair = document.getElementById("crosshair");
      crosshair.style.left = overlayWidth / 2 + "px";
      crosshair.style.top = overlayHeight / 2 + "px";
    }

    function resetImage() {
      shapes = [];
      croppedCtx.clearRect(0, 0, croppedCanvas.width, croppedCanvas.height);
    }

    function closeModal() {
      document.getElementById("myModal").style.display = "none";
    }

    let rotation = 0;
    function rotateLeft() {
      rotation -= Math.PI / 2;
      drawRotatedImage(rotation);
    }

    function rotateRight() {
      rotation += Math.PI / 2;
      drawRotatedImage(rotation);
    }

    function drawRotatedImage(rotation) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.save();
      ctx.translate(canvas.width / 2, canvas.height / 2);
      ctx.rotate(rotation);
      ctx.drawImage(
        imageObj,
        -canvas.width / 2,
        -canvas.height / 2,
        canvas.width,
        canvas.height
      );
      ctx.restore();
    }

    overlay.addEventListener('mousedown', function (event) {
      isDragging = true;
      let rect = canvas.getBoundingClientRect();
      offsetX = event.clientX - rect.left - overlay.offsetLeft;
      offsetY = event.clientY - rect.top - overlay.offsetTop;

      console.log("OffsetX:", offsetX);
      console.log("OffsetY:", offsetY);

      document.addEventListener('mousemove', dragOverlay);

      function dragOverlay(event) {
        let mouseX = event.clientX - rect.left;
        let mouseY = event.clientY - rect.top;

        // Calculate the new position for the overlay
        let newLeft = mouseX - offsetX;
        let newTop = mouseY - offsetY;

        // Ensure the overlay stays within the bounds of the canvas
        newLeft = Math.min(Math.max(0, newLeft), rect.width - overlay.offsetWidth);
        newTop = Math.min(Math.max(0, newTop), rect.height - overlay.offsetHeight);

        overlay.style.left = newLeft + 'px';
        overlay.style.top = newTop + 'px';
      }

      document.addEventListener('mouseup', function () {
        isDragging = false;
        document.removeEventListener('mousemove', dragOverlay);
      });
    });


    function updateOverlayPosition() {
      let overlay = document.getElementById("overlay");
      let overlayWidth = Math.abs(startX - endX);
      let overlayHeight = Math.abs(startY - endY);
      let overlayX = Math.min(startX, endX);
      let overlayY = Math.min(startY, endY);

      overlay.style.width = overlayWidth + "px";
      overlay.style.height = overlayHeight + "px";
      overlay.style.left = overlayX + "px";
      overlay.style.top = overlayY + "px";

      // Update crosshair position
      let crosshair = document.getElementById("crosshair");
      crosshair.style.left = overlayWidth / 2 + "px";
      crosshair.style.top = overlayHeight / 2 + "px";
    }

    function zoomIn() {
      scale += 0.1;
      drawZoomedImage();
    }

    function zoomOut() {
      scale -= 0.1;
      drawZoomedImage();
    }

    function drawZoomedImage() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.save();
      ctx.translate(canvas.width / 2, canvas.height / 2);
      ctx.scale(scale, scale);
      ctx.drawImage(imageObj, -canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height);
      ctx.restore();
    }
  </script>
</body>

</html>

Autodesk Forge error #9 – No viewable content

I am trying to upload my model using Autodesk Forge. I got all the necessary tokens and URN using Postman. I wrote the code using the instructions, but it gives error #9. I still haven’t figured out how to fix it.

I found such a message on the page, I didn’t really understand how it works, but if I understood correctly, then this is a message that my requests are being blocked, maybe because of this I get such an error, but I couldn’t fix it either
I’ve tried downloading other models, but to no avail
I hid my token, but left the string with the URN, because it seems to me that I might somehow incorrectly specify it

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Autodesk Forge Viewer</title>
    <script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.54/viewer3D.min.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
        #forgeViewer {
            width: 100%;
            height: 100vh;
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
    <div id="forgeViewer"></div>

    <script>
        var options = {
            env: 'AutodeskProduction',
            api: 'derivativeV2',
            getAccessToken: function(onTokenReady) {
                var accessToken = '<my_token>';
                var expireTimeSeconds = 60 * 30;
                onTokenReady(accessToken, expireTimeSeconds);
            }
        };
        var documentId = 'urn:dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6bG9yZDYwNi9yYWNhZHZhbmNlZHNhbXBsZXByb2plY3QucnZ0';

        Autodesk.Viewing.Initializer(options, function() {
            var viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer'));
            viewer.start();
            Autodesk.Viewing.Document.load(documentId, function(document) {
                var defaultModel = document.getRoot().getDefaultGeometry();
                viewer.loadDocumentNode(document, defaultModel);
            }, function(errorMsg) {
                console.error('Load Error: ' + errorMsg);
            });
        });
    </script>
</body>
</html>    ```

How can I download the current tab url from a chrome extension service worker if the current tab is a pdf?

So I’m building a Chrome extension using Kotlin JS that will create a context menu button that will allow users to import the contents of the current tab into the extension and do useful things with it. If you’re interested in what those useful things are you can see a non functional v0.1 of it here or checkout the website.

I have it mostly working but it fails when a pdf is open in the current tab. A minimal working example that reproduces the issue is below

import app.externals.chrome.contextMenus.OnClickData
import io.ktor.client.HttpClient
import io.ktor.client.request.get
import io.ktor.client.statement.readBytes
import js.objects.jso
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

private val client = HttpClient()

private suspend fun downloadPage(onClickData: OnClickData): ByteArray? {
    return onClickData.frameUrl?.let { client.get(it).readBytes() }
}

fun main() {
    app.externals.chrome.runtime.onInstalled.addListener {
        externals.chrome.contextMenus.create(jso {
            this.id = "download-page"
            this.title = "download-page"
            this.contexts = arrayOf("all")
        })
    }

    app.externals.chrome.contextMenus.onClicked.addListener { onClickData, _ ->
        if (onClickData.menuItemId == "download-page") {
            GlobalScope.launch {
                downloadPage(onClickData)
            }
        }
    }
}

When the “download-page” context menu button is clicked it will get the url of the current tab and download its contents. This works fine for most sites, but if I try it on a pdf document like this one I get a CORS error

Access to fetch at 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf' from origin 'chrome-extension://bdicfcohaofoaoakidlocbdaphldiaok' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. 

I’m guessing this has something to do with the fact that Chrome views pdf documents in iframes through what’s basically an embedded application. I want to resolve this issue and have the service worker successfully download the pdf.

I made some progress in an unexpected way. If I define a blank content script and have the manifest run it for pdf urls it magically works.

{
  "manifest_version": 3,

  "name": "The Grok App",
  "description": "Search For Your Documents",
  "version": "0.2.0",

  "action": {
    "default_icon": "logo_no_text128.png"
  },

  "icons": {
    "16": "logo_no_text16.png",
    "48": "logo_no_text48.png",
    "64": "logo_no_text64.png",
    "128": "logo_no_text128.png"
  },

  "background": {
    "service_worker": "chromeExtensionBackground.js"
  },

  "side_panel": {
    "default_path": "sidePanel.html"
  },

  "content_scripts": [
    {
      "matches": ["https://*/*.pdf"],
      "js": ["content.js"],
      "run_at": "document_idle"
    }
  ],

  "permissions": [
    "activeTab",
    "contextMenus",
    "scripting",
    "sidePanel"
  ]
}

Here content.js is totally blank and does nothing. I don’t totally understand why this works, but it seems to fix the problem, which would be fine but I’m not sure the Chrome extension reviewers will be okay with me running a blank js file on all pdf files as a work around for what really seems like a bug. So any other solutions would be appreciated!