OpenLayers GeoTIFF Color Mapping Issue – All Data Shows as Single Color

I’m trying to apply color mapping to a GeoTIFF layer in OpenLayers 9.2.4, but I’m encountering an issue where the entire GeoTIFF is displayed as a single color instead of applying my color ranges properly.

Issue Description

I have a GeoTIFF file with raster data values that should be mapped to different colors based on value ranges. I’ve created a color mapping array and applied it using WebGLTile styling, but the visualization doesn’t match my color legend.

Expected Behavior

Different areas of the GeoTIFF should display different colors based on pixel values
The colors should match the ranges defined in my colorMappings array
Actual Behavior
The entire GeoTIFF is rendered with a single color
The color mapping doesn’t seem to be applied correctly

Here’s the relevant part of my code:

// Color mapping rules
const colorMappings = [
  { min: 0, max: 2, color: [0, 97, 0] },
  { min: 2, max: 4, color: [50, 128, 27] },
  // ... more ranges ...
];

// GeoTIFF source
const source = new ol.source.GeoTIFF({
  sources: [{ url: './test.tif' }],
  convertToRGB: false
});

// Color expression for styling
const colorExpression = [
  'case',
  ...colorMappings.flatMap((mapping) => [
    ['all', 
     ['>=', ['band', 1], mapping.min], 
     ['<', ['band', 1], mapping.max]
    ],
    ['color', ...mapping.color, 255]
  ]),
  ['color', 0, 0, 0, 0]
];

// WebGL tile layer with styling
const tiffLayer = new ol.layer.WebGLTile({
  source: source,
  style: { color: colorExpression }
});

What I Suspect

I suspect the issue might be related to the band index in the color expression. I’m currently using [‘band’, 1] to reference the data values, but I’m not sure if this is correct for my GeoTIFF file.

Possible issues:

  • OpenLayers band indexing might be 0-based instead of 1-based
  • My GeoTIFF might have multiple bands and I’m referencing the wrong one
  • The data values in my GeoTIFF might be outside the ranges I’ve defined
  • There might be a problem with how WebGLTile applies styling to GeoTIFF data

Questions

1、How can I determine which band index I should be using?
Is there a way to debug what values are actually in my GeoTIFF?
2、Are there any common issues with WebGLTile styling for GeoTIFF that I should be aware of?
3、Should I be configuring the source or style differently?
4、Any assistance would be greatly appreciated!

NOW_STATUS

How to make my API call not give me a string as an error response but the error’s body instead? [duplicate]

I have a problem with the management of an error for my API call in my Angular app:

sendRequest(request: BookingRequest): Observable<any>{
const authorityCode = this.tableService.enteId;
const baseUrl = this.getCarBookingBaseUrl(authorityCode);
 const url = `${baseUrl}/api/Booking`;
 const body = JSON.stringify(request);
return this.http.post<any>(url, body, { headers: this.buildBasicAuthHeaders() }).pipe(
  map(_ => _.bookingId || 'Number not found'),
  catchError(error => {
    const errorMessage = error?.error?.message || 'Unknown error';
    return throwError(() => new Error(`Error while sending request: ${errorMessage}`));
  })
);}

This is my call which works if there are no errors. However, in case I get an error 406, in the Chrome’s console I receive this in the response of the 406 error call:

{"message":"Invalid contract"}

This is what I want to receive when I subscribe to this function. In case I get error 406, I need to show this message on screen.
Problem is that error in the catchError is always like this:

"Http failure response for https:INSERT_URL_HERE: 406 OK"

How can I manage the JSON that the error sends back to me with the message I need to show?

Data fetching with pagination on nextui-org/react Autocomplete form input

I have an issue related to the Autocomplete component in nextui-org/react. I am trying to implement a form autocomplete input, which loads multiple languages by making a paginated requests to the server. I am kind of new to React and I am struggling with these features:

  • When the user scrolls to the bottom of the list, a request with the next page should be triggered, in order to fetch the next page of data.
  • When the user types on the input form, a search should be made to the existing data (the data that is already received in the frontend). If the match is not found there, then a request should be made to the server.
  • How to implement a debounce feature, so that the search is not applied every time I press a key.

Has anyone worked with this implementation before? If so, could you provide me some ideas?

I tried creating a Context which would wrap my form input. Each time I scrolled, I would fetch the next page, but the next page would replace my already existing data.

How to upload an image using Inertia.js & Laravel

I try to upload an image using Inertia.js and React with Laravel.

In my react component I have:

    const { data, setData, post, processing, errors } = useForm({
        img: null,    
    });

    const submit = (e) => {
        e.preventDefault();
        console.log(data.img, data.img instanceof File) // File, true
        post(route('admin.templates.store'), {
            forceFormData: true,
        })
    }

and jsx

<form onSubmit={submit} className="max-w-2xl mx-auto">
<div className="mb-4 w-full">
  <label htmlFor="image" className="label">* Image</label>
    <input 
      type="file" 
      name="img" 
      id="image" 
      accept="image/*" 
      required 
      className="input-b"
      onChange={e => setData('img', e.target.files[0])}
     />
</div>
</form>

In the Laravel store method the has_file is always false and the img filed is an empty array.
The store method is a POST.

public function store(Request $request) {
        dd([
            'has_file' => $request->hasFile('img'),
            'file' => $request->file('img'),
            'all' => $request->all(),
        ]);
    } 

Any suggestions? Thanks.

Google Apps Script SyntaxError: Identifier ‘firstDataRow’ declared on save

I’m working on a Google Apps Script to synchronize events from my Google Calendar to a Google Spreadsheet. The script is designed to:

  • Fetch events for specific monthly tabs in my spreadsheet (e.g., “SEPTEMBER – FY26 EDGE Stadium – Planning Events”).
  • Parse details like event name, attendees, ticket number, and location from the event description.
  • Combine new events with existing data on the sheet and sort them chronologically.
  • Place a “Last Sync” timestamp on a dedicated “Sync Log” sheet.
  • Critically, it’s configured to handle multiple header rows (4 rows) and specific data validation rules for meeting rooms.

I am consistently encountering a SyntaxError that prevents me from even saving the script. The error message is:
Syntax error: SyntaxError: Identifier 'firstDataRow' has already been declared line: 290 file: Untitled.gs

Key details about the problem:

  • Error occurs on saving: The script cannot be saved or run due to this syntax error.
  • Specific line: The error points to let firstDataRow = HEADER_ROWS_TO_SKIP + 1;
  • Variable scope: I understand that “Identifier has already been declared” usually means a variable is declared twice. However, firstDataRow is intended to be declared once per sheet iteration and used correctly thereafter. The code includes checks and structuring to avoid this.

Troubleshooting steps I’ve already tried:

  1. Created a brand new Apps Script project and deleted all default code.
  2. Copied and pasted the entire script (provided below) carefully, ensuring no lines were missed or extra characters included.
  3. Attempted saving in different web browsers.
  4. Cleared my browser’s cache and cookies.
  5. Confirmed my Google Calendar ID and Spreadsheet ID are correct.
  6. Confirmed the sheet naming convention is correct and the script sees all relevant sheets.
  7. Confirmed HEADER_ROWS_TO_SKIP is correctly set to 4 for my sheet’s structure (data starts on Row 5).
  8. The spreadsheet has data validation rules on certain columns (e.g., Column X and Y are manual inputs with dropdowns; the “Meeting Room” column also has dropdowns). The script has been updated to exclude manual columns from writes and to correctly parse meeting room names.

My question is:
Why would this specific SyntaxError (Identifier ‘firstDataRow’ has already been declared) occur upon saving the script, given the variable scoping appears correct, and what could be unique to my Apps Script environment that causes this? Is there a subtle corruption or state issue in the Apps Script editor itself that prevents proper compilation/saving of this code?


const now = new Date();
// --- UPDATED DATE RANGE LOGIC ---
// Set start date to September 1st of the current year
const startOfYear = new Date(now.getFullYear(), 8, 1); // Month is 0-indexed, so 8 is September

// If the current date is already past September 1st, start from 'now'. Otherwise, start from September 1st.
const startDate = (now > startOfYear) ? now : startOfYear;

// Set the end date to one year from the calculated start date
const futureDate = new Date(startDate);
futureDate.setFullYear(startDate.getFullYear() + 1);

const allEvents = calendar.getEvents(startDate, futureDate);
// --- END UPDATED DATE RANGE LOGIC ---

// --- NEW DEBUG LOG: Log ALL Sheet Names Found in the Spreadsheet ---
Logger.log('--- All Sheet Names Found in the Spreadsheet ---');
sheets.forEach(sheet => {
    Logger.log(`  Sheet Name: "${sheet.getName()}"`);
});
Logger.log('------------------------------------------------');
// --- END NEW DEBUG LOG ---

// --- DEBUG LOG: Check if your November event is even retrieved from the calendar ---
Logger.log('--- All Events Retrieved from Calendar (Title, Date, and Month Index) ---');
allEvents.forEach(event => {
    Logger.log(`  ${event.getTitle()} on ${event.getStartTime().toDateString()} (Month Index: ${event.getStartTime().getMonth()})`);
});
Logger.log('----------------------------------------------------------');
// --- END DEBUG LOG ---


sheets.forEach(sheet => {
  // Log for all sheets to debug if NOVEMBER tab is being skipped
  Logger.log(`Checking sheet: "${sheet.getName()}"`); 
  if (!monthTabPattern.test(sheet.getName())) {
    Logger.log(`Skipping sheet (name mismatch): "${sheet.getName()}"`); 
    return; 
  }

  const sheetMonthName = sheet.getName().split(" ")[0].toUpperCase();
  Logger.log(`Processing sheet: "${sheet.getName()}" (Sheet Month Name: ${sheetMonthName})`);


  // --- CRITICAL FIX FOR READING EXISTING TICKETS ON EMPTY SHEETS ---
  let existingTickets = new Set(); // Initialize as empty Set

  let lastRowWithContent = sheet.getLastRow(); // Get the last row with any content
  let firstDataRow = HEADER_ROWS_TO_SKIP + 1; // This is the first row where actual data should be (e.g., Row 5)

  // Only attempt to read existing tickets if there are actual data rows in the sheet
  if (lastRowWithContent >= firstDataRow) {
      const numRowsToRead = lastRowWithContent - firstDataRow + 1; // Calculate number of rows to read
      // Read existing tickets from the Ticket Number column
      const ticketsData = sheet.getRange(firstDataRow, COLUMN_INDICES['Ticket Number'] + 1, numRowsToRead, 1).getValues();
      ticketsData.flat().filter(Boolean).forEach(ticket => existingTickets.add(ticket));
  }
  // --- END CRITICAL FIX ---


  const eventsForMonth = allEvents.filter(e => {
      const eventMonthName = Utilities.formatDate(e.getStartTime(), "CET", "MMMM").toUpperCase(); // Get full month name
      Logger.log(`  FILTER CHECK: Event '${e.getTitle()}' (Cal Month Name: ${eventMonthName}) vs Sheet '${sheet.getName()}' (Sheet Month Name: ${sheetMonthName}). Match: ${eventMonthName === sheetMonthName}`);
      return eventMonthName === sheetMonthName;
  });

  Logger.log(`Found ${eventsForMonth.length} events for "${sheet.getName()}"`);

  const newRows = [];

  eventsForMonth.forEach(event => {
    const title = event.getTitle();
    const description = event.getDescription() || "";
    const location = event.getLocation() || "";

    Logger.log(`--- Processing Event: ${title} on ${event.getStartTime().toDateString()} ---`);

    const start = event.getStartTime();
    const end = event.getEndTime();

    // Helper to extract specific data from the description using regex
    const extract = (label) => {
      // FIXED REGEX: Ensured the lookahead group is properly terminated.
      const regex = new RegExp(`${label}:\s*(.*?)(?=(?:<br>|<p[^>]*>|<\/p>|<a[^>]*>|<\/a>|\n)|$)`, "i");
      
      const match = description.match(regex);
      const extractedValue = match ? match[1].trim().replace(/<[^>]*>/g, '') : ""; // Strip all HTML tags
      Logger.log(`  Extracted '${label}': '${extractedValue}'`); 
      return extractedValue;
    };

    // --- Data Extraction ---
    let eventNameFromDesc = extract("Name of event");
    const actualEventName = eventNameFromDesc || title; // Use extracted name, fallback to event title

    const rawPax = extract("Number of attendees").replace(/[^0-9]/g, ""); // Extract numbers only
    const pax = rawPax ? `${rawPax} PAX` : ''; // Format as 'XX PAX'
    Logger.log(`  Raw PAX: '${rawPax}', Formatted PAX: '${pax}'`);

    // SF Event Host: Now relies solely on extraction from description
    const sfEventHost = extract("Who the IBP is"); 
    Logger.log(`  SF Event Host: '${sfEventHost}'`);
    
    const ticket = extract("Event number");
    Logger.log(`  Ticket Number: '${ticket}'`);

    // --- Type Column Logic (Column C) ---
    let eventType = '';
    if (title.toUpperCase().includes("SIC")) {
      eventType = "SIC";
    } else {
      const typeMatch = description.match(/Whether it is internal/ external:s*(Internal|External)/i);
      eventType = typeMatch ? typeMatch[1] : ""; // Will be "Internal" or "External" based on description
    }
    Logger.log(`  Event Type (derived): '${eventType}'`);

    // --- Meeting Room Logic (Column F) ---
    let finalRoomName = "";
    const normalizedCalendarLocation = location.toLowerCase(); // For matching keys in LOCATION_MAPPING

    // 1. Check for exact direct matches in the LOCATION_MAPPING (case-insensitive)
    for (const calendarLocMapKey in LOCATION_MAPPING) {
        if (normalizedCalendarLocation.includes(calendarLocMapKey)) {
            finalRoomName = LOCATION_MAPPING[calendarLocMapKey];
            break;
        }
    }

    // 2. If not found in direct mapping, try to match against the dropdown options pattern
    if (!finalRoomName) {
        // Clean up calendar location for regex matching (remove prefixes like "Amsterdam - Edge Stadium-")
        let cleanedLocationForMatch = location.replace(/Amsterdam - Edge Stadium-/, '').replace(/ [Google Meet]/i, '').trim();
        // Also normalize "(XX)" to "(XX pax)" if that's how dropdowns are
        cleanedLocationForMatch = cleanedLocationForMatch.replace(/((d+))$/, '($1 pax)');

        // Escape special characters for regex from dropdown options
        // Handle both '&' and '&amp;' as they might appear.
        const escapedDropdownOptions = DROPDOWN_ROOM_OPTIONS.map(option => 
            option.replace(/[.*+?^${}()|[]\]/g, '\$&') // Escape common regex special chars
                  .replace(/&/g, '(?:&|&amp;)') // Handle both & and &amp;
        );
        
        // This regex tries to find any of the dropdown options anywhere in the cleaned location
        const roomPattern = new RegExp(`(${escapedDropdownOptions.join('|')})`, 'i');

        const match = cleanedLocationForMatch.match(roomPattern);
        if (match && match[1]) {
            finalRoomName = match[1].replace(/&amp;/g, '&'); // Use the captured group and convert &amp; back to &
        } else {
            Logger.log(`  Warning: No regex match found for cleaned location: '${cleanedLocationForMatch}'`);
        }
    }
    Logger.log(`  Final Meeting room name: '${finalRoomName}'`);


    // --- Duplicate Check ---
    Logger.log(`  Checking duplicate: Ticket '${ticket}', exists in sheet: ${existingTickets.has(ticket)}`);
    if (!ticket || existingTickets.has(ticket)) {
        if (!ticket) Logger.log(`Skipping event "${title}" because no ticket number was found.`);
        else Logger.log(`Skipping event "${title}" with ticket ${ticket} because it already exists.`);
        return; // This 'return' skips the event
    }
    Logger.log(`  Event "${title}" passed duplicate check.`);

    // --- Construct Row Data ---
    // Initialize with empty strings for columns A to W (TOTAL_COLUMNS: 23)
    const rowData = new Array(COLUMN_INDICES.TOTAL_COLUMNS).fill(''); 

    rowData[COLUMN_INDICES['Dayporter Assigned']] = ""; // Manual
    rowData[COLUMN_INDICES['Date of event']] = Utilities.formatDate(start, "CET", "dd/MM/yyyy");
    rowData[COLUMN_INDICES['Type']] = eventType;
    rowData[COLUMN_INDICES['Name of Event']] = actualEventName;
    rowData[COLUMN_INDICES['SF Event Host']] = sfEventHost;
    rowData[COLUMN_INDICES['Meeting room']] = finalRoomName; // Use the cleaned and validated room name
    rowData[COLUMN_INDICES['PAX']] = pax;
    rowData[COLUMN_INDICES['Start Time (CET)']] = Utilities.formatDate(start, "CET", "HH:mm");
    rowData[COLUMN_INDICES['Finish Time (CET)']] = Utilities.formatDate(end, "CET", "HH:mm");
    rowData[COLUMN_INDICES['Ticket Number']] = ticket;

    // Populate other fields if data is extractable or has defaults
    // These fields are filled up to Column W (index 22). Columns X and Y are left untouched.
    rowData[COLUMN_INDICES['Slack Channel']] = ""; 
    rowData[COLUMN_INDICES['SIC Guest Registration Done?']] = "";
    rowData[COLUMN_INDICES['Ground Floor Check-In']] = "";
    // Basic check: if 'Catering:' label exists, assume 'Yes', otherwise 'No'.
    rowData[COLUMN_INDICES['Catering YES/NO']] = extract("Catering") ? "Yes" : "No"; 
    rowData[COLUMN_INDICES['Catering What, Caterer & Time Status: request/pending/confirmed']] = extract("Catering"); // Full catering info
    rowData[COLUMN_INDICES['Menu']] = "";
    rowData[COLUMN_INDICES['Furniture Set Up']] = "";
    rowData[COLUMN_INDICES['Comments']] = description; // Full description can go here, or more parsed details
    rowData[COLUMN_INDICES['AV Requirements']] = extract("AV support");
    rowData[COLUMN_INDICES['AV Ticket']] = "";
    rowData[COLUMN_INDICES['Alcohol (SVP Approval) YES/NO']]= "";
    rowData[COLUMN_INDICES['Minors']]= "";
    rowData[COLUMN_INDICES['OOH Event']]= "";
    // 'Extra security requested?': Column X (index 23) - Manual, not managed by script
    // 'VP / C-Level': Column Y (index 24) - Manual, not managed by script

    newRows.push(rowData);
    Logger.log(`  Event "${title}" added to newRows.`); // Log if event is added
  });

  // --- DEBUG LOG: Check newRows.length before the 'if' condition ---
  Logger.log(`DEBUG: newRows.length for "${sheet.getName()}": ${newRows.length}`);
  // --- END NEW DEBUG LOG ---

  // --- CRITICAL LOGIC FIX: Explicitly handle empty newRows array ---
  if (newRows.length === 0) {
      Logger.log(`Skipping write operation for "${sheet.getName()}" because newRows is empty.`);
      // This explicit 'return' prevents the error "The number of rows in the range must be at least 1."
      // when newRows is truly empty for a sheet (e.g., April, July in your logs)
      return; // Exit processing for this sheet if no new rows to add/sort.
  }
  // --- END CRITICAL LOGIC FIX ---


  // This block will now only execute if newRows > 0
  let firstDataRow = HEADER_ROWS_TO_SKIP + 1;
  let lastUsedRowInSheet = sheet.getLastRow();
  
  // Determine the actual range of existing data to read.
  let numExistingDataRows = 0;
  if (lastUsedRowInSheet >= firstDataRow) {
      numExistingDataRows = lastUsedRowInSheet - firstDataRow + 1;
  }

  let allData = [];
  if (numExistingDataRows > 0) {
      // Read existing values within the defined data columns (A to W)
      allData = sheet.getRange(firstDataRow, 1, numExistingDataRows, COLUMN_INDICES.TOTAL_COLUMNS).getValues();
  }

  const combinedData = allData.concat(newRows);
  const sorted = combinedData.sort((a, b) => {
      // Get the date value from the appropriate column
      let aDateValue = a[COLUMN_INDICES['Date of event']];
      let bDateValue = b[COLUMN_INDICES['Date of event']];

      let aDate = new Date(0); // Default to epoch for empty/invalid dates
      let bDate = new Date(0);

      // Attempt to parse/use aDateValue
      if (aDateValue instanceof Date) {
        aDate = aDateValue;
      } else if (typeof aDateValue === 'string' && aDateValue.trim() !== '') {
        try {
          aDate = Utilities.parseDate(aDateValue.trim(), "CET", "dd/MM/yyyy");
        } catch (e) {
          Logger.log(`Warning: Could not parse date for A: '${aDateValue}' Error: ${e.message}`);
        }
      }

      if (bDateValue instanceof Date) {
        bDate = bDateValue;
      } else if (typeof bDateValue === 'string' && bDateValue.trim() !== '') {
        try {
          bDate = Utilities.parseDate(bDateValue.trim(), "CET", "dd/MM/yyyy");
        } catch (e) {
          Logger.log(`Warning: Could not parse date for B: '${bDateValue}' Error: ${e.message}`);
        }
      }
      
      return aDate.getTime() - bDate.getTime();
  });

  const newNumberOfRowsToWrite = sorted.length;
  const newNumberOfColsToWrite = COLUMN_INDICES.TOTAL_COLUMNS; 

  // Define the target range for writing the sorted data (A to W)
  const targetRange = sheet.getRange(firstDataRow, 1, newNumberOfRowsToWrite, newNumberOfColsToWrite);
  targetRange.setValues(sorted); // This overwrites the target area

  // IMPORTANT: If the number of sorted rows is *less* than the previously used rows,
  // clear the excess rows below the new data (in columns A to W)
  if (newNumberOfRowsToWrite < numExistingDataRows) {
      const clearStartRow = firstDataRow + newNumberOfRowsToWrite;
      const rowsToClearCount = numExistingDataRows - newNumberOfRowsToWrite;
      // Clear only the cells in the columns the script manages (A to W)
      sheet.getRange(clearStartRow, 1, rowsToClearCount, newNumberOfColsToWrite).clearContent();
      Logger.log(`Cleared ${rowsToClearCount} excess rows for tab: "${sheet.getName()}"`);
  }
  
  Logger.log(`${newRows.length} new events added and sheet sorted for tab: "${sheet.getName()}"`);

});

// --- FINAL FIX for "Last Sync" placement ---
// Place "Last Sync" on the "Sync Log" sheet, cell A1
const syncLogSheet = spreadsheet.getSheetByName("Sync Log");
if (syncLogSheet) {
  syncLogSheet.getRange('A1').setValue("Last Sync: " + Utilities.formatDate(now, "CET", "dd/MM/yyyy HH:mm:ss"));
  Logger.log('Last Sync timestamp updated on "Sync Log" sheet, A1.');
} else {
  Logger.log('Warning: "Sync Log" sheet not found. Could not update Last Sync timestamp.');
}
// --- END FINAL FIX ---

Thank you in advance for any insights or assistance!

AppsScript + JDBC + MySQL – retrieve DECIMAL value and add it to sheet as number

I have MySQL db which contains a stored procedure named spYearlyTotals.
The procedure accepts a year as a param and returns 13 columns. The first one is some string label, the latter ones are DECIMAL(15,2) which represent currency totals for the given label for each month.

I have an AppScript function which basically runs this procedure and displays the values in a google sheet:

function displayYearlyTotals(ss) {
  let totalsTab = ss.getSheetByName("totals tab");
  let year = totalsTab.getRange("A3").getValue();

  let conn = Jdbc.getConnection(_dbUrl, _dbUsername, _dbPassword);  
  try {
    let stmt = conn.prepareStatement('CALL spYearlyTotals(?)');
    stmt.setInt(1, year);
    let results = stmt.executeQuery();

    let row = Array();
    let data = Array();
    
    while (results.next()) {
      row = [];
      row.push(results.getString(1)); // label
      for (let i = 1; i <= 12; i++) {
        let amnt = results.getFloat(1 + i); // monthly values

        row.push(results.wasNull() ? null : amnt);
      }

      data.push(row);
    }

    totalsTab.getRange(3, 1, data.length, 13).setValues(data);
  }
  finally {
    conn.close();
  }

}

Using getFloat leads to small inaccuracies – decimal values are treated as floats which sometimes makes my values to differ by 0.01. This is not acceptable for me.
From the other hand – values are pushed to the range as numbers and google sheet formatting works fine for my output.

I have tried replacing getFloat(i+1) by getString(i+1) and getBigDecimal(i+1).toFixed(2). Values are retrieved accurately but they are treated as strings – thus my formatting in the sheet is lost.

What is the proper way to handle DECIMAL columns so that they are correctly passed to the sheet as numbers?

OATH 2.0 Code Implementation of Client Credentials Grant

I am currently working on an implementation of OATH 2.0 to generate access tokens. I would use the client credentials grant from OpenId:
https://www.npmjs.com/package/openid-client?activeTab=readme
But the Code is not working for me. I have used the exact same code as in the tutorial:

import * as client from "openid-client";

const server: URL = new URL(
  "*"
);
const clientId = "*";
const clientSecret = "*";
const scope = "*";
const resource = "*";

let config: client.Configuration = await client.discovery(
  server,
  clientId,
  clientSecret
);

let tokens: client.TokenEndpointResponse = await lib.clientCredentialsGrant(
  config,
  { scope, resource }
);

console.log("Token Endpoint Response", tokens);

These are my errors:

Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
Cannot find name 'lib'.

Has anyone experience with this? Thanks in regards!

How to transcribe local audio File/Blob with Transformers.js pipeline? (JSON.parse error)

I’m working on a browser-based audio transcription app using Transformers.js by Xenova. I’m trying to transcribe a .wav file selected by the user using the following code:

import { pipeline } from '@xenova/transformers';

async function transcribe(file) {
    console.log(file.name); // logs the selected .wav filename

    const transcriber = await pipeline(
        'automatic-speech-recognition',
        'Xenova/whisper-tiny.en'
    );

    if (!file) return;

    const url = file;
    const text = await transcriber(url);
}

This function is triggered when a user uploads a local .wav file (from an <input type="file" accept=".wav"></input>).

What I’ve Tried / Verified:

  • I’m importing the pipeline correctly from @xenova/transformers

  • The model name ‘Xenova/whisper-tiny.en’ is spelled correctly

  • I’m online (not offline mode)

  • I used the exact example from the docs which works with a remote URL like:

    const url = 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/jfk.wav';
    

    But I’m trying to use a local File object (user uploads a .wav)

How to add php script into script? [duplicate]

In the PHP code below;

How can we modify it so that when the input changes, the value in it is assigned to $_SESSION[“roomId”]?
Latterly, I want to call the $_SESSION[“roomId”] from “myPhp.php”.
Thanks in advance for your help,

Best Wishes

<?php

    session_start();
    $_SESSION["roomId"]="";

    
?>

<!DOCTYPE html>
<html>
    <body>
        <script>

        function chkLen() {
                if(document.getElementById("dCell").value.length >0) {
                    var deg = document.getElementById("dCell").value;
                    <?php $_SESSION['roomId']=deg; ?>
                }

            }

        </script>

        <form name="myForm" onsubmit="myPhp.php">
        <input id="dCell" type="text" onChange="chkLen();" value="" />
        </form>
    </body> 
</html>

Handling Events Between Two Different Web Pages

Suppose Page 1 opens a new window (Page 2) using window.open.
Is it technically possible for an event on Page 2 (like clicking a button) to affect the content or behavior of Page 1?

For example, when a user clicks a “Confirm” button on Page 2, the popup window (Page 2) closes using window.close(), and at the same time, Page 1 navigates to a detail view or updates its content.

Is this kind of interaction possible between two pages?
If so, what would be the recommended or standard way to implement it?

Thank you in advance for your advice.

White space shown in page when displayed in browser [closed]

I have below HTML and Java script code.

function isNumberKey(evt) {
  var charCode = (evt.which) ? evt.which : evt.keyCode
  if (charCode > 31 && (charCode < 48 || charCode > 57)) {
    alert("Enter only numbers!");
    return false;
  }
  return true;
}

var getRdnUrl = "/peccgi/xmlhttp/getrdninfo"; // The server-side script

var animstart = 0;
var ErrorCnt = 0;
var MaxError = 0;
var Commerror = 0;
var timerID = 0;
var StopUpdate = true;
var Commerror = 0;
var UpdateRate = 1000;


function cycle_update(error, width, height) {
  const c = document.getElementById("progressCanvas");
  const ctx = c.getContext("2d");

  ctx.strokeRect(20, 20, width, height);
  // Create linear gradient
  const grad = ctx.createLinearGradient(0, 0, width, height);
  //Color c = Color.parseColor("#c0c0c0");
  if (error) {
    grad.addColorStop(0, "rgb(255, 0, 0)");
    grad.addColorStop(1, "rgb(255, 0, 0)");
  } else {
    //animstart = animstart > 1?animstart-1:animstart;
    grad.addColorStop(animstart, "rgb(0, 228, 0)");
    animstart += 0.25
    animstart = animstart > 1 ? animstart - 1 : animstart;
    grad.addColorStop(animstart, "rgb(0, 160, 0)");
    animstart += 0.25
    animstart = animstart > 1 ? animstart - 1 : animstart;
    grad.addColorStop(animstart, "rgb(255, 255,255)");
    animstart += 0.25
    animstart = animstart > 1 ? animstart - 1 : animstart;
    grad.addColorStop(animstart, "rgb(0, 196, 0)");
    animstart += 0.25
    animstart = animstart > 1 ? animstart - 1 : animstart;
    grad.addColorStop(animstart, "rgb(0, 228, 0)");
  }

  // Fill circle with gradient
  ctx.beginPath();
  ctx.rect(20, 20, width, height);
  //ctx.arc(30,30, 20, 0, 2 * Math.PI);
  ctx.fillStyle = grad;
  ctx.fill();
  animstart += 0.25;
  if (animstart > 1) animstart -= 1;
}

function StartUpdate() {
  cycle_update(false, 100, 40);
}
.rdnTableHeader {
  background-color: #005E60;
  color: #ffffff;
  font-weight: bold;
}

.progress {}

.ctrlbtn {
  background-color: #005E60;
  border: none;
  color: white;
  padding: 15px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  margin: 4px 2px;
  cursor: pointer;
}
<html>

<head>
  <TITLE> Venkata info Page </TITLE>
</head>

<body>
  <div class="pageMain full">
    <p align="center">
    <h2>Venkata's Information </h2>
    </p>
  </div>
  <label for="lblUpdatePeriod">Update Period(sec): </label>
  <input name="period" type="number" id="period" onkeypress="return isNumberKey(event)" />
  <br><br>
  <p>Click on the Start button update page dynamically.</p>
  <button class="ctrlbtn" type="button" id="StartBtn" onclick="StartUpdate();">Start update</button>
  <div id="divCanvas"><canvas class="progress" width="200" height="200" id="progressCanvas"></canvas></div>
  <p> Copy right </p>
</body>

</html>

When I open page in browser I am seeing below snapshot. I require help on following points

  1. I am not able to find from where space is coming between Start update button and copy right.
  2. I also want to show progress button next to Start update button, when I click “Start update” button.
    Can any one help me in resolving above points. Thanks for your guidance
    enter image description here

How to resolve a shift/reduce conflict for greedy modifiers in a Tree-sitter grammar for VB.NET?

I am developing a Tree-sitter grammar for VB.NET and have run into a persistent parsing issue with member declarations that have multiple modifiers. The parser fails to be “greedy” and consumes only the first modifier, misinterpreting the second modifier as a variable name.

This appears to be a classic shift/reduce conflict, but the standard solutions I’ve tried (using prec, prec.dynamic, and the conflicts array) have not resolved the issue, often because they interfere with other precedence rules in the grammar.

The Problem

Given a simple VB.NET class, the parser should correctly handle fields with both single and multiple modifiers.

Minimal VB.NET Example:

Public Class MyTestClass
    ' This line with a single modifier parses correctly.
    Private _someField As String

    ' This line with multiple modifiers fails.
    Private ReadOnly _anotherField As Integer
End Class

When parsing the line Private ReadOnly _anotherField As Integer, the parser incorrectly stops after Private and tries to parse ReadOnly as the field’s name.

Incorrect AST Output:

The resulting Abstract Syntax Tree for the failing line looks like this, clearly showing the error

(field_declaration
  (modifiers
    (member_modifier)  -- "Private"
  )
  (variable_declarator
    (identifier)       -- "ReadOnly"
  )
  (ERROR)              -- "_anotherField As Integer"
)

The modifiers rule is not greedy, and an ERROR node is produced.

Relevant Grammar Snippet (grammar.js)
Here are the key rules from my grammar.js that are involved in this issue.

module.exports = grammar({
  name: 'vbnet',
  // ... other rules and extras

  rules: {
    // ...

    member_modifier: $ => choice(
      ci('Public'), ci('Private'), ci('Protected'), ci('Friend'),
      ci('Protected Friend'), ci('Private Protected'), ci('ReadOnly'),
      ci('WriteOnly'), ci('Shared'), ci('Shadows'), ci('MustInherit'),
      ci('NotInheritable'), ci('Overrides'), ci('MustOverride'),
      ci('NotOverridable'), ci('Overridable'), ci('Overloads'),
      ci('WithEvents'), ci('Widening'), ci('Narrowing'),
      ci('Partial'), ci('Async'), ci('Iterator')
    ),

    modifiers: $ => repeat1($.member_modifier),

    _type_member_declaration: $ => choice(
      // ... other members like empty_statement, inherits_statement
      prec(2, $.constructor_declaration),
      prec(1, $.method_declaration),
      prec(1, $.property_declaration),
      // ... other members with precedence
      $.field_declaration // Lower precedence
    ),

    field_declaration: $ => seq(
      optional(field('attributes', $.attribute_list)),
      field('modifiers', $.modifiers),
      commaSep1($.variable_declarator),
      $._terminator
    ),

    variable_declarator: $ => seq(
      field('name', $.identifier),
      optional($.array_rank_specifier),
      optional($.as_clause),
      optional(seq('=', field('initializer', $._expression)))
    ),

    // ... other rules
  }
});

function ci(keyword) {
  return new RegExp(keyword.split('').map(letter => `[${letter.toLowerCase()}${letter.toUpperCase()}]`).join(''));
}
// ... other helpers

The Question

How can I modify this Tree-sitter grammar to correctly and “greedily” parse multiple consecutive modifiers in a field_declaration, while still correctly resolving the ambiguities between different types of member declarations (e.g., a field_declaration vs. a method_declaration)?

Is there any way I can view documentation while hovering over the element after importing from a CDN?

I’m new to the club here, so this is my first question here.

My problem is using a CDN for jQuery which in terms of function, works, but the documentation while hovering over a jQuery element doesn’t work. It just says “any”. Or type s for show(), just doesn’t autocomplete.
For those who don’t know I use VScode’s IntelliSense.

From there, after I tried the CDN, I decided to use npm. The autocompletion and documentation while hovering over the element works.

With CDN

With npm

npm‘s documentation does work but it throws this error in ChromeDevTools.

The error

My index.html code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <title>jQuery Test</title>
</head>
<body>
    <h1>This is a test for jQuery.</h1>
    <br>
    <div class="show-images">
        <h1>jQuery works!</h1>
        <img src="images/5290058.png" alt="photo" id="image1">
    </div>
    <!-- <script src="https://code.jquery.com/jquery-3.7.1.js" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous"></script> -->
    <script src="script.js"></script>
</body>
</html>

and my styles.css code:

body {
    font-family: Verdana, Geneva, Tahoma, sans-serif;
}

h1 {
    text-align: center;
    font-weight: 900;
}

.show-images {
    text-align: center;
    display: none;
}

#image1 {
    border-radius: 15px;
    border: 3px solid black;
}

What is wrong with my npm and CDN, or am I just dumb and it is always like this?

Serial Key create (no random) [closed]

Not a random key,

I want to generate a specific key

example :
1967-1583-1558-1485

9892-4817-4575-7760

7834-0038-6240-4510

I just want it to give me the keys I added

Is it possible to do something like this?

function makeid(length) {
  var result = "";
  var characters = '0123456789';
  for (var i = 0; i < length; i++) {
    result += characters[Math.floor(Math.random() * characters.length)];
  }
  result = result.match(/d{1,4}/g).join("-");
  return result;
}

console.log(makeid(16));