Why angular (or perhaps any UI framework) rounds incorrectly?

So I detected this in angular, but then I’m trying the chrome console like this and I get the same problem. Can somebody explain why this happens?

Open console in your browser and type: 14.9 divided by 100

Result: 0.149 which is ok

enter image description here

Now, do the opposite:
0.149 x 100 it should be 14.9 right?!

enter image description here

Well no, you get 14.8999999999999999999 instead….

In C# this is clear for me, some data types (decimal vs double) has a binary calculation that could lead to precision loss, but here I’m not able to pick another numeric type rather than NUMBER, so what can I do to have precision in these cases?

How to implement *paginated* fuzzy matching on a Trie data structure (in JavaScript or TypeScript)?

I asked how to paginate a trie a while back, and got this elegant and simple Trie structure in the answer:

class TrieNode {
  constructor(key) {
    // the "key" value will be the character in sequence
    this.key = key;

    // we keep a reference to parent
    this.parent = null;

    // we have hash of children
    this.children = {};

    // check to see if the node is at the end
    this.end = false;

    // count how many words are at this node or below.
    this.count = 0;

    // Ensure children are in the right order.
    this.lastChildKey = '';
  }

  getWord() {
    let output = [];
    let node = this;

    while (node !== null) {
      output.unshift(node.key)
      node = node.parent
    }

    return output.join('')
  }
}

class Trie {
  constructor() {
    this.base = new TrieNode(null)
  }

  insert(word) {
    let node = this.base

    const points = Array.from(word)

    for (const i in points) {
      const point = points[i]
      node.count++
      if (!node.children[point]) {
        const child = node.children[point] = new TrieNode(point)
        child.parent = node
      }

      node = node.children[point]

      if (i == word.length - 1) {
        node.end = true
      }

      // If words were inserted out of order, fix order of children.
      if (node.lastChildKey <= point) {
        node.lastChildKey = point
      }
      else {
        // Need to fix order of children.
        let keys = Object.keys(node.children)
        keys.sort()
        let orderedChildren = {}
        for (const key in keys) {
          orderedChildren[key] = node.children[key]
        }
        node.children = orderedChildren
      }
    }
  }

  contains(word) {
    let node = this.base

    const points = Array.from(word)

    for (const i in points) {
      const point = points[i]

      if (node.children[point]) {
        node = node.children[point]
      } else {
        return false
      }
    }

    return node.end;
  }
  find(prefix, startAt, maxCount) {
    let node = this.base
    let output = []

    const points = Array.from(prefix)

    for (const i in points) {
      const point = points[i]

      // make sure prefix actually has words
      if (node.children[point]) {
        node = node.children[point]
      } else {
        // there's none. just return it.
        return output
      }
    }

    const stack = [node]
    while (stack.length) {
      if (maxCount <= output.length) {
          return output
      }
      node = stack.shift()
      if (node.count < startAt) {
        startAt -= node.count
      }
      else {
        // base case, if node is at a word, push to output
        if (node.end) {
          if (0 < startAt) {
            startAt--;
          }
          else {
            output.push(node.getWord())
          }
        }

        // iterate through each children, call recursive findAllWords
        for (var child in node.children) {
          stack.push(node.children[child])
        }
      }
    }

    return output
  }
}

You can use it like this:

const fs = require('fs')
const Trie = require('./Trie')

const words = fs.readFileSync('tmp/scrabble.csv', 'utf-8')
  .trim()
  .split(/n+/)
  .map(x => x.trim())

const trie = new Trie.Trie()

words.forEach(word => trie.insert(word))

console.log(trie.find('a', 0, 12))

console.log(trie.find('a', 6, 6))

Asking AI about fuzzy string matching on Tries, they gave this implementation:

class TrieNode {
    children: Map<string, TrieNode> = new Map();
    isEndOfWord: boolean = false;
    word: string | null = null; // To store the word at leaf nodes
}

class Trie {
    root: TrieNode = new TrieNode();

    insert(word: string) {
        let node = this.root;
        for (const char of word) {
            if (!node.children.has(char)) {
                node.children.set(char, new TrieNode());
            }
            node = node.children.get(char)!;
        }
        node.isEndOfWord = true;
        node.word = word; // Store the complete word at the end node
    }

    fuzzySearch(query: string): {word: string, score: number}[] {
        let results: {word: string, score: number}[] = [];
        // Initial call with max distance, here it's set to a portion of the query length for flexibility
        const maxDistance = Math.floor(query.length / 2); 
        this.searchRecursive(this.root, query, "", 0, maxDistance, results);
        // Sort results based on score, higher first
        return results.sort((a, b) => b.score - a.score);
    }

    private searchRecursive(node: TrieNode, query: string, currentWord: string, currentScore: number, maxDistance: number, results: {word: string, score: number}[]): void {
        if (query.length === 0 || node.isEndOfWord) {
            let finalScore = currentScore;
            if (node.word) {
                // Adjust score based on the length difference, assuming a penalty for each missing character
                finalScore -= Math.abs(node.word.length - currentWord.length) * 5;
                if (query.length === 0 && node.isEndOfWord) {
                    results.push({ word: node.word, score: finalScore });
                }
            }
        }

        if (maxDistance < 0) return; // Stop if max edits exceeded

        for (let i = 0; i < query.length; i++) {
            const char = query[i];
            if (node.children.has(char)) {
                // Exact match, continue with the rest of the query
                const nextNode = node.children.get(char)!;
                this.searchRecursive(nextNode, query.substring(i + 1), currentWord + char, currentScore + 10, maxDistance, results);
            }

            // Edit operations with penalties
            node.children.forEach((childNode, childChar) => {
                // Substitution (replace char)
                if (childChar !== char) {
                    this.searchRecursive(childNode, query.substring(i + 1), currentWord + childChar, currentScore - 5, maxDistance - 1, results);
                }

                // Insertion (add a char)
                this.searchRecursive(childNode, query.substring(i), currentWord + childChar, currentScore - 5, maxDistance - 1, results);
            });

            // Deletion (skip a char in query)
            this.searchRecursive(node, query.substring(i + 1), currentWord, currentScore - 5, maxDistance - 1, results);
            break; // Only apply one edit per recursion level
        }
    }
}

// Example enhanced usage
let trie = new Trie();
trie.insert("VisualStudioCode");
trie.insert("VisualStudioCommunity");
trie.insert("VerySimpleCode");
trie.insert("VisualSpaceCoordinator");

const searchResults = trie.fuzzySearch("VSC");
console.log(searchResults);

If you implement “pruning” of the scored results (sorted by score), how can you also implement pagination, without going through the entire set of trie nodes? That is, say I want to return 100 results, if I use the second Trie example, it will return possibly 1000’s of results (assuming a large dictionary like the 100k+ scrabble dictionary, or a million word dictionary). Then I can paginate those results, but that is a waste of computational effort. How can you avoid processing all the nodes in the trie, while implementing VSCode-like fuzzy text matching (with scoring), AND implementing pagination, where you can jump to a specific page and get say 100 nodes from that point forward?

Note: It appears to get really high quality fuzzy matching you need machine learning, AI, and user data input (like most recently accessed files, for VSCode), etc.. I don’t intend on creating the perfect paginated fuzzy matching Trie out there, just something that works reasonably well with your standard algorithms. Just not sure yet how / if it’s possible to combine pagination with the fuzzy matching scoring aspect, on a Trie.

Sending data to API, getting CORS error on preflight using XHR

I am currently trying to send data to an API on a subdomain, but it is failing.

In devtools I can see there is a CORS error relating to a redirect:

Access to XMLHttpRequest at 'https://api.example.com/v1/dashboard/images/upload.php' from origin 'https://example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

I assume the redirect is caused by lack of credentials even though I have withCredentials on my xhr object:

let endpoint = form.action,
    xhr = new XMLHttpRequest();

xhr.open('POST', endpoint);
xhr.withCredentials = true;

xhr.upload.addEventListener('progress', ({loaded, total}) => {
    ... stuff here ...
});

let data = new FormData(form);
xhr.send(data);

My API has these headers set in the Nginx config:

add_header "Access-Control-Allow-Origin" "https://example.com" always;
add_header "Access-Control-Allow-Credentials" "true";

Other APIs in use work fine but use fetch rather than XHR – the reason for using XHR for this request is I want to feedback to the user upload progress, which I understand isn’t a feature of fetch?

Remove all subsequent objects with similar strings in key from array in Javascript [duplicate]

I’m trying to extract all objects from an array, into a new array, that have a unique name based on the first 3 characters.

Input:

[
 {
  name: 'Danny',
  age:33
 },
 {
  name:'Daniel',
  age:35
 },
 {
  name:'Chris',
  age:36
 },
 {
  name:'Dan',
  age:34
 },
 {
  name:'Roger',
  age:38
 }
]

Output:

[
 {
  name: 'Danny',
  age:33
 },
 {
  name:'Chris',
  age:36
 },
 {
  name:'Roger',
  age:38
 }
]

How can I do this most efficiently?

Is there a way to handle files between server and client sides?

To put it simply, I’m trying to create a series of buttons from the names of files in a folder located on the server (here it is called “CAD”). I know that a JavaScript running client-side cannot access server folders on the server file system. What is the best way to make this happen? I am a beginner to this so any help would be very appreciated.

I have tried using PHP, but that only allows me to access local folders on my laptop. When I host my web-app, I want to be able to access the files in folders in the server. I have also tried used a Node.JS environment, but this also does not work very well.

const fs = require("fs").promises;

function main() {
    findFileTypes("CAD", (fileNames, fileTypes) => {
        console.log(fileNames);
        console.log(fileTypes);
    });
}

main();

function findFileTypes(directory, callback) {
    fs.readdir(directory)
        .then(fileNames => {
            const fileTypes = fileNames.map(fileName => {
                const dotIndex = fileName.lastIndexOf(".");
                if (dotIndex > 0) {
                    return fileName.substring(dotIndex);
                } else {
                    return "";
                }
            });
            callback(fileNames, fileTypes);
        })
        .catch(error => {
            console.error("Error reading directory:", error);
        });
}

PHP cannot read a cookie set by Javascript

Javascript:

document.cookie = "name=value0;";

fetch("/path/to/file.php", {
      method: "POST",
      credentials: "same-origin",
      body: JSON.stringify({
        value1: value1,
        value2: value2
      }),
      headers: {
        "Content-Type": "application/json"
      },
    });

PHP:

var_dump($_COOKIE);

PHP response:

array(0) {
}

I have the PHP file in a seperate folder from the Javascript file, but they are on the same domain. When I set the cookie in Javascript, I use fetch to call the PHP file, but when it calls, there is no cookies that PHP can see. In the network console I can see that the script is being ran successfully.

FullCalendar “Today” Button Not Working and Unresponsive in Inspect Mode

I’m implementing a FullCalendar instance on my website and facing an issue where the “Today” button is not functioning as expected. Despite my efforts, clicking the “Today” button does not navigate the calendar to the current date. My code setup for initializing the calendar is as follows:

    var now = new Date();
    // Ensure it doesn't go back to the previous day
    var adjustedHour = now.getHours() - 2 < 0 ? 0 : now.getHours() - 2;
  
    var scrollTime = adjustedHour.toString().padStart(2, '0') + ':00:00';

    document.addEventListener('DOMContentLoaded', function() {
      var calendarEl = document.getElementById('calendar');
      var calendar = new FullCalendar.Calendar(calendarEl, {
        initialView: 'timeGrid',
        dayCount: getDayCountForWindowSize(),
        height: '99%',
        titleFormat: { // Specify how the title should be formatted
            month: 'short', // Full name of the month
            year: '2-digit' // 4 digit year
        },
        allDaySlot: false,
        scrollTime: scrollTime,
        dayHeaderFormat: { weekday: 'short', day: '2-digit' }
        });
        
      calendar.render();
    });

    function getDayCountForWindowSize() {
        var width = window.innerWidth;
        if (width < 768) { // Mobile devices
            console.log(3)
            return 3;
        } else if (width >= 768 && width < 1024) { // Tablets
            return 5;
        } else { // Desktops and larger screens
            return 7; // Assuming a full week for larger screens
        }
    }

Debugging Steps Taken:

  1. Console Errors: Checked the browser’s console for errors and found none related to FullCalendar or its initialization.
  2. Event Listeners: Inspected the “Today” button for additional click
    event listeners and found only those attached by FullCalendar. No
    custom or conflicting event handlers are present.
  3. CSS Inspection: Looked into potential CSS conflicts that could interfere with the button’s functionality, specifically pointer-events, but found no issues. The button’s styles seem to be in order.
  4. Element Isolation: While trying to inspect the element in the
    browser, I noticed that the “Today” button does not get highlighted
    separately.

Can someone help me with what I am missing here?

pickadate plugin is not working as it is always showing wrong date in the dropdown calendar

I have the Calendar dates setup, i have two input fields and both carry dates and input fields values are coming Like this

I have the following Js code

var picker1 = $('#gameDate2').pickadate({
    format: 'mm/dd/yyyy',
    selectYears: true,
    selectMonths: true,
    selectYears: true,
    selectMonths: true,
    disable: [
        true,
        [2023, 11, 23],
        [2023, 11, 23],
        [2023, 11, 23],
        [2023, 11, 23],
        [2023, 11, 24],
        [2023, 11, 24],
        [2023, 11, 24],
        [2023, 11, 24],
        [2023, 11, 25],
        [2023, 11, 25],
        [2023, 11, 25],
        [2023, 11, 25],
        [2023, 11, 26],
        [2023, 11, 26],
        [2023, 11, 26],
        [2023, 11, 26],
        [2023, 11, 26],
        [2023, 11, 27],
        [2023, 11, 27],
        [2023, 11, 27],
        [2023, 11, 27],
        [2023, 11, 27],
        [2023, 2, 21],
        [2023, 3, 21],
        [2023, 3, 21],
        [2023, 3, 21],
        [2023, 3, 22],
        [2023, 4, 1],
        [2023, 4, 12],
        [2023, 4, 21],
        [2023, 4, 21],
        [2023, 4, 21],
        [2023, 4, 21]
    ],
    'min': "12/23/2023",
    'max': "05/21/2024",
    klass: {
        infocus: 'picker__day--enabled',
        highlighted: 'picker__day--outfocus'
    },
    today: '',
    clear: '',
    close: '',
    onSet: function(event) {
        var selectedDate = event.select;
        if (selectedDate === undefined) {
            selectedDate = Date.now();
        }
        if (typeof selectedDate == "number") {
            selectedDate = unixDateTOString(selectedDate);
        }
        $.ajax({
            url: 'schedule_getgame.cfm?gamedate=' + selectedDate + '&clientID=' + '1111',
            success: function(data) {
                if (data.length > 0) {
                    var $jsonObject = $.parseJSON(data);
                    $gameSelect.html('');
                    if ($jsonObject.length === 0) {
                        $gameSelect.prop("disabled", true);
                        $color.css('display', 'none');
                    } else {
                        $gameSelect.prop("disabled", false);
                        $color.css('display', 'inline-block');
                        $gameSelect.append('<option value="">Please select Game ......</option>');
                        $.each($jsonObject, function(index, item) {
                            if (typeof gameIdJs !== 'undefined' && gameIdJs == item.gameID) {
                                $gameSelect.append("<option selected value='" + item.gameID + "-" + item.clientID + "-" + item.gameNumber + "-" + item.gameDate + "-" + item.gameTime + "-" + item.homeTeam + "-" + item.awayTeam + "'>" + 'Game ' + item.gameNumber + " on " + item.gameDate + " at " + item.gameTime + " between " + item.homeTeam + " and " + item.awayTeam + "</option>");
                            } else {
                                $gameSelect.append("<option value='" + item.gameID + "-" + item.clientID + "-" + item.gameNumber + "-" + item.gameDate + "-" + item.gameTime + "-" + item.homeTeam + "-" + item.awayTeam + "'>" + 'Game ' + item.gameNumber + " on " + item.gameDate + " at " + item.gameTime + " between " + item.homeTeam + " and " + item.awayTeam + "</option>");
                            }
                        })
                    }
                }
            }
        });
    }
}).pickadate('picker');
if (gameDateJs !== 0) {
    $('#gameDate2').val(gameDateJs);
    picker1.set('select', gameDateJs, {
        format: 'mm/dd/yyyy'
    });
}
var picker2 = $('#gameDate3').pickadate({
    format: 'mm/dd/yyyy',
    selectYears: true,
    selectMonths: true,
    selectYears: true,
    selectMonths: true,
    disable: [
        true,
        [2023, 11, 23],
        [2023, 11, 23],
        [2023, 11, 23],
        [2023, 11, 23],
        [2023, 11, 24],
        [2023, 11, 24],
        [2023, 11, 24],
        [2023, 11, 24],
        [2023, 11, 25],
        [2023, 11, 25],
        [2023, 11, 25],
        [2023, 11, 25],
        [2023, 11, 26],
        [2023, 11, 26],
        [2023, 11, 26],
        [2023, 11, 26],
        [2023, 11, 26],
        [2023, 11, 27],
        [2023, 11, 27],
        [2023, 11, 27],
        [2023, 11, 27],
        [2023, 11, 27],
        [2024, 2, 21],
        [2024, 3, 21],
        [2024, 3, 21],
        [2024, 3, 21],
        [2024, 3, 22],
        [2024, 4, 1],
        [2024, 4, 12],
        [2024, 4, 21],
        [2024, 4, 21],
        [2024, 4, 21],
        [2024, 4, 21]
    ],
    'min': "12/23/2023",
    'max': "05/21/2024",
    klass: {
        infocus: 'picker__day--enabled',
        highlighted: 'picker__day--outfocus'
    },
    today: '',
    clear: '',
    close: '',
    onSet: function(event) {
        var selectedDate = event.select;
        if (selectedDate === undefined) {
            selectedDate = Date.now();
        }
        if (typeof selectedDate == "number") {
            selectedDate = unixDateTOString(selectedDate);
        }
        $.ajax({
            url: 'schedule_getgame.cfm?gamedate=' + selectedDate + '&clientID=' + '1111',
            success: function(data) {
                if (data.length > 0) {
                    var $jsonObject = $.parseJSON(data);
                    $gameSelectAway.html('');
                    if ($jsonObject.length === 0) {
                        $gameSelectAway.prop("disabled", true);
                        $color1.css('display', 'none');
                    } else {
                        $gameSelectAway.prop("disabled", false);
                        $color1.css('display', 'inline-block');
                        $gameSelectAway.append('<option value="">Please select Game ......</option>');
                        $.each($jsonObject, function(index, item) {
                            if (typeof gameIdJsAway !== 'undefined' && gameIdJsAway == item.gameID) {
                                $gameSelectAway.append("<option selected value='" + item.gameID + "-" + item.clientID + "-" + item.gameNumber + "-" + item.gameDate + "-" + item.gameTime + "-" + item.homeTeam + "-" + item.awayTeam + "'>" + 'Game ' + item.gameNumber + " on " + item.gameDate + " at " + item.gameTime + " between " + item.homeTeam + " and " + item.awayTeam + "</option>");
                            } else {
                                $gameSelectAway.append("<option value='" + item.gameID + "-" + item.clientID + "-" + item.gameNumber + "-" + item.gameDate + "-" + item.gameTime + "-" + item.homeTeam + "-" + item.awayTeam + "'>" + 'Game ' + item.gameNumber + " on " + item.gameDate + " at " + item.gameTime + " between " + item.homeTeam + " and " + item.awayTeam + "</option>");
                            }
                        })
                    }
                }
            }
        });
    }
}).pickadate('picker');
if (gameDateJsAway !== 0) {
    picker2.set('select', gameDateJsAway, {
        format: 'mm/dd/yyyy'
    });
}

function unixDateTOString(unix_timestamp) {
    var dateObj = new Date(unix_timestamp);
    var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    var year = dateObj.getFullYear();
    var month = dateObj.getMonth() + 1;
    var date = dateObj.getDate();
    var formattedTime = date + '/' + month + '/' + year;
    return formattedTime;
}

now it works but what hapens is, when i select the date and from the dropdown it shows dec 2023 but 27 selected and in the second calendar dropdown using piakdate it shows a totaly different date

i am getting lost in this code what is going wrong here

code is updated as above

Why is this timing function getting a typeError? [duplicate]

The timer stops when the mouse hovers over a (.typing) item and the timer resumes when the mouse leaves. That works, but I wanted to remove two classes from separate id’s when their respective setTimeout function hits 0.

Heres the code:

let dhaTimeout = {
  id: null,
  startTime: 0,
  remainingTime: 5000,
  isPaused: false
}
let stackTimeout = {
  id: null,
  startTime: 0,
  remainingTime: 10000,
  isPaused: false
}

function startTimeout(timeout, elementId){
  if(timeout.isPaused){
    timeout.isPaused = false;
    timeout.startTime = Date.now();
    timeout.id = setTimeout(() => {
      const element = document.getElementById(elementId)
      if(element){
        element.classList.remove("gone")  
      } else { 
        console.log(`Element not found, ${elementId}`)
      }
    }, timeout.remainingTime)
  } else{
      timeout.startTime = Date.now()
      timeout.id = setTimeout(() => {
        const element = document.getElementById(elementId)
        element.classList.remove("gone")}, timeout.remainingTime)
    }
  }
function pauseTimeout(timeout){
  if(!timeout.isPaused && timeout.id){
    clearTimeout(timeout.id)
    timeout.isPaused = true;
    timeout.remainingTime = timeout.remainingTime - (Date.now() - timeout.startTime)
    timeout.id = null
  }
}

function onMouseEnter(){
  pauseTimeout(stackTimeout)
  pauseTimeout(dhaTimeout)
}

function onMouseLeave(){
  startTimeout(stackTimeout)
  startTimeout(dhaTimeout)
}

document.addEventListener('DOMContentLoaded', function() {
  document.querySelectorAll(".typing").forEach(element => {
    element.addEventListener('mouseenter', onMouseEnter)
    element.addEventListener('mouseleave', onMouseLeave)
  })
})

startTimeout(stackTimeout, 'full-stack')
startTimeout(dhaTimeout, 'dha')


I’m getting a typeError when the startTimeout function is called for the second time, saying can’t read classList when it’s null. So I logged the element to see if its there but its not finding it.. but I have nothing removing the individual element so it’s not making sense to me how it’s not finding the element, maybe the class but the element being gone? I didn’t think the html code was necessary as its 3 p elements, first two with the ‘typing’ class and last two with the ‘gone’ class. id of ‘dha’ for the second p and ‘full-stack’ for the third.

I’ve tried to add a separate if else for the failure of finding the element to find it again somehow but that lead nowhere.

i do not know how to remove items on wishlist

i started making a wishlist but i dont know how to do the following:

  • a button which add/remove items from database when clicked
  • display the favourites
@app.route("/add_favourite", methods=["POST"]) # / contact page
def add_favourite():
    if request.method == "POST":
        TablePk = request.form.get("TablePk")
        Id = request.form.get("Id")
        CustomerId = request.form.get("CustomerId")
        dbObject = Database(DB_FILE)
        # Check if that is already added
        # May be remove favourite
        dbObject.addFavourite(TablePk, Id, CustomerId)
        return "<span class='badge text-bg-success'>Added!</span>"
    def addFavourite(self, TablePk, Id, CustomerId):
        cursor = self.connection.cursor()
        query = f"INSERT INTO Favourite ({TablePk}, 'CustomerId') VALUES ({Id}, {CustomerId});"
        #print(query)
        try:
            cursor.execute(query)
            self.connection.commit()
            return True
        except:
            print("Something went wrong")
    $(".favourite-btn").on("click", function (e) {
        e.preventDefault();
        $(".badge").hide("slow");
        
        var button = "#" + $(this).attr('id');
        console.log(button);
        var data = { "TablePk":$(button).attr("data-table"), "Id":$(button).attr("data-id"), "CustomerId":$(button).attr("data-user") }
        console.log(data);
        $.ajax({
            url: "/add_favourite",
            data: data,
            type: "POST",
            success: function (response) {
                $(button).after(response);
                setTimeout(function () {
                    $(".badge").hide("slow");
                }, 3000);
            }

        });
    });

i attempted to create a function to remove the code but it didnt work

How to properly show decrypted text in bound label of FormView

I am using CryptoJS to encrypt a sensitive field and write the encrypted value to the database. This works well. But now I want to decrypt the value and display the value to a bound label within a FormView called “FvActions”, using the javascript CryptoJS.AES.decrypt method.

The Show_Decrypt function takes three parameters. Parameter 1 is the control name to get the cyphered text from and will have the decrypted value written to., Paramter 2 is the cyphered text, and parameter 3 is the cypher key to be used by CryptoJS to decrypt. Here is the javascript that’s in tags:

        function Show_Decrypt(tx, str, key) {
        var t = "#" + tx;
        var s = str.toString();
        var ky = key.toString();
      
        var decrypted = CryptoJS.AES.decrypt(s.toString(), ky.toString());
        $(t).innerHTML = decrypted;
    }

Now this is the Formview Code

Private Sub fvactions_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) Handles fvactions.ItemDataBound

    Dim lbl As Label = e.Item.FindControl("ptLabel")
        Dim epcrlbl As Label = e.Item.FindControl("Lblepcr")
    ScriptManager.RegisterStartupScript(Me, Me.GetType(), "keyLicDtlz", "Show_Decrypt('" & lbl.ClientID.ToString & "','" & lbl.Text.Trim & "','" & epcrlbl.Text.Trim & "');", True)


End Sub

I can see in the console that the parameters are being passed to the function however, following error is shown.
Uncaught SyntaxError: Invalid or unexpected token
The error seems to be generated at the ‘+’ sign in the passed in parameter #2.
Show_Decrypt(‘ContentPlaceHolder1_fvactions_ptLabel_0′,’U2FsdGVkX1+6tq8s40Z63HaZMOmvUpeYioFwZMFG9Ps=’,’CF777′);Show_Decrypt(ContentPlaceHolder1_fvactions_ptLabel_0,U2FsdGVkX1+6tq8s40Z63HaZMOmvUpeYioFwZMFG9Ps=,CF777);

I hope I’ve provided enough info. Please help.

how javascript submission function handles Checkbox in html form on google apps script?

In html data entry form, wanted to replace a Radio type with Checkbox for possible multi-selections:

<form id="ProductDetails" onsubmit="handleFormSubmit(this)">
  <p class="h4 mb-4 text-center">Restaurant Details</p>
  <div id="message"></div>
  <input type="text" id="recId" name="recId" value="" style="display: none">

  <div class="mb-1">
    <label for="name" class="form-label">Name</label>
    <input type="text" id="name" name="name" class="form-control form-control-sm" required>
  </div>

  <div class="mb-1">  //Text type
    <label for="name" class="form-label">Product Condition</label>
    <input type="text" id="name" name="name" class="form-control form-control-sm" required>
  </div>

  <div class="mb-1">
    <label class="form-label"><B>Product Condition</B></label><br>
    <div class="form-check form-check-inline">
      <input type="checkbox" id="new1" name="prodCondition" class="form-check-input" value="new1">
      <label for="new1" class="form-check-label">New1</label>
    </div>
    <div class="form-check form-check-inline">
      <input type="checkbox" id="new2" name="prodCondition" class="form-check-input" value="new2">
      <label for="new2" class="form-check-label">New2</label>
    </div>
  </div>

  <button type="submit" class="btn btn-primary">Submit</button>
</form>

//HANDLE FORM SUBMISSION, original that works
  function handleFormSubmit(formObject) {
    $('#spinnerModal').modal('show');
    google.script.run.withSuccessHandler(createTable).processForm(formObject);
    document.getElementById("ProductDetails").reset();
  }

The new submission function should include multi-selections from the Checkbox to its corresponding column/cel (hope separated with comma) in Google sheet. ChatGDP suggested this but it doesn’t work:

function handleFormSubmit(formObject) {
    // Initialize formObject.prodCondition as an array if it doesn't exist or isn't an array
    if (!Array.isArray(formObject.prodCondition)) {
        formObject.prodCondition = [];
    }
    
    console.log("Before collecting checkbox values:");
    console.log("prodCondition array length:", formObject.prodCondition.length);

    // Loop through all checked checkboxes and push their values into the array
    document.querySelectorAll('input[name="prodCondition"]:checked').forEach((checkbox) => {
        formObject.prodCondition.push(checkbox.value);
    });
    
    console.log("After collecting checkbox values:");
    console.log("prodCondition array length:", formObject.prodCondition.length);

    // Now that we've collected the checkbox values, we can proceed with the form submission
    console.log("Submitting form with the following values:");
    console.log(formObject); // Log the entire formObject to see its contents
    
    $('#spinnerModal').modal('show');
    google.script.run.withSuccessHandler(createTable).processForm(formObject);
    document.getElementById("ProductDetails").reset();
}

error from Console:

Before collecting checkbox values:
userCodeAppPanel:60 prodCondition array length: 2
userCodeAppPanel:64 Uncaught TypeError: formObject.prodCondition.push is not a function
    at userCodeAppPanel:64:34
    at NodeList.forEach (<anonymous>)
    at handleFormSubmit (userCodeAppPanel:63:70)
    at HTMLFormElement.onsubmit (userCodeAppPanel:1:8911)

Thanks for help. – Ben

tried ChatGDP but its solution didn’t work