Node Js sort Manipulate

Node.js Sort and Manipulate
In the JavaScript file, you have a program that performs a GET request on the route https://coderbyte.com/api/challenges/json/wizard-list and then sort the object keys alphabetically. However, the sorting should be case-insensitive, and the original data structure should be preserved (e.g., arrays should remain arrays, objects should remain objects).

Next, remove any duplicate objects from arrays. Two objects are considered duplicates if they have the same keys and values in the same order. Although JavaScript objects don’t inherently maintain key order, key order should be considered for this challenge (using something like a Set). Only the first occurrence should be preserved when an array contains duplicate objects.

Finally, remove any object properties with all values set to an empty string, null, or undefined, and console log an array of the modified objects as a string.

Example Input:

[{“name”:”John”,”age”:30,”city”:”New York”,”country”:”USA”,”Hobbies”:[“reading”,”swimming”,”hiking”,”swimming”],”occupation”:”programmer”,”favorite_foods”:{“Breakfast”:”pancakes”,”Lunch”:””,”dinner”:”pasta”,”Snack”:””},”gear”:{“type”:””,”material”:””,”color”:null},”affiliations”:[“”,””,””],”friends”:[{“name”:”Jane”,”age”:28,”city”:”New York”,”country”:”USA”,”occupation”:null},{“name”:”Tom”,”age”:32,”city”:”London”,”country”:”UK”,”occupation”:”teacher”},{“name”:”Jane”,”age”:28,”city”:”New York”,”country”:”USA”,”occupation”:null}]}]

Example Output:

[{“age”:30,”city”:”New York”,”country”:”USA”,”favorite_foods”:{“Breakfast”:”pancakes”,”dinner”:”pasta”},”friends”:[{“age”:28,”city”:”New York”,”country”:”USA”,”name”:”Jane”},{“age”:32,”city”:”London”,”country”:”UK”,”name”:”Tom”,”occupation”:”teacher”}],”gear”:{},”Hobbies”:[“reading”,”swimming”,”hiking”],”name”:”John”,”occupation”:”programmer”}]

code is running but output is incorrect

How to Change the Hover Background Color of a Dropdown Option in Angular? [duplicate]

I’ve been struggling to find the perfect solution to change the hover background color of a dropdown option in an Angular form. By default, the dropdown options display a blue background on hover, but I need to change that color to pink.
dropdown image on hover of options

Here is the HTML structure of my form:

<div class="form-group">
  <label for="supportHierarchy">Support Hierarchy</label>
  <select id="supportHierarchy" [(ngModel)]="flag.supportHierarchy" name="supportHierarchy" class="form-control custom-select">
    <option class="custom-option" [value]="'Yes'">Yes</option>
    <option class="custom-option" [value]="'No'">No</option>
  </select>
</div>

And here is the CSS I’ve been trying:

option:hover,
option:checked,
option:active,
option:focus {
  background: linear-gradient(#5a0c6f, #5a0c6f);
}

.custom-option:hover,
.custom-option:checked,
.custom-option:active,
.custom-option:focus {
  background: linear-gradient(#5a0c6f, #5a0c6f);
}

.custom-option:hover {
  background-color: red !important;
}

Issues:
The above CSS only works if the dropdown is already open (for example, if I set the size attribute on the element to force the dropdown to stay open).
The hover effect does not seem to apply when the dropdown is closed, which is the main issue I need to solve.
I’ve tried various approaches and scoured multiple solutions online, but none seem to work for my requirement.

References:
Changing hover background color with javascript
How to change the background color of a select option on hover

Question:
How can I effectively change the background color of the dropdown options on hover, so that it displays the desired color (pink) when the dropdown is open and being interacted with? Any help or alternative approach would be appreciated!

How can I prevent Navigate forward?

I currently have a beforeunload event handler which exists when a form is dirty. it correctly blocks page a “Refresh” and navigating “Back”, but navigate “Forward” is not prevented.

window.addEventListener('beforeunload', (event) => {
    event.preventDefault();
})

This can happen if a user navigates back and starts filling out a form, I need to warn them that their data is not saved will be lost if they navigate forward again.

I thought about using popstate but that wont work either https://stackoverflow.com/a/32432366/10917416

Is there another event fired when Navigating forward?

Short lived Observables and higher-order mapping operators

I was reading this article and I can’t wrap my head around why switchMap operator is preferred over other operatros like mergeMap, concatMap, exhaustMap in case of short-lived, finite value, Observables like HTTP Request?

import { of, delay, switchMap, mergeMap, concatMap, exhaustMap } from 'rxjs';

function simulateHttp(val: any, due: number) {
  return of(val).pipe(delay(due));
}


const saveUser$ = simulateHttp("User saved", 1000);

const httpResult$ = saveUser$.pipe(
  switchMap(sourceValue => {
      console.log(sourceValue);
      return simulateHttp("Data reloaded", 2000);
      }
   )
);

httpResult$.subscribe(
  console.log,
  console.error,
  () => console.log('Completed httpResult$')
);

Unable to fetch json file via axios from local project root

I’m using React with Typescript and Webpack 5, served with webpack-dev-server. My project structure is as follows:

Project
 |-src
 | |-(All my code)
 |-app.config.json

I keep my backend URLs in a “app.config” file that’s located in the root directory and I need to read it somehow. Since it’s possible that it will change in runtime as I debug different servers, I’d like it to be loaded dynamically and I tried doing so via axios as axios.get('/app.config.json')

However, this results in a 404 Not Found error. Moreover, if I go directly by the address localhost:8080/app.config.json it will not be there either, as if not included at all when serving. Do I need to somehow include this file in webpack config?

I’d like to add that I would greatly prefer to keep the method of loading this file as axios from the root directory (not in /public, etc.) unless there’s absolutely no fix as other projects in my org follow this pattern and this particular one just doesn’t work after updating to wp5 for some reason.

litespeed cdn with quic cloud is creating errored JS code when it’s minified or cached. How do i turn this off?

I have a simple JS file that adds and removes classes to html elements. it’s working perfectly fine in my dev environment. However in production i noticed i’m getting an error in a file that litespeed created with as shown.
working js

the other image shows when it loads without litespeed there is no problem
issue js

I tried turning off JS setting but it’s not affecting the issue.
Tried flushing the cache and hard restarting on devices.

optimizedwebs.design

I removed the CDN and it works fine now, I’m wondering if it was configuration with litespeed, no docs on the matter that go into enough detail.

UseEffect in infinite loop because of dynamic url

I have looked through the topic already discussed, but I am not finding an answer for my case anywhere. I have a function:

export async function onlyMyErrorsMatter(){
  try {
    // Simulate API call
    const response = await fetch('www.some-url.com', {
      method: 'GET',
      headers: {
        'Authorization': 'Bearer invalid-token', // Simulate permission issue
      },
    });

    if (!response.ok) {
      console.error(`API Error: ${response.status} ${response.statusText}`);
      window.location.href = url; // Use the dynamic URL
     }

    }

    return await response.text();

  } catch (error) {
    console.error("Error caught in onlyMyErrorsMatter:", error);

    // Check if redirection is already done
    window.location.href = url; // Use the dynamic URL
  }
};

As you can see I use dynamic URL which comes from my env file which is provided by Vite:

const url = SOME_VITE_ENV_VAR

I have a react component, which I am using the data in.

function Component() {
  const [result, setResult] = useState("");

  useEffect(() => {
    const fetchResult = async () => {
      const result = await onlyMyErrorsMatter();
      if (result) {
        setResult(result);
      }
    };

    fetchData();
  }, []);

The problem is, when I end up at the endpoint which actually should fire an auth error and redirect, I get into the render loop, no redirect. When I however replace the url with a hardcoded one, like

const url = "www.example.com"

Loop disappears and all works as it should. But I need a dynamic URL here. Also it’s important errors are handled in the separate function, still I am only interested in redirects in special cases of API fetch problems, no other errors should fire a redirect.

Moreover, with dynamic urls my endpoint gets another addition of "/undefined", which is incredibly weird and I can’t really find where is it coming from. Seems like my env variable can be undefined? Is this causing the issue.

How do I keep the literal type information alive?

I have the following code snippet, my question is how do I keep the literal type information of knowLiteral without having to spell out the type like I am doing right now?

// @ts-check
/**
 * @typedef {Readonly<Record<string, string>>} ReadonlyStringRecord
 */

/**
 * @template {ReadonlyStringRecord} T
 */
class Main {
    /**
     * @param {T} knowLiteral
     */
    constructor(knowLiteral) {
        /**
         * @readonly
         * @type {T}
         */
        this.knowLiteral = knowLiteral;
    }
}


// how not to have to write this?
/**
 * @extends {Main<{
 *   this_is_know: '42'
 * }>}
 */
class Main2 extends Main {
    constructor() {
        const knowLiteral = /** @type {const} */ ({ 'this_is_know': '42' });
        super(knowLiteral);
    }

    testFunc() {
        //this should (and does) error.
        let x = this.knowLiteral.this_is_not_defined;
    }
}

Contact Form Error: Uncaught ReferenceError: validatetTextarea is not defined

At the bottom of the code, line 639

$('#form-submit').prop('disabled', false).attr("onclick", "window.location.href='#';");

Once # is replaced with any URL

Error appears: Uncaught ReferenceError: validatetTextarea is not defined

line 626 code:

else if (!validatetTextarea()) { e.preventDefault(); } });

Problem is, when contact form button is clicked, blank page appears with text ‘Something Went Wrong’
If # is replaced with google.com or any link, it still display the same error.


// clear form onload page
$(window).on('pageshow', function() {
  $('#contact')[0].reset();
});


$(document).ready(function() {
  // keypress enter - false
  $('#name, #email, #message').keypress(function (e) {
    let key = e.which;
    if(key == 13) {
        return false;  
    }
  });   


  //-------------------name validation-------------------


  // validate name
  $('#name').on('input blur keydown keyup change', function(){
    validateName();
  });

  let nameVal = false;

  // validation function
  function validateName() {
    let name = document.querySelector('#name');
    let regex = /^[a-zA-Zа-яА-ЯёЁіІїЇєЄ0-9.-_ ]+$/;
    let minLengthName = 2; 
    let maxLengthName  = 30; 
    let regexName = /(.)1{3}/;
    let firstChar = $("#name").val().charAt(0);

    // check max len
    $('#name').on('keydown keypress', function(e) {
      let val = $(this).val();
      if (val.length >= maxLengthName && e.keyCode !== 8 && e.keyCode !== 46) {
        e.preventDefault();
      }
    });

    // checking for an empty string
    if (name.value.length == 0) {
      $('#name').removeClass('valid');
      $('#name').removeClass('invalid');
      $('.valid_info_name').text('');
      nameVal = false;
      return false;
    }
    // check first character
    else if (!(/[a-zA-Zа-яА-ЯёЁіІїЇєЄ]/).test(firstChar)) {
      $('#name').removeClass('valid');
      $('#name').removeClass('invalid');
      $('.valid_info_name').text("The name entered is invalid. The first character must be a letter").css('color', 'red');
      $('#name').addClass('invalid'); 
      nameVal = false;
      return false;
    }
    // length check
    else if ((0 < name.value.length && name.value.length < minLengthName) || (name.value.length > maxLengthName)) {
      $('#name').removeClass('valid');
      $('#name').removeClass('invalid');
      $('.valid_info_name').text("The name entered is invalid. The name must be between " + minLengthName + " and " + maxLengthName + " characters").css('color', 'red');
      $('#name').addClass('invalid'); 
      nameVal = false;
      return false;
    }        
    // input validation no more than 3 identical characters in a row
    else if (regexName.test($('#name').val())) {
      $('#name').removeClass('valid');
      $('#name').removeClass('invalid');
      $('.valid_info_name').text("The name entered is invalid. Too many identical characters").css('color', 'red');
      $('#name').addClass('invalid'); 
      nameVal = false;
      return false;
    }
    // checking for valid characters
    else if (!regex.test($('#name').val())) {
      $('#name').removeClass('valid');
      $('#name').removeClass('invalid');
      $('.valid_info_name').text("The name entered is invalid. The name can only contain letters, numbers, spaces and symbols (._-)").css('color', 'red');
      $('#name').addClass('invalid'); 
      nameVal = false;
      return false;
    }
    else {
      $('#name').removeClass('valid');
      $('#name').removeClass('invalid');
      $('.valid_info_name').text("The entered name is valid").css('color', 'green');
      $('#name').addClass('valid');
      // check first character
      if (!(/[a-zA-Zа-яА-ЯёЁіІїЇєЄ]/).test(firstChar)) {
        $('#name').removeClass('valid');
        $('#name').removeClass('invalid');
        $('.valid_info_name').text("The name entered invalid. The first character must be a letter").css('color', 'red');
        $('#name').addClass('invalid'); 
        nameVal = false;
        return false;
      }
  
      nameVal = true;
      return true;
    }
  }


  // prohibit entering more than 3 identical characters in a row
  $(document).ready(function() {
    $('#name').on('keypress', function(e) {
      let re = /(.)1{2}/;
      if (re.test($('#name').val())) {
        e.preventDefault();
      }
    });
  });


  // first character can only be [a-zA-Zа-яА-ЯіІїЇєЄ]
  $(document).ready(function() {
    $('#name').on('keypress', function(event) {
      let inputName = $("#name");
      let valueName = inputName.val();
      let nameKey = String.fromCharCode(event.which);
      if (valueName.length === 0 && !/[a-zA-Zа-яА-ЯіІїЇєЄ]/.test(nameKey)) {
        event.preventDefault();
      }
    });
  });


  // allowed chars
  $('#name').on('keypress', function(e) {
    let allowedChars = /[a-zA-Zа-яА-ЯёЁіІїЇєЄ0-9'-._ ]/;
    let charCode = (typeof e.which === "number") ? e.which : e.keyCode;
    if (!allowedChars.test(String.fromCharCode(charCode))) {
      e.preventDefault();
    }      
  });  


  //-------------------email validation-------------------


  var minLength = 8;
  var maxLength = 50;
  var emailRegEx = /^([a-zA-Z0-9._-]+|[a-zA-Z0-9]+(?:[._-][a-zA-Z0-9]+)*)@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/;
  var input = document.querySelector('#email');

  // check max len
  $('#email').on('keydown keypress', function(e) {
      let val = $(this).val(); 
      if (val.length >= maxLength && e.keyCode !== 8 && e.keyCode !== 46) {
        e.preventDefault();
      }
  });


  // check deny char    
  function denyChar(infoCallback) {
    $('#email').on('keypress', function(event) {
      let regex = /[a-zA-Z0-9.-_@]/;
      let char = String.fromCharCode(event.which);
      if (!regex.test(char)) {
        setTimeout(function() {    
            event.preventDefault();
            $('.valid_info_email').text('Latin letters, numbers and some symbols are allowed in this field').css('color', 'red'); 
            setTimeout(function() {
              infoCallback();
            }, 1000); 
        }, 1000);
        return false;
      }
      else { 
        infoCallback();      
        return true;
      }
    });
  }


  // validate email
  $('#email').on('input keypress blur keydown keyup change', function() {
    validateEmail();
  }); 

  let emailVal = false;

  function validateEmail() {
    if (input.value.length >= minLength && input.value.length <= maxLength) {  
      let regexFirst = /^[a-zA-Z0-9]+$/;
      let regexD = /(.)1{6}/;
      // check char "@"
      if (input.value.indexOf('@') !== -1) {
        let email = $('#email').val();
        let atIndex = email.indexOf('@');
        // check dots 
        if (atIndex >= 0) {
          let domain = email.split('@')[1];
          let numDots = (domain.match(/./g) || []).length;
          // check more than 2 dots in a row after "@"
          if (/@.*?.{2,}/.test(email)) {
            $('#email').removeClass('valid');
            $('#email').removeClass('invalid');
            $('.valid_info_email').text('The address entered is invalid. Check the address you entered').css('color', 'red');
            $('#email').addClass('invalid'); 
            let infoCallback = function() {
              $('.valid_info_email').text('The address entered is invalid. Check the address you entered').css('color', 'red');
            };
            denyChar(infoCallback);
            emailVal = false;
            return false;
          }
          // check more than 2 dots after "@"
          else if (numDots >= 3) {
            $('#email').removeClass('valid');
            $('#email').removeClass('invalid');
            $('.valid_info_email').text('The address entered is invalid. Too many dots after "@"').css('color', 'red');
            $('#email').addClass('invalid'); 
            let infoCallback = function() {
              $('.valid_info_email').text('The address entered is invalid. Too many dots after "@"').css('color', 'red');
            };
            denyChar(infoCallback);
            emailVal = false;
            return false;
          }
          // check first char
          else if (!regexFirst.test($('#email').val().charAt(0))) {
            $('#email').removeClass('valid');
            $('#email').removeClass('invalid');
            $('.valid_info_email').text('The address entered is invalid. The first character can only be a letter or a number').css('color', 'red');
            $('#email').addClass('invalid'); 
            let infoCallback = function() {
              $('.valid_info_email').text('The address entered is invalid. The first character can only be a letter or a number').css('color', 'red');
            };
            denyChar(infoCallback);
            emailVal = false;
            return false;
          } 
          // check duplicates
          else if (regexD.test($('#email').val())) {
            $('#email').removeClass('valid');
            $('#email').removeClass('invalid');
            $('.valid_info_email').text('The address entered is invalid. Too many identical characters').css('color', 'red');
            $('#email').addClass('invalid'); 
            let infoCallback = function() {
              $('.valid_info_email').text('The address entered is invalid. Too many identical characters').css('color', 'red');
            };
            denyChar(infoCallback);
            emailVal = false;
            return false;
          }
          else {
            // checking emailRegEx validation
            if (emailRegEx.test($('#email').val())) {
              // check first char
              if (!regexFirst.test($('#email').val().charAt(0))) {
                $('#email').removeClass('valid');
                $('#email').removeClass('invalid');
                $('.valid_info_email').text('The address entered is invalid. The first character can only be a letter or a number').css('color', 'red');
                $('#email').addClass('invalid'); 
                let infoCallback = function() {
                  $('.valid_info_email').text('The address entered is invalid. The first character can only be a letter or a number').css('color', 'red');
                };
                denyChar(infoCallback);
                emailVal = false;
                return false;
              } 
              // check duplicates
              else if (regexD.test($('#email').val())) {
                $('#email').removeClass('valid');
                $('#email').removeClass('invalid');
                $('.valid_info_email').text('The address entered is invalid. Too many identical characters').css('color', 'red');
                $('#email').addClass('invalid'); 
                let infoCallback = function() {
                  $('.valid_info_email').text('The address entered is invalid. Too many identical characters').css('color', 'red');
                };
                denyChar(infoCallback);
                emailVal = false;
                return false;
              }
              else {
                $('#email').removeClass('valid');
                $('#email').removeClass('invalid');
                $('.valid_info_email').text('The entered address is valid').css('color', 'green');
                $('#email').addClass('valid');
                let infoCallback = function() {
                  $('.valid_info_email').text('The entered address is valid').css('color', 'green');
                };
                denyChar(infoCallback);
                emailVal = true;
                return true;     
              }
            }
            else {
              $('#email').removeClass('valid');
              $('#email').removeClass('invalid');
              $('.valid_info_email').text('The address entered is invalid').css('color', 'red');
              $('#email').addClass('invalid'); 
              let infoCallback = function() {
                $('.valid_info_email').text('The address entered is invalid').css('color', 'red');
              };
              denyChar(infoCallback);
              emailVal = false;
              return false;
            }
          }
        }     
      }   
      // check first char
      else if (!regexFirst.test($("#email").val().charAt(0))) {
        $('#email').removeClass('valid');
        $('#email').removeClass('invalid');
        $('.valid_info_email').text('The address entered is invalid. The first character can only be a letter or a number').css('color', 'red');
        $('#email').addClass('invalid'); 
        let infoCallback = function() {
          $('.valid_info_email').text('The address entered is invalid. The first character can only be a letter or a number').css('color', 'red');
        };
        denyChar(infoCallback);
        emailVal = false;
        return false;
      } 
      // check duplicates
      else if (regexD.test($('#email').val())) {
        $('#email').removeClass('valid');
        $('#email').removeClass('invalid');
        $('.valid_info_email').text('The address entered is invalid. Too many identical characters').css('color', 'red');
        $('#email').addClass('invalid'); 
        let infoCallback = function() {
          $('.valid_info_email').text('The address entered is invalid. Too many identical characters').css('color', 'red');
        };
        denyChar(infoCallback);
        emailVal = false;
        return false;
      }
      else {
        $('#email').removeClass('valid');
        $('#email').removeClass('invalid');
        $('.valid_info_email').text('The entered address is invalid, please enter "@"').css('color', 'red');
        $('#email').addClass('invalid'); 
        let infoCallback = function() {
          $('.valid_info_email').text('The entered address is invalid, please enter "@"').css('color', 'red');
        };
        denyChar(infoCallback);
        emailVal = false;
        return false;
      }   
    }           
    else if (input.value.length == 0) {
        $('#email').removeClass('valid');
        $('#email').removeClass('invalid');
        $('.valid_info_email').text('');
        let infoCallback = function() {
          $('.valid_info_email').text('');
        };
        denyChar(infoCallback);
        emailVal = false;
        return false;
    }
    else {
      if ((input.value.length > 0 && input.value.length < minLength) || input.value.length > maxLength) {
        $('#email').removeClass('valid');
        $('#email').removeClass('invalid');
        $('.valid_info_email').text('The address entered is invalid, valid from ' + minLength + ' to ' + maxLength + ' characters').css('color', 'red');
        $('#email').addClass('invalid'); 
        let infoCallback = function() {
          $('.valid_info_email').text('The address entered is invalid, valid from ' + minLength + ' to ' + maxLength + ' characters').css('color', 'red');
        };
        denyChar(infoCallback);
        let regexFirst = /^[a-zA-Z0-9]+$/;
        let regexD = /(.)1{6}/;
        // check first char
        if (!regexFirst.test($("#email").val().charAt(0))) {
          $('#email').removeClass('valid');
          $('#email').removeClass('invalid');
          $('.valid_info_email').text('The address entered is invalid. The first character can only be a letter or a number').css('color', 'red');
          $('#email').addClass('invalid'); 
          let infoCallback = function() {
            $('.valid_info_email').text('The address entered is invalid. The first character can only be a letter or a number').css('color', 'red');
          };
          denyChar(infoCallback);
          emailVal = false;
          return false;
        } 
        // check duplicate
        else if (regexD.test($('#email').val())) {
          $('#email').removeClass('valid');
          $('#email').removeClass('invalid');
          $('.valid_info_email').text('The address entered is invalid. Too many identical characters').css('color', 'red');
          $('#email').addClass('invalid'); 
          let infoCallback = function() {
            $('.valid_info_email').text('The address entered is invalid. Too many identical characters').css('color', 'red');
          };
          denyChar(infoCallback);
          emailVal = false;
          return false;
        }

        emailVal = false;
        return false;       
      }
    }
  }
  

  // input parameters
  $(document).ready(function() {    
    $('#email').on("keypress", function(event) {
      let input = $("#email");
      let value = input.val();
      let key = String.fromCharCode(event.which);
      // first character can only be [a-zA-Z0-9]
      if (value.length === 0 && !/[a-zA-Z0-9]/.test(key)) {
        event.preventDefault();
        return false;
      }
      // starting from the second, you can enter [a-zA-Z0-9.-_]
      if (value.length === 1 && !/[a-zA-Z0-9-_.]/.test(key)) {
        event.preventDefault();
        return false;
      }
      // starting from the third character, you can enter [a-zA-Z0-9.-_@]
      if (value.length >= 2 && !/[a-zA-Z0-9.-_@]/.test(key)) {
        event.preventDefault();
        return false;
      }
      // the input cannot contain two or more dots in a row (for example, '..' or '....')
      if (key === "." && value.slice(-1) === ".") {
        event.preventDefault();
        return false;
      }

      // in the input, the limit on the number of consecutive identical characters is up to 5
      $(document).ready(function() {
        $('#email').on('input', function() {
          let value = $(this).val();
          let regex = /(.)1{6}/;
          
          if (regex.test(value)) {
            $(this).val(value.slice(0, -1));
          }
        });
      });
    
      // after "@" the first character can only be entered [a-zA-Z0-9], starting from the second one can be entered [a-zA-Z0-9.-]
      $(document).ready(function() {
        $('#email').on('keypress', function(event) {
          let key = String.fromCharCode(event.which);
          let value = $(this).val();  

          // if the character "@" is entered, limit the input of the first character after "@"
          if (value.indexOf("@") !== -1 && value.indexOf(".") === -1 && value.slice(-1) === "@" && !/[a-zA-Z0-9]/.test(key)) {
            event.preventDefault();
            return false;
          }

          // after the first character after "@", allow letters, numbers, dots, hyphens, or underscores
          if (value.indexOf("@") !== -1 && value.indexOf(".", value.indexOf("@")+2) !== -1 && /[a-zA-Z0-9.-_]/.test(value.slice(-1)) && !/[a-zA-Z0-9.-_]/.test(key)) {
            event.preventDefault();
            return false;
          }

          // if a dog is found and the entered period is found after it, only the characters [a-zA-Z0-9.-_] are allowed
          if (value.indexOf("@") !== -1 && value.indexOf(".") !== -1 && value.indexOf(".") > value.indexOf("@") && !/[a-zA-Z0-9.-_]/.test(key)) {
            event.preventDefault();
            return false;
          }
          
          // if a dog is found, only 2 dots can be entered after it
          if (value.indexOf("@") !== -1 && value.indexOf(".", value.indexOf("@")+1) !== -1 && value.indexOf(".", value.indexOf("@")+1) !== value.lastIndexOf(".") && value.indexOf(".", value.indexOf("@")+1) !== -1 && !/[a-zA-Z]/.test(key)) {
            event.preventDefault();
            // if a point is found, allow input /[a-zA-Z0-9.-_]/
            if (value.indexOf("@") !== -1 && value.indexOf(".", value.indexOf("@")+1) !== -1 && value.indexOf(".", value.indexOf("@")+1) === value.lastIndexOf(".") && !/[a-zA-Z0-9.-_]/.test(key)) {
              event.preventDefault();    
              return false;
            }
            // if the second entered point is found after the dog, only characters [a-zA-Z] are allowed
            if (value.indexOf("@") !== -1 && value.indexOf(".", value.indexOf("@")) !== -1 && value.indexOf(".", value.indexOf(".", value.indexOf("@")+1)) !== -1 && !/[a-zA-Z]/.test(key)) {
              event.preventDefault();
              return false;
            }
                       
            return false;
          }     
        });
      });    
              
      
      // allow enter "@" only one times
      $(document).ready(function() {
        let inputField = $('#email');
        inputField.on('keypress', function(e) {
          let currentValue = $(this).val();
          if (e.which === 64 && currentValue.indexOf('@') !== -1) {
            e.preventDefault();
          }
        });
      });
    

      // allowed chars
      $('#email').on('keypress', function(e) {
          let allowedChars = /[a-zA-Z0-9._@-]/;
          let charCode = (typeof e.which === "number") ? e.which : e.keyCode;
          if (!allowedChars.test(String.fromCharCode(charCode))) {
          e.preventDefault();
          }      
      });  
    });

  });

  
  //-------------------textarea validation-------------------
  

  // validate textarea
  $('#message').on('blur keydown keyup change', function() {
    validateTextarea();
  });

  let textareaVal = false;

  // validation function of Textarea
  function validateTextarea() {
    let message = $('#message').val();
    let regex_textarea = /^[a-zA-Zа-яА-ЯёЁіІїЇєЄ0-9., -'_]+$/;
    let maxLengthMessage = 500;

    $('#message').on('keydown keypress', function(e) {
      let val = $(this).val();
      if (val.length >= maxLengthMessage && e.keyCode !== 8 && e.keyCode !== 46) {
        e.preventDefault();
      }
    });

    // checking for an empty field
    if (message == 0) {
      $('#message').removeClass('valid');
      $('#message').removeClass('invalid');
      $('.valid_info_message').text("");
      textareaVal = false;
      return false;
    } 
    // if the field contains illegal characters
    else if (!regex_textarea.test(message)) {
      $('#message').removeClass('valid');
      $('#message').removeClass('invalid');
      $('.valid_info_message').text("Invalid characters entered").css('color', 'red');
      $('#message').addClass('invalid'); 
      textareaVal = false;
      return false;
    } 
    // if the field contains more than 500 characters
    else if (message.length > 500) {
      $('#message').removeClass('valid');
      $('#message').removeClass('invalid');
      $('.valid_info_message').text("The maximum message length is 500 characters").css('color', 'red');
      $('#message').addClass('invalid'); 
      textareaVal = false;
      return false;
    } 
    else { 
      $('#message').removeClass('valid');
      $('#message').removeClass('invalid');
      $('.valid_info_message').text("The entered message is valid").css('color', 'green');
      $('#message').addClass('valid');
      textareaVal = true;
      return true;
    }

  }


  // allowed characters
  $('#message').on('keypress', function(e) {
    let allowedChars = /^[a-zA-Zа-яА-ЯёЁіІїЇєЄ0-9., -'_]/;
    let charCode = (typeof e.which === "number") ? e.which : e.keyCode;
    if (!allowedChars.test(String.fromCharCode(charCode))) {
      e.preventDefault();
    }      
  }); 


  // -----------------------------------------------------------
  
  // remove emoji
  $(document).ready(function(){
    var nameRegex = /^[a-zA-Zа-яА-ЯёЁіІїЇєЄ0-9.-_ ]+$/;
    var emailRegex = /^[a-zA-Z0-9._@-]+$/;
    var messageRegex = /^[a-zA-Zа-яА-ЯёЁіІїЇєЄ0-9., -'_]+$/;
  
    $('#name').on('input keydown keyup change', function() {
      removeInvalidChars($(this), nameRegex);
    });
  
    $('#email').on('input keydown keyup change', function() {
      removeInvalidChars($(this), emailRegex);
    });
  
    $('#message').on('input keydown keyup change', function() {
      removeInvalidChars($(this), messageRegex);
    });
  
    function removeInvalidChars(input, regex) {
      var str = input.val();
      str = str.replace(/[^ws.-@а-яА-ЯёЁіІїЇєЄ,']/g, '');
      input.val(str);
    }
  });
  
  // -----------------------------------------------------------
  
  // event handler on form submission
  $('form').on('submit', function(e) {
    // cancel form submission if validation fails
    if (!validateName()) {
      e.preventDefault();
    }
    else if (!validateEmail()) {
      e.preventDefault(); 
    }
    else if (!validatetTextarea()) {
      e.preventDefault(); 
    }   
  });
  

  // form validation
  $('#contact').on('input blur keyup change', function() {
    validateEmail();
    validateName();
    validateTextarea();

    if (emailVal === true && nameVal === true && textareaVal === true) {
      $('#form-submit').prop('disabled', false).attr("onclick", "window.location.href='#';"); 

      $('#name, #email, #message').keypress(function(e) {
        if (emailVal === true && nameVal === true && textareaVal === true) {
          var key = e.which;
          if(key == 13) {
            $('#form-submit').click();
            return false;  
          }
        }
      });   
      return true;
    } 
    else {
      $('#form-submit').prop('disabled', true);

      $('#name, #email, #message').keypress(function(e) {
        let key = e.which;
        if(key == 13) {
            return false;  
        }
      });  
      
      return false;
    }  
  });
  
});    ````


I changed return false/true on few locations, but nothing helped. Reverted it to the original in this post. Can't understand why form won't work. Where is the error? Thanks.

Apps Script to change cell on other 2 sheets, base on changed on first sheet

i have these column that i want to work on
i have initial list of name on ItemDB!D3:D
and these 2 column Purchasing!E2:E and Sale!G14:G that have part of the name from ItemDB!D3:D, also on Purchasing!E2:E and Sale!G14:G i use data validation from list of ItemDB!D3:D.
Then i make a button with the name of updateValues, and i try to make a apps script so when i clicked the button, it will check cell that change on ItemDB!D3:D then after find the change, it will also change the cell on Purchasing!E2:E and Sale!G14:G

the problem here are it run fine on small dataset, but when i applied to larger dataset, it not working properly. So can anyone help me to give some input what i need to do now?
here are some of the example and the code i use.

example:

ItemDB!D3:D

Apple –> changed to AppleX

Lemon

Banana

.

Purchasing!E2:E

Apple –> changed to AppleX when Apple on ItemDB!D3:D changed

Apple –> changed to AppleX when Apple on ItemDB!D3:D changed

Lemon

.

Sale!G14:G

Banana

Lemon

Apple –> changed to AppleX when Apple on ItemDB!D3:D changed

function updateValues() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const itemDBSheet = ss.getSheetByName('ItemDB');
  const purchasingSheet = ss.getSheetByName('Purchasing');
  const saleSheet = ss.getSheetByName('Sale');

  // Get current values from ItemDB!D3:D
  const currentRange = itemDBSheet.getRange('D3:D' + itemDBSheet.getLastRow());
  const currentValues = currentRange.getValues().flat();

  // Load previous values from Script Properties (or initialize if not set)
  const scriptProperties = PropertiesService.getScriptProperties();
  let previousValuesString = scriptProperties.getProperty('previousValues') || '';

  // Convert the string back to an array
  let previousValues = previousValuesString ? previousValuesString.split(',') : [];

  // Initialize previousValues with current values if empty
  if (previousValues.length === 0) {
    previousValues = [...currentValues];
  }

  // Get full ranges for Purchasing and Sale sheets
  const purchasingRange = purchasingSheet.getRange(2, 5, purchasingSheet.getLastRow() - 1, 1);
  const saleRange = saleSheet.getRange(14, 7, saleSheet.getLastRow() - 13, 1);

  const purchasingValues = purchasingRange.getValues();
  const saleValues = saleRange.getValues();

  // Create maps for quick lookups
  const purchasingMap = new Map(purchasingValues.map((value, index) => [value[0], index]));
  const saleMap = new Map(saleValues.map((value, index) => [value[0], index]));

  let changesMade = false;

  // Compare current and previous values
  for (let i = 0; i < currentValues.length; i++) {
    const currentValue = currentValues[i];
    const previousValue = previousValues[i] || '';

    if (currentValue !== previousValue) {
      // Update Purchasing sheet
      if (purchasingMap.has(previousValue)) {
        const rowIndex = purchasingMap.get(previousValue);
        purchasingValues[rowIndex][0] = currentValue;
        changesMade = true;
      }

      // Update Sale sheet
      if (saleMap.has(previousValue)) {
        const rowIndex = saleMap.get(previousValue);
        saleValues[rowIndex][0] = currentValue;
        changesMade = true;
      }

      // Update the previousValues array with the current value
      previousValues[i] = currentValue;
    }
  }

  // Apply the changes to the sheets if any changes were made
  if (changesMade) {
    purchasingRange.setValues(purchasingValues);
    saleRange.setValues(saleValues);
  }

  // Convert the updated previousValues array back to a string and store it in Script Properties
  scriptProperties.setProperty('previousValues', previousValues.join(','));
}

StyledMapType of terrain map type, and others?

As far as I can tell, a google.maps.StyledMapType is (at least by default) a styled version of the default roadmap (google.maps.MapTypeId.ROADMAP). Is there any way to create a StyledMapType based on another map type, such as the terrain map (google.maps.MapTypeId.TERRAIN)?

Context

I am insisting on a StyledMapType here because—as far as I can tell—other approaches will not work for my application.

Have to be able to turn style on and off on the fly

Whether or not this custom style applies depends on my application state. Any solution that permanently adjusts the terrain map, or requires creating a new map for the new style, is a no-go for me.

Cannot use the existing map type with an inline style

My map uses google.maps.AdvancedMarkerElement, which has a requirement that the map has a mapId from the Google Cloud Console.

Having a mapId causes map.setOptions({ styles: /*…*/ }) to fail, issuing a warning to the browser console explaining that it doesn’t work.

Cannot use Cloud-based styling

Having a mapId is supposed to be for using the Google Cloud Console to control styling—that’s why inline styles don’t work when you have one. But I can’t use that, because the Google account is owned by the client, and us contractors don’t have access. The client set up the mapId for me, but they are not willing to give us direct access, or figure out importing the styling themselves.

Beyond that, as far as I can tell from the documentation—which is terrible so I could be wrong—it doesn’t seem like this kind of styling is something you can change on the fly. So, for example, I could style the roadmap, but then the roadmap would always have that style. So even if I fought with the client to get access or convince them to import some styles for us, it doesn’t seem like it would solve things.

Example

const map = new google.maps.Map(containerElement, {
    mapId: 'some_map_id',
    mapTypeId: google.maps.MapTypeId.ROADMAP,
});

// Grayscale roadmap — WORKS
const grayscaleRoadmap = new google.maps.StyledMapType(
    [{ stylers: [{ saturation: '-100' }] }],
    { name: 'Grayscale Roadmap' },
);
map.mapTypes.set('grayscale_roadmap', grayscaleRoadmap);
if (shouldBeGrayscale && map.getMapTypeId() === google.maps.MapTypeId.ROADMAP) {
    map.setMapTypeId('grayscale_roadmap');
}

// Grayscale terrain map — DOES NOT WORK, exactly the same as the grayscale roadmap
const grayscaleTerrain = new google.maps.StyledMapType( // do I need to do something different here?
    [{ stylers: [{ saturation: '-100' }] }],
    { name: 'Grayscale Terrain Map' },
);
map.mapTypes.set('grayscale_terrain', grayscaleTerrain);
if (shouldBeGrayscale && map.getMapTypeId() === google.maps.MapTypeId.TERRAIN) {
    map.setMapTypeId('grayscale_terrain');
}

How to ignore single quotes in the validator.js isAlphanumeric function

I am trying to validate a string using express validator, specifically with the function isAlphanumeric, but I would like to add space, dash, and single quote as characters to accept.

Here is my code:

body("title")
    .trim()
    .isLength({ min: 1 })
    .escape()
    .withMessage("Le champ titre est obligatoire.")
    .isAlphanumeric("fr-FR", { ignore: " -'" })
    .withMessage("Le champ titre contient des caractères non autorisés."),

With this code, I can type in strings with dashes and spaces in the HTML form without them being rejected, but if I add a single quote, I get a validation error with the last “withMessage” error. The string does not pass the isAlphanumeric test.

I thought of a character escaping problem inside of the “ignore” string, so I have tried the following:

  • ” -‘”
  • ” -”'” (as seen here on another question) – quote backslash quote quote
  • / -‘/ (using RegExp)
  • /[ -‘]/ (and every combination with and [], I think)

I cannot find the proper way to include the single quote in the “ignore” option of the isAlphanumeric validator, and I feel like I am trying anything randomly until I find the right way to do it, which is not really satisfying. As everything works fine with other characters, I still think of a character escaping problem but I cannot figure out which one.

I am sure that ignoring single quotes has already been done, but I could not find the answer on Google or Stack Overflow, so I guess it was time I signed up on this site to ask this question by myself.
I would like a “regexp-free” solution if it exists, as it must be doable with the string version (I still need to improve my regexp skill).

Vite chrome-ext issue

My stack react, vite, ts. The only thing is, I changed the manifest a little bit. I need react (other scripts) to load as soon as I click on an extension, i.e. when I click on an extension the react app should appear.

//vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';
import svgr from 'vite-plugin-svgr';
import { TanStackRouterVite } from '@tanstack/router-plugin/vite';

export default defineConfig({
  plugins: [react(), svgr(), TanStackRouterVite()],
  server: {
    watch: {
      usePolling: true,
    },
    host: true,
    strictPort: true,
    port: 3001,
  },
  build: {
    rollupOptions: {
      input: {
        content: 'src/content.tsx',
        background: 'src/background.ts',
      },
      output: {
        entryFileNames: 'assets/[name].js',
        assetFileNames: 'assets/[name].[ext]',
      },
    },
    outDir: 'dist',
    emptyOutDir: true,
    assetsDir: '.',
    sourcemap: false,
  },
});

// manifest.json
{
  "manifest_version": 3,
  "name": "Test",
  "version": "1.0",
  "action": { "default_icon": {} },
  "permissions": ["activeTab", "scripting"],
  "background": {
    "service_worker": "assets/background.js"
  },
  "icons": {
    "16": "favicon-16x16.png",
    "32": "favicon-32x32.png",
    "48": "icon-48x48.png",
    "128": "icon-128x128.png"
  },
  "web_accessible_resources": [
    {
      "resources": [
        "assets/content.css",
        "favicon-16x16.png",
        "favicon-32x32.png",
        "icon-48x48.png",
        "icon-128x128.png"
      ],
      "matches": []
    }
  ]
}
//background.ts
chrome.action.onClicked.addListener((tab) => {
  if (!tab.id) return;

  chrome.scripting.executeScript({
    target: { tabId: tab.id },
    files: ['assets/content.js'],
  });
});

I want to make a build for chrome extension, but the browser writes error(s) – Uncaught SyntaxError: Unexpected token ‘export’. It’s like it’s not transpiling the code correctly, I don’t know