The conditional code is running without checking the condition

I am trying to hide an element if the mousedown event gets triggered on body but don’t want it to hide if another element is clicked. The code is working fine if I don’t use the logical or Operator and use only one condition.

.aa{
    position: absolute;
    top: 7rem;
    left: 5rem;
    width:20rem;
    height: 20rem;
    background-color:rgba(39, 139, 69, 0.733) ;
}
button{
    position: relative;
    top: 8rem;
    left: 8rem;
    background-color: #f0ff1f;
    border: none;
    padding: 1rem;
    width: 5rem;
    color: rgb(255, 255, 255);

}
button:active{
    background-color: #565c0b;
}
.da{
    position: absolute;
    top: 8rem;
    left: 30rem;
    width: 15rem;
    height: 15rem;
    background-color:rgba(1, 111, 255, 0.733) ;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body style="background-color: rgb(47, 53, 54);">
   <div class="aa"><button>button</button></div>
   <div class="da"></div>
    <script>
document.onmousedown =function(event){
    
    if(event.target.tagName!='BUTTON'  ||  event.target.className!='aa')
      document.getElementsByClassName('da')[0].style.display = 'none';
console.log(event.target.className!='da' || event.target.tagName!='BUTTON')
console.log(event.target.tagName, event.target.className)}

    </script>
</body>

</html>

Restricted Data Token (RDT) for self-authorized app

I’m trying to retrieve order data from an express.js backend using the Amazon sp-api. I also need address data, customization data etc, which requires me to get a Restricted Data Token (RDT). On the app registration page I selected all types of information that the app should get access to:

enter image description here

But when I try to retrieve the token, I’m getting this error:

Amazon SP API Error: CustomError: Application does not have access to one or more requested data elements: [buyerInfo, buyerCustomizedInfo, shippingAddress]

I tried many different values, but it doesn’t work. Here’s how I make the call:

      const rdt = await spApi.callAPI({
        operation: 'createRestrictedDataToken',
        endpoint: 'tokens',
        body: {
            restrictedResources: [
                {
                    method: 'GET',
                    path: '/orders/v0/orders',
                    dataElements: ['shippingAddress']
                }
            ]
        }
    });

I can only retrieve basic data now, but the RDT thing doesn’t work. Does anyone have experience with this?

When downloading files or downloading multiple files in a zip, it shows the file is insecure or corrupted at times

Have a downloadFiles function in my code which allows users to either download individual files or multiple files in a zip. However, every download comes back as ‘insecure’ or ‘corrupted’, not sure where in my code I’m going wrong or if its some server error or CORS error. Would appreciate some assistance for this.

The downloadFiles function:

  const downloadFiles = async (items: typeof miscellaneousData) => {
    if (items.length === 1) {
      const link = document.createElement('a');
      link.href = items[0].downloadLink;
      link.setAttribute('download', '');
      link.style.display = 'none';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      return;
    }

    const zip = new JSZip();
    
    try {
      items.forEach((item) => {
        const fileName = item.downloadLink.split('/').pop() || 'document.docx';
        zip.file(fileName, item.downloadLink);
      });

      const content = await zip.generateAsync({ type: 'blob' });
      const zipUrl = URL.createObjectURL(content);
      
      const link = document.createElement('a');
      link.href = zipUrl;
      link.download = 'templates.zip';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      URL.revokeObjectURL(zipUrl);
    } catch (error) {
      console.error('Error creating zip:', error);
      items.forEach((item, index) => {
        setTimeout(() => {
          const link = document.createElement('a');
          link.href = item.downloadLink;
          link.setAttribute('download', '');
          link.style.display = 'none';
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
        }, index * 1000);
      });
    }
  };

On my local server it works fine, no insecure or corruption, but on production/live site it always comes back as insecure/corrupted for individual or bulk downloads in a zip.

Obviously want this so on production it downloads files securely/non-corrupted.

THe files are stored/inputted as a URL in the codebase and I believe my function is extracting the URL rather than the file content. However I’ve tried to extract the file content instead but it returns the same issues or incorrect functionality such as not being able to download in bulk etc.

i want to run a website inside webview on android but it uses getusermedia

the thing is it uses getusermedia and it only works in secure contexts & i want the app to be offline
i’m using webview on react native
it opens like with about protocol and getusermedia does not work on that

i have tried using pwa on site but it would’t work once the app was closed it needed internet again when i tested it in apk
what to do ?

when i test webview with a https server it works as expected but it is online i want my app to be completely offline
using inline html and files when opened the getuseredia function does not work
the webview opens the files with about protocol

can we change that ?

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Simple Frequency Tuner</title>
    <link rel="manifest" href="manifest.json">
    <style>
        body {
            font-family: sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        .frequency-display {
            font-size: 48px;
            text-align: center;
            color: #333;
            background: white;
            padding: 2rem;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .Hz {
            font-size: 24px;
            color: #666;
            margin-left: 8px;
        }
    </style>
</head>
<body>
      <div id="network-status" class="online">You are online</div>

    <div class="frequency-display">
        <span id="frequency">0.0</span>
        <span class="Hz">Hz</span>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/aubio.min.js"></script>
    <script>
        class Tuner {
            constructor() {
                this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
                this.analyser = this.audioContext.createAnalyser();
                this.bufferSize = 4096;
                this.scriptProcessor = this.audioContext.createScriptProcessor(
                    this.bufferSize, 1, 1
                );
                this.frequencyDisplay = document.getElementById('frequency');
            }

            start() {
                const self = this;
                navigator.mediaDevices.getUserMedia({ audio: true })
                    .then(function(stream) {
                        self.audioContext.createMediaStreamSource(stream)
                            .connect(self.analyser);
                        self.analyser.connect(self.scriptProcessor);
                        self.scriptProcessor.connect(self.audioContext.destination);
                        
                        aubio().then(function(aubio) {
                            const pitchDetector = new aubio.Pitch(
                                "default",
                                self.bufferSize,
                                1,
                                self.audioContext.sampleRate
                            );

                            self.scriptProcessor.addEventListener('audioprocess', function(event) {
                                const frequency = pitchDetector.do(
                                    event.inputBuffer.getChannelData(0)
                                );
                                if (frequency) {
                                    self.frequencyDisplay.textContent = frequency.toFixed(1);
                                }
                            });
                        });
                    })
                    .catch(function(error) {
                        alert('Error accessing microphone: ' + error.message);
                    });
            }
        }

        // Start the tuner when the page is clicked
        document.body.addEventListener('click', function() {
            new Tuner().start();
        }, { once: true });
    </script>
      <script>
        // Register the service worker
        if ('serviceWorker' in navigator) {
          window.addEventListener('load', () => {
            navigator.serviceWorker.register('/service-worker.js')
              .then((registration) => {
                console.log('Service Worker registered with scope:', registration.scope);
              })
              .catch((error) => {
                console.log('Service Worker registration failed:', error);
              });
          });
        }
      </script>
    <script>
        // Function to update the network status
        function updateNetworkStatus() {
            const statusBanner = document.getElementById('network-status');
            if (navigator.onLine) {
                statusBanner.textContent = 'You are online';
                statusBanner.className = 'online';
            } else {
                statusBanner.textContent = 'You are offline. Content may be unavailable.';
                statusBanner.className = 'offline';
            }
        }

        // Listen for online and offline events
        window.addEventListener('online', updateNetworkStatus);
        window.addEventListener('offline', updateNetworkStatus);

        // Initial check of the network status
        updateNetworkStatus();
    </script>
</body>
</html>

`

here is the complete code

Fetching from a local JSON file not returning any data, function stops running when fetch added

Trying to fetch a json array from a local json file. The function runs fine when the fetch is not there but as soon as I added the fetch it doesn’t run the function at all. I added a console log to the top of the function and it doesn’t pop up if the fetch is added.

So basically I’ve tried multiple different methods to fetch, I’ve tried no .then(), I’ve used the same method as my other project with a json array in a local file and has had the same result repeatedly. The function doesn’t even console log, is there anywhere I could have went wrong?

Please see my code below:

HTML:


<body onload="sortLocations()">



    <script src="test-script.js"></script>



</body>

JavaScript:






async function sortLocations() {



  



  console.log('1')



  



    let loc1 = await fetch("locations-test.json", {



        method: "GET",



        headers: {



            Accept: "application/json"



        }



    })



        .then(response => response.json())



        .then(response => console.log(JSON.stringify(response)));



       



  console.log('2')



  

  \ ... Code to use the fetched data ...

  

JSON example to be fetched: (…) is in same format as example


[

  {...},

  {...},

  {...},

  {

        company: "text",

        banner: "text",

        icon: "text",

        locations: [

            {

                name: "text",

                img: "text",

                latLong: [num, num],

                address: "text",

                postcode: "text",

                tenants: [

                    {

                        company: "text",

                        banner: "text",

                        icon: "text"

                    }

                ]

            }

        ]

      },

  {...}, 

  {...}

]

“Load More” button in JavaScript

I’m working on calling an API to fetch information from a movie search website. I’m trying to create a “Load More” button in JavaScript, but my code isn’t working. What could be the reason?

document.addEventListener("DOMContentLoaded", initializePage);
document.addEventListener("DOMContentLoaded", () => {
    
    const urlParams = new URLSearchParams(window.location.search);
   
    const values = [...urlParams.values()];
    const searchValue = values[0];
    let yearValue = values[1];
    let genreValue = values[2];

    const yearCheckboxes = document.querySelectorAll(".yearlist-yearchk");
    const genreCheckboxes = document.querySelectorAll(".genrelist-genrechk");

    yearCheckboxes.forEach((checkbox) => {
        if (checkbox.value === yearValue) {
            checkbox.checked = true;
        }
        checkbox.addEventListener("change", () => {
            yearCheckboxes.forEach((cb) => {
                if (cb !== checkbox) {
                    cb.checked = false;
                }
                else if(checkbox) {
                    yearValue = checkbox.value;
                    console.log(yearValue);
                    getMovies(searchValue,yearValue,genreValue,1);
                }
            });
        });
    });

    genreCheckboxes.forEach((checkbox) => {
        if (checkbox.value === genreValue) {
            checkbox.checked = true;
        }
        checkbox.addEventListener("change", () => {
            genreCheckboxes.forEach((cb) => {
                if (cb !== checkbox) {
                    cb.checked = false;
                }
                else if(checkbox) {
                    genreValue = checkbox.value;
                    console.log(genreValue);
                    getMovies(searchValue,yearValue,genreValue,1);
                }
            });
        });
    });


});

formEl.addEventListener("submit", (e) => {
    e.preventDefault();
    searchPoint();
});

document.addEventListener("DOMContentLoaded", () => {
    const container = document.querySelector(".wrapper-itemcontainer"); 
    const loadMoreButton = document.querySelector(".load-more"); 
    let currentPage = 1;
    const itemsPerPage = 5;

 
    function renderData(items) { 
        // items.forEach((item) => {
        //     const div = document.createElement("div"); 
        //     div.className = "data-item";
        //     // div.textContent = item; 
        //     container.appendChild(div);
        // });
        console.log (items)
    }

    
    const MOVIE_ID = "tt3896198";
    const API_KEY = "2bf32dbe";

    async function fetchData(page) { 
        try {
            const response = await fetch(`http://www.omdbapi.com/?s=movie_title&apikey=${API_KEY}&page=${page}`);
            if (!response.ok) {
                throw new Error('네트워크 응답이 좋지 않습니다.');
            }
            const data = await response.json();  
            return data.items; 
        } catch (error) { 
            console.error('데이터를 가져오는 중 오류 발생:', error);
            return [];
        }
    }

    // "Load More" 
    loadMoreButton.addEventListener("click", async () => {
        console.log('test')
        const itemsToDisplay = await fetch(`http://www.omdbapi.com/?s=movie_title&apikey=${API_KEY}&page=1`);
        if (itemsToDisplay.length > 0) {
            renderData(itemsToDisplay);
            currentPage++;
        }
        console.log(itemsToDisplay + "dfasd") 


        if (itemsToDisplay.length < itemsPerPage) {
            loadMoreButton.classList.add("hide");
        }
    });


    async function init() {
        const initialItems = await fetch(`http://www.omdbapi.com/?s=movie_title&apikey=${API_KEY}&page=1`); 
        renderData(initialItems); 
        currentPage++; 

        
        if (initialItems.length < itemsPerPage) { 
            loadMoreButton.classList.add("hide");
        }
    }

    init(); 
});

I used a placeholder API key in the code.
I want the button to load more results when clicked.
Also, I want to hide the button when there are no more results.

How can I push to an array inside an object that is returned by a function?

I am trying to access and alter an array that is within an object that is being returned by a function. I built two mock arrays within objects (The first on its own, the second inside a function.) The first allows me to alter it but the second does not despite them being similar. I want to make the second work, without assigning the function to a variable, but cannot figure out how.

arr = {
  hed : "rush",
  gup : [1,2,3,4],
  tee : "shirt"
      }
arr.gup.push("donkey")
console.log(arr.gup)

function stuff() {
  return {
    one : "tree",
    two : "apple",
    three : 45,
    four : "red",
    five : ["blue", "cat", "train"],
  }
}
stuff().five.push("honey")
console.log(stuff().five)

ESP32 Webserver doesn’t run Javascript file in HTML script tag

I am trying to use a pressure sensor on an ESP32 and then plot a live updating graph. The code I used worked perfectly when using my home network but when making the switch to creating my own network and then sending the data it fails.

Changes to the HTML files are reflected after using LittleFS to upload the data and the Javascript file runs when running the HTML file independently, but when running it through the ESP32 there is nothing. I have attached the .ino,.html and the .js files.

I can even see live data sent to the html when i go the the IP address/readings as coded. It’s just the js file that doesn’t run

#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <LittleFS.h>
#include <Arduino_JSON.h>

#define ZERO_SAMPLES 50
#define COUNTS_PER_PSI 735990  // Increased to further scale down PSI values
#define PSI_TO_CMH2O 70.307    // Conversion factor from PSI to cmH2O
#define DRIFT_THRESHOLD 0.1    // PSI threshold to consider as "no pressure"
#define STABLE_TIME 3000       // Time in ms that readings need to be stable for re-zeroing
#define DRIFT_SAMPLES 10 
// Replace with your network credentials
const char* ssid = "ESP32";
const char* password = NULL;
long  zeroOffset = 8290303;
bool isCalibrated = false;
int sampleCount = 0;
long calibrationSum = 0;
// Drift compensation variables
unsigned long stableStartTime = 0;
bool isStable = false;
float lastPSI = 0;
int stableSampleCount = 0;
const int inputpin = 15;
const int outputpin = 2;
char pressuredata[40];
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

// Create an Event Source on /events
AsyncEventSource events("/events");

// Json Variable to Hold Sensor Readings
JSONVar readings;

// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 750;

// GPIO where the DS18B20 sensors are connected to

// Setup a oneWire instance to communicate with OneWire devices (DS18B20)

// Pass our oneWire reference to Dallas Temperature sensor


// Initialize LittleFS
void initLittleFS() {
  if (!LittleFS.begin()) {
    Serial.println("An error has occurred while mounting LittleFS");
  }
  else{
    Serial.println("LittleFS mounted successfully");
  }
}

// Initialize WiFi
/* void initWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("Connecting to WiFi ..");
  //Serial.println(cmH20)
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.println(WiFi.localIP());
} */
void checkAndUpdateZero(long rawPressure, float currentPSI) {
  // Check if current pressure is close to zero
  if (abs(currentPSI - 1) < DRIFT_THRESHOLD) {  // Remember we're applying -1 offset to PSI
    if (!isStable) {
      // Start tracking stable period
      isStable = true;
      stableStartTime = millis();
      stableSampleCount = 1;
    } else {
      stableSampleCount++;
      
      // Check if we've been stable long enough and have enough samples
      if (stableSampleCount >= DRIFT_SAMPLES && 
          (millis() - stableStartTime) >= STABLE_TIME) {
        // Update zero offset
        zeroOffset = rawPressure;
        stableSampleCount = 0;
        isStable = false;
      }
    }
  } else {
    // Reset stable tracking if pressure is not near zero
    isStable = false;
    stableSampleCount = 0;
  }
}
float convertToPSI(long rawValue, long zero) {
  return (float)(rawValue - zero) / COUNTS_PER_PSI;
}

String readPressureRaw() {
  
  while (digitalRead(inputpin)) {}

  long result = 0;
  noInterrupts();
  
  for (int i = 0; i < 24; i++) {
    digitalWrite(outputpin, HIGH);
    digitalWrite(outputpin, LOW);
    result = (result << 1);
    if (digitalRead(inputpin)) {
      result++;
    }
  }
  
  for (char i = 0; i < 3; i++) {
    digitalWrite(outputpin, HIGH);
    digitalWrite(outputpin, LOW);  }
  
  interrupts();

  long pressure = result ^ 0x800000;
  if (!isCalibrated){
    calibrationSum += pressure;
    sampleCount++;
    readings["sensor1"] = String(0,3);
    if (sampleCount >= 15){
      long zeroOffset = calibrationSum/15;
      isCalibrated = true;
    }
  } else {
    float psi = convertToPSI(pressure , zeroOffset);
    float cmH20 = psi * 70.307;
    checkAndUpdateZero(pressure,psi);
    String pressuredata = String(cmH20,3);
    readings["sensor1"] = pressuredata;
  }
  String jsonresult = JSON.stringify(readings);
  return jsonresult;
  //Serial.println(zeroOffset);
  
  
 
}
  
void setup() {
  pinMode(inputpin,INPUT);
  pinMode(outputpin, OUTPUT);
  // Serial port for debugging purposes
  Serial.begin(115200);
  //initWiFi();
  Serial.println();
  
  // Setting the ESP as an access point
  Serial.print("Setting AP (Access Point)…");
  // Remove the password parameter, if you want the AP (Access Point) to be open
  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);
  initLittleFS();
  digitalWrite(outputpin, LOW);
  for(int i = 0; i < 10; i++) {
    digitalWrite(outputpin, HIGH);

    digitalWrite(outputpin, LOW);
  }
  // Web Server Root URL
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(LittleFS, "/index.html", "text/html");
  });

  server.serveStatic("/", LittleFS, "/");

  // Request for the latest sensor readings
  server.on("/readings", HTTP_GET, [](AsyncWebServerRequest *request){
    String json = readPressureRaw();
    request->send(200, "application/json", json);
    json = String();
  });

  events.onConnect([](AsyncEventSourceClient *client){
    if(client->lastId()){
      Serial.printf("Client reconnected! Last message ID that it got is: %un", client->lastId());
    }
    // send event with message "hello!", id current millis
    // and set reconnect delay to 1 second
    client->send("hello!", NULL, millis(), 10000);
  });
  server.addHandler(&events);

  // Start server
  server.begin();

  
}

void loop() {
  
  if ((millis() - lastTime) > timerDelay) {
    // Send Events to the client with the Sensor Readings Every 10 seconds
    events.send("ping",NULL,millis());
    
    events.send(readPressureRaw().c_str(),"new_readings" ,millis());
    lastTime = millis();
  }
}
<!DOCTYPE html>
<html>
  <head>
    <title>DASHBOARD</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="image/png" href="favicon.png">
    <link rel="stylesheet" type="text/css" href="style.css">
    <script src="https://code.highcharts.com/highcharts.js"></script> 
  </head>
  <body>
    <div class="topnav">
      <h1 id="header"> Pressure Waveform and Control Data</h1>
    </div>
    <div class="content">
      <div class="card-grid">
        <div class="card">
          <p id = "id1" class="card-title">Pressure Chart</p>
          <div id="chart-pressure" class="chart-container"></div>
        </div>
      </div>
    </div>
    <script type="text/javascript" src="script.js"></script> 
  </body>
</html>

window.addEventListener('load', getReadings);

var chartT = new Highcharts.Chart({
  chart:{
    renderTo:'chart-pressure'
  },
  series: [
    {
      name: 'Pressure #21',
      type: 'line',
      color: '#101D42',
    },
  ],
  title: {
    text: undefined
  },
  xAxis: {
    type: 'datetime',
    dateTimeLabelFormats: { second: '%H:%M:%S' }
  },
  yAxis: {
    title: {
      text: 'Pressure '
    }
  },
  credits: {
    enabled: false
  }
});


function plotPressure(jsonValue) {

  var keys = Object.keys(jsonValue);
  var x = (new Date()).getTime();
  const key = keys[0];
  var y = Number(jsonValue[key]);
  if(chartT.series[0].data.length > 40) {
    
    chartT.series[0].addPoint([x, y], true, true, true);
  } else {
    chartT.series[0].addPoint([x, y], true, false, true);
  }

}


function getReadings(){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      var myObj = JSON.parse(this.responseText);
      console.log(myObj);
      plotPressure(myObj);
    }
  };
  xhr.open("GET", "/readings", true);
  xhr.send();
}

if (!!window.EventSource) {
  var source = new EventSource('/events');

  source.addEventListener('open', function(e) {
    console.log("Events Connected");
  }, false);

  source.addEventListener('error', function(e) {
    if (e.target.readyState != EventSource.OPEN) {
      console.log("Events Disconnected");
    }
  }, false);

  source.addEventListener('message', function(e) {
    console.log("message", e.data);
  }, false);

  source.addEventListener('new_readings', function(e) {
    console.log("new_readings", e.data);
    var myObj = JSON.parse(e.data);
    plotPressure(myObj);
  }, false);
}

Expected graph here. Like this

CryptoJS problem decrypting an encrypted file download chunked stream

I have a sample client-side HTML webpage that allows a user to upload a file to a NodeJS file storage server. When a user uploads a file from the webpage, the client’s browser encrypts the file with a password before sending it to the server. The user can then download the file from that webpage by inputting the uploaded filename and the password – the browser downloads and decrypts the file. This is done using streams and CryptoJS so I can upload and download large files. (I had success using strings before, but it evidently does not work with large files).

I’ve managed to get the encryption process working: I’m able to upload a file to the server that the client’s browser encrypts – I can see the uploaded file on the server. However, I’m having trouble decrypting and downloading the file when it is being downloaded. The downloaded file always shows up with a size of 0 bytes every time with no data.

I’ve verified that the encrypted file blob size in bytes was received correctly by the client when downloading. The salt and IV are received as well. However, it appears that the value variable is always undefined when setting it to await reader.read(); – “No Value Detected” is logged. At this point, I’m not quite sure what the problem is as no errors are thrown.

I attached a small reproduceable sample below.

Browser Client Code (HTML):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File Upload & Download</title>
</head>
<body>
<h1>Upload and Download Large Files</h1>

<h2>Upload File</h2>
<input type="file" id="fileInput">
<button id="uploadButton">Upload</button>
<div id="uploadStatus"></div>

<h2>Download File</h2>
<input type="text" id="downloadFilename" placeholder="Enter file name to download">
<button id="downloadButton">Download</button>

<script src="app.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

</body>
</html>

Code for client app.js:

// Utility: Derive AES Key from Password
async function deriveKey(password, salt) {
    const enc = new TextEncoder();
    const keyMaterial = await window.crypto.subtle.importKey(
        'raw',
        enc.encode(password),
        'PBKDF2',
        false,
        ['deriveKey']
    );

    return window.crypto.subtle.deriveKey(
        {
            name: 'PBKDF2',
            salt: salt,
            iterations: 100000,
            hash: 'SHA-256',
        },
        keyMaterial,
        { name: 'AES-CBC', length: 256 },
        false,
        ['encrypt', 'decrypt']
    );
}

// Utility: Generate Random Initialization Vector (IV)
function generateIV() {
    return crypto.getRandomValues(new Uint8Array(16)); // 16 bytes for AES-CBC
}

// Encrypt File in Chunks
async function encryptFile(file, password) {
    const chunkSize = 64 * 1024; // 64 KB
    const reader = file.stream().getReader();
    const enc = new TextEncoder();

    // Generate salt and IV
    const salt = crypto.getRandomValues(new Uint8Array(16));
    const iv = generateIV();

    // Derive AES key
    const key = await deriveKey(password, salt);

    // Create a Blob for the encrypted output
    const encryptedChunks = [];
    encryptedChunks.push(salt); // Store salt in the output
    encryptedChunks.push(iv);   // Store IV in the output

    let done = false;

    while (!done) {
        const { value, done: isDone } = await reader.read();
        if (value) {
            const encryptedChunk = await crypto.subtle.encrypt(
                { name: 'AES-CBC', iv: iv },
                key,
                value
            );
            encryptedChunks.push(new Uint8Array(encryptedChunk));
        }
        done = isDone;
    }

    return new Blob(encryptedChunks, { type: 'application/octet-stream' });
}

async function decryptFile(encryptedBlob, password) {
    // Check there is a blob to begin with
    if (!encryptedBlob) {
        throw new Error('No encrypted file provided.');
    } else {
        console.log('Encrypted Blob size:', encryptedBlob.size);
    }

    const reader = encryptedBlob.stream().getReader();

    // Read the first 32 bytes: 16 for salt, 16 for IV
    const { value: header } = await reader.read();
    if (!header) {
        throw new Error('Failed to read the file header.');
    }
    const salt = header.slice(0, 16); // First 16 bytes are salt
    const iv = header.slice(16, 32); // Next 16 bytes are IV

    console.log(`Salt:`, salt);
    console.log(`IV:`, iv);

    // Derive AES key
    const key = await deriveKey(password, salt);

    console.log(`Key: ${key}`);

    const decryptedChunks = [];
    let done = false;

    // Start reading chunks
    while (!done) {
        const { value, done: isDone } = await reader.read();
        done = isDone;

        if (value) {
            console.log("Value detected!");
            try {
                // Decrypt each chunk
                const decryptedChunk = await crypto.subtle.decrypt(
                    { name: 'AES-CBC', iv },
                    key,
                    value.buffer
                );
                decryptedChunks.push(new Uint8Array(decryptedChunk));
            } catch (error) {
                throw new Error('Decryption failed. Check the password or file integrity.');
            }
        } else {
            console.warn('No value detected!');
        }
    }

    // Combine all decrypted chunks into a single Blob
    return new Blob(decryptedChunks, { type: 'application/octet-stream' });
}


document.getElementById('uploadButton').addEventListener('click', async () => {
    const fileInput = document.getElementById('fileInput');
    const uploadStatus = document.getElementById('uploadStatus');
    const password = prompt('Enter a password to encrypt the file:');

    if (!fileInput.files.length || !password) {
        uploadStatus.textContent = 'Please select a file and enter a password.';
        return;
    }

    const file = fileInput.files[0];
    uploadStatus.textContent = 'Encrypting file...';

    try {
        const encryptedFile = await encryptFile(file, password);

        const formData = new FormData();
        formData.append('file', encryptedFile, `${file.name}.enc`);

        const response = await fetch('/upload', {
            method: 'POST',
            body: formData,
        });

        if (response.ok) {
            uploadStatus.textContent = 'File uploaded successfully!';
        } else {
            uploadStatus.textContent = 'File upload failed.';
        }
    } catch (err) {
        console.error('Error encrypting file:', err);
        uploadStatus.textContent = 'Encryption failed.';
    }
});

document.getElementById('downloadButton').addEventListener('click', async () => {
    const filename = document.getElementById('downloadFilename').value;
    const password = prompt('Enter the password to decrypt the file:');

    if (!filename || !password) {
        alert('Please enter the filename and password.');
        return;
    }

    const response = await fetch(`/download/${filename}.enc`);

    if (response.ok) {
        const encryptedBlob = await response.blob();

        try {
            const decryptedBlob = await decryptFile(encryptedBlob, password);

            // Trigger download of the decrypted file
            const a = document.createElement('a');
            const url = URL.createObjectURL(decryptedBlob);
            a.href = url;
            a.download = filename.replace('.enc', '');
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);

            alert('File decrypted and downloaded successfully!');
        } catch (err) {
            alert(err);
        }
    } else {
        alert('Failed to download the file.');
    }
});

Node.JS Server Code (should not do cryptography; only stores encrypted data):

const express = require('express');
const fs = require('fs');
const multer = require('multer');
const path = require('path');

const app = express();
const PORT = 3000;

// Configure multer for file uploads
const upload = multer({
    dest: 'uploads/' // Directory to store uploaded files
});

// Serve static files for the client-side HTML/JS
app.use(express.static(path.join(__dirname, 'public')));

// Endpoint to upload a file
app.post('/upload', upload.single('file'), (req, res) => {
    const tempPath = req.file.path;
    const targetPath = path.join(__dirname, 'uploads', req.file.originalname);

    // Move the file to a permanent location
    const readStream = fs.createReadStream(tempPath);
    const writeStream = fs.createWriteStream(targetPath);

    readStream.on('error', (err) => {
        console.error('Error reading file:', err);
        res.status(500).send('File upload failed.');
    });

    writeStream.on('error', (err) => {
        console.error('Error writing file:', err);
        res.status(500).send('File upload failed.');
    });

    writeStream.on('finish', () => {
        fs.unlink(tempPath, (err) => {
            if (err) console.error('Failed to delete temp file:', err);
        });
        res.status(200).send('File uploaded successfully!');
    });

    readStream.pipe(writeStream);
});

// Endpoint to download a file
app.get('/download/:filename', (req, res) => {
    const filePath = path.join(__dirname, 'uploads', req.params.filename);

    if (!fs.existsSync(filePath)) {
        return res.status(404).send('File not found');
    }

    const readStream = fs.createReadStream(filePath);
    res.setHeader('Content-Disposition', `attachment; filename="${req.params.filename}"`);
    res.setHeader('Content-Type', 'application/octet-stream');

    readStream.on('error', (err) => {
        console.error('Error reading file:', err);
        res.status(500).send('File download failed.');
    });

    readStream.pipe(res);
});

// Start the server
app.listen(PORT, () => {
    console.log(`Server is running at http://localhost:${PORT}`);
});

Can anyone help me understand what I’m doing wrong?

how to config stylelint in vue project?

I am trying to config stylelint for my vue project (here we can only consider the latest version)

At first, I want to use:

extends: ['stylelint-config-recommended','stylelint-config-recommended-scss', 'stylelint-config-recommended-less','stylelint-prettier/recommended']

However, GPT -4 seems to say that there may be some conflicts. So I change to
below stylelint.config.cjs:

/** @type {import('stylelint').Config} */
module.exports = {
    defaultSeverity: 'error',
    extends: ['stylelint-config-recommended', 'stylelint-prettier/recommended'],
    overrides: [
        {
            files: ['**/*.vue'],
            extends: ['stylelint-config-recommended-vue'],
            customSyntax: 'postcss-html',
            rules: {
                // Vue 
            },
        },
        {
            files: ['**/*.scss'],
            extends: ['stylelint-config-recommended-scss'],
            rules: {
                // SCSS 
            },
        },
        {
            files: ['**/*.less'],
            extends: ['stylelint-config-recommended-less'],
            rules: {
                // Less 
            },
        },
    ],
    rules: {
        'no-empty-source': null,
        'no-descending-specificity': null,
        'selector-pseudo-class-no-unknown': [
            true,
            {
                ignorePseudoClasses: ['deep', 'global'],
            },
        ],
    },
};

But I still have some issues: will a vue sfc file with scss style obey the same style rule as it is in a single .scss file?

I understand the vue sfc file will be parsed into several parts and the style part will be treated as a .scss file?

Please help me! It’s hard to check or test if the config is right or wrong. I would appreciate it if you could provide best practices!

Duplicate console.log() sometimes shows number of times it was printed

I’m following a tutorial to learn React.
The full source code can be found here.

I have one instance of useEffect which is used to print to the console:

  useEffect(() => {
    console.log('render');
  })

My app has two text inputs and a button which adds a <li> to a <ul>.

When I type in either of the two inputs, the console.log() shows the number of times it was printed in the console tab.

However, when I click a button which adds the <li>, it shows a new log in the console window with the same text.

Why does the console not just increment the count of that log?

Here’s a screenshot showing what I mean:

I typed in either textbox 6 times to get the 6 ‘render’ logs, then I clicked the button to add the item to the list:

Shows a count of 6 'render' logs followed by one 'render' log

java script : rowcount = x why ${rowcount + 1} alway show 1

I want to pass value by name c_lastname31_2 c_lastname31_3 c_lastname31_4 but it always c_lastname31_1

function addRow() {
        const tableBody = document.querySelector("table tbody");

        // จำกัดจำนวนแถวไม่เกิน 20
        if (rowcount >= 20) {
            alert("คุณไม่สามารถเพิ่มแถวได้เกิน 20 แถว");
            return;
        }

        // เพิ่มแถวใหม่
        const newRow = tableBody.insertRow();

        // เพิ่มเซลล์และเนื้อหาในแต่ละเซลล์
        const newCellIndex = newRow.insertCell(0);
        newCellIndex.textContent = ${rowcount + 1}; // หมายเลขแถว

        newRow.insertCell(1).innerHTML = `<input type="text" name="c_lastname31_${rowcount + 1}" maxlength="200" />`;
        newRow.insertCell(2).innerHTML = `<input type="checkbox" name="f_DesignatedPersonsY31_${rowcount + 1}" value="Y" />`;
        newRow.insertCell(3).innerHTML = `<input type="checkbox" name="f_DesignatedPersonsN31_${rowcount + 1}" value="Y" />`;
        newRow.insertCell(4).innerHTML = `<input type="checkbox" name="f_BasicOffenceY31_${rowcount + 1}" value="Y" />`;
        newRow.insertCell(5).innerHTML = `<input type="checkbox" name="f_BasicOffenceN31_${rowcount + 1}" value="Y" />`;

        // ปุ่มลบ
        newRow.insertCell(6).innerHTML = `<button type="button" onclick="removeRow(this)">ลบ</button>`;

        // เพิ่มค่า rowcount
        rowcount++;
        localStorage.setItem('rowcount', rowcount);
    }

How do I splitTextToColumns only for cells containing commas in Google Apps Script?

I am super new to Google Apps Script and I’ve run into a roadblock. Essentially, I have a form on my website that automatically populates names and addresses into a Google Sheet, and the entire address is entered into one cell where the street, city + state, zip code, and country are all separated by line breaks.

Ultimately I want to split the address data into individual columns (Street, City, State, Zip Code, Country) but ONLY for the cells that contain the line breaks. As new data is populated from the website form to the Google Sheet on a regular basis, the goal is for the script to skip over the already separated rows of data and just separate the data for the new entries at the bottom of the sheet.

Here’s my current function:

function splitColumnV1() {

var ss = SpreadsheetApp.getActiveSpreadsheet();

  var lastRowComma = ss.getLastRow();
  var commaRange = ss.getRange('B2:B' + lastRowComma);      // range of the data containing cells I want to split
  
  const searchText = 'n';
  const replaceText = ', ';

  commaRange                     // with the range, find all line breaks and replace with commas
  .createTextFinder(searchText)
  .replaceAllWith(replaceText); 

for (var j = 0; j < lastRowComma; j++) {                      // for each cell value
  if (j.getValues.createTextFinder(', ') != null) // currently getting the error here
   {
  j.splitTextToColumns(', ');     // if there are line breaks then split the text to columns
  }
  elseif (j.getValues.createTextFinder(', ') != null)
    {
  continue;            // if there are no commas in the cell then skip to the next cell
  }
}
}

Currently my code works up until “for, if” section, but then I get the error code: “TypeError: Cannot read properties of undefined (reading ‘createTextFinder’)”

If I remove the whole “for, if” section and replace it with just the line commaRange.splitTextToColumns(', '); then it sort of works, but it replaces the already separated data with blank cells. Any help would be super appreciated!

PDF.js webpack promise never fulfilled

I’m trying to run a very simple PDF viewer using the PDF.js (pdfjs-dist) module. I’m importing the webpack from npm. The javascript looks like this.

import * as pdfjsLib from "pdfjs-dist/webpack";

I’m using the latest PDFjs build (4.10.38) and following instructions from their readme: https://github.com/mozilla/pdf.js/tree/master/examples/webpack

I run this line from the console

pdfjsLib.getDocument( "https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf" ).promise.then( function ( doc ) { 
 console.log( doc ); 
}, function ( error ) { 
 console.log( error ); 
});

it returns a Promise{<pending>} that never resolves.

I’ve added .mjs to the end of the import line, but no changes.

I’ve included the pdfjsLib.getDocument(… in the js, but it never writes to the console since the Promise is never resolved.

TypeScript Interface Type for Array [duplicate]

I tried Googling for this, but I’m not sure if I’m not using the right terminology or just not looking for the right thing, but I am trying to figure something out here with TypeScript / React.

So I have this one component which sends in an array as a prop, and in that area is either a direct string, or a JSX Element containing a string, and that array is supposed to render the string data in another component. The code will probably explain better:

// my-directory/home.tsx

import { Link } from "react-router";
import Content from "my-directory/content.tsx";

export default function Home() {
  const mainContent = () => {
    const stringOne = `A regular string with no special anythings.`;
    const stringTwo = (
      <>
        A string that is inside JSX tags, to be able to use a <Link to="/">link to a page</Link>
      </>
    );

    return [stringOne, stringTwo];
  };

  return <Content mainContent={mainContent()} />;
}
// my-directory/content.tsx

interface Props {
  mainContent: Array<any> // this is where I want to correct this, as I know this is not ideal
}

export default function Content({ mainContent }: Props) {
  return (
    <div>
      {mainContent.map((content: string, index: string) =>
        <div key={index}>{content}</div>
      )}
    </div>
  );
}

I’m not very high-level with TypeScript, so I’m not sure how to pass in the proper type for mainContent inside the interface Props in the Content component.

Hoping this is all understandable, and thanks for any guidance, or pointing me in the right direction…!