Idiomatic way to compare possibly-null value with greater than

Typescript is complaining about an expression of this form:

if (foo?.length > 3) {

saying that foo might be null (ts18048) , which is true. But if it’s true, then foo?.length will evaluate to undefined, which will not be greater than 3, which is the behaviour I want.

Is there an idiomatic way to reassure TypeScript?

I can do if (foo && foo.length) but in this case, foo is quite a long expression.

Date Start + Hours

what is the problem with my code it doesn’t compute the exact hours that i put

 <label for="start">Start Date:</label>
    <input type="datetime-local" id="start" onchange="calculateEndDate()">
    
    <label for="hours">Hours:</label>
    <select id="hours" onchange="calculateEndDate()">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
      <option value="4">4</option>
      <option value="5">5</option>
    </select>
    
    <label for="end">End Date:</label>
    <input type="datetime-local" id="end" readonly>
    
    <script>
      function calculateEndDate() {
        const start = new Date(document.getElementById("start").value);
        const hours = parseInt(document.getElementById("hours").value);
        const end = new Date(start.getTime() + hours * 60 * 60 * 1000);
        document.getElementById("end").value = end.toISOString().slice(0, -8);
      }
    </script>

can anyone help me with this problem thanks

How to open a .bat file during the test execution in Cypress

I would like to open a .bat file in windows folder during the test in Cypress.

For example,

describe("open a file", () => {
  it("open a bat file", () => {
    xxx;
    xxx;
  })
})

Someone said can use

const wshShell = new ActiveXObject("WScript.Shell");
      wshShell.Run("D:\dir\user.bat"); 

but it has error here to find the ActiveXObject. How to import it? Or there is a better way to solve it.

Javascript – add string when using document.createElement

I’m creating a callout using the Apple MapKit JS using document.createElement which is working by adding elements from an array that contains the data. I would now like to add a string in front of some of the elements. Here’s how the callout currently looks:

enter image description here

I would like to add the string Phone: in front of the phone number so it would read Phone: +1 (415) 983-8030 in this example but haven’t been able to work out the correct syntax here.

Here’s the code for the callout that I’m creating:

// Landmark annotation callout delegate
var calloutDelegate = {
// Return a div element and populate it with information from the
// annotation, including a link to a review site.
calloutContentForAnnotation: function(annotation) {
    var element = document.createElement("div");
    element.className = "review-callout-content";

    var link = element.appendChild(document.createElement("a"));
    link.href = annotation.landmark.url;
    link.textContent = "website";


    var phone = element.appendChild(document.createElement("p"));
    phone.textContent = annotation.landmark.phone;

    var addLine = element.appendChild(document.createElement("br"));

    var contact = element.appendChild(document.createElement("a"));
    contact.href = annotation.landmark.url2;
    contact.textContent = "contact";

    // Add more content.
    element.style.width = "240px";
    element.style.height = "100px";
    return element;
}

I can’t work out how to add a string prior to the phone.textContent = annotation.landmark.phone; line – everything I’ve tried so far has failed.

Why is it possible to get private members and this scope in object literal? [duplicate]

Before asking questions, I just started studying JavaScript, so I am not familiar with it.

While I am studying GraphQL, I saw a article about that Object literal is approriate to singleton pattern.
But It is diffucult to understand how Object literal control the scope and obtain private members.

To make some repository by using array in javascript, I wrote code down as below:

import {Person} from "../domain/domain.js";

export default (() => {
  let people = [];
  let newID = 1;
  return {
    getNewID() {
      newID += 1;
      return newID - 1;
    },
    addPerson(name, age) {
      let person = new Person(this.getNewID(), name, age);
      people.push(person);
      return person;
    }
  ...
  }
})();

It works good, but It was hard to understand private members and this scope.

I think that the returned values should be an object literal, just as

{
  getNewID() { newID += 1; ... },
  addPerson(name, age) { let person = new Person(this.getNewID(), ... },
}

(1) In getNewID(), How can it find the newID varaible? It seems there is no variable to refer values in that function. It is difficult to understand how it works.

(2) In addPerson(name, age), If I change the function as arrow function, how it does change the scope of this and how should I change the getNewID() in addPerson() to be possible to be referred?

Display “Notify Me” button for out of stock product variants

I am using Shopify and trying to integrate a button for out of product variants

In the “Back in Stock” app they have given a code snippet to include

{% unless product.available %}
  <a href="#" class="BIS_trigger" data-product-data="{{ product | json | escape }}">
    Email when available
  </a>
{% endunless %}

The code for the template product-preorder template is below

div id="product-add">
      {% if product.variants.size > 1 %}  
        <select name="id" class="sizeDropdown">
          
          {% for variant in product.variants %}
            {% if variant.available %}
              <option value="{{ variant.id }}" data-status="">{{ variant.title }}</option>
            {% else %}
              <option value="{{ variant.id }}" data-status="sold-out">{{ variant.title }} - Sold Out</option>

           
            {% endif %}
            
          {% endfor %}
        </select>
    
      {% endif %}
    
  

      {% if section.settings.show-quantity %}
        <div class="qty-selection">
          <!--h5>{{ 'products.product.quantity' | t }}</h5-->
          <a class="down" field="quantity">-</a>
          <input min="1" type="text" name="quantity" class="quantity" value="1" />
          <a class="up" field="quantity">+</a>
        </div>
  
      {% endif %}

        </div>


 $(document).on('change',".sizeDropdown",function(e) {
    let status = $(this).find(":selected").data('status');

    if(status == "sold-out"){
      
      $("#preOrderDiv").addClass('hideThis');
      $(".qty-selection").addClass('hideThis');
      
      
    }else{
      $("#preOrderDiv").removeClass('hideThis');
      $(".qty-selection").removeClass('hideThis');    
    }
  })


I am just not sure where to include the code snippet from the app so it will show the “Notify Me” button for sold out product variants.

Any help would be greatly appreciated.

Since you can’t return html in JS, I can’t include the tag in the if block

Angular issue with setInterval

I have this code:

export class GameControlComponent {
  @Output() counterUpdated = new EventEmitter<{counter: number, type: string}>();
  @Output() counterStop = new EventEmitter();
  counterSet: any;
  counterStart: number = 0;
   
  startCount() {
    console.log('counter is ' + this.counterStart);
    this.counterSet = setInterval(this.updateCount, 1000);
    //this.updateCount();
  }

  updateCount() {
    this.counterStart += 1;
    console.log('New counter is ' + this.counterStart);
    this.counterUpdated.emit({
      counter: this.counterStart, 
      type: (this.counterStart % 2) === 0 ? 'even' : 'odd'
    });  
  }

I have a button in html component that listen to this: (click)='startCount()'.
Now, if I use this.updateCount() (commented above), everything goes fine, and each time I press the button the counterStart is updated in the method updateCount.
If use this.counterSet = setInterval(this.updateCount, 1000), counterStart in updateCount becomes NaN.

Why? Any idea?

@snak setInterval(this.updateCount.bind(this), 1000) this is working fine, even if I didn’t understand why this should be different in the two methods, because both are in the same class

How to integrate mailerlite embedded forms in nextjs statically generated site on github pages

So instead of popups, I’m integrating a mailerlite embedded form into a statically generated website hosted on github pages using Next.js. I followed the approach at How to use mailerlite popups in a Next.js application but I did notice the mailerlite snippet code in my use case is different.

The JS snippet I’m told to use:

<!-- MailerLite Universal -->
<script>
    (function(w,d,e,u,f,l,n){w[f]=w[f]||function(){(w[f].q=w[f].q||[])
    .push(arguments);},l=d.createElement(e),l.async=1,l.src=u,
    n=d.getElementsByTagName(e)[0],n.parentNode.insertBefore(l,n);})
    (window,document,'script','https://assets.mailerlite.com/js/universal.js','ml');
    ml('account', '3Y7XX4');
</script>
<!-- End MailerLite Universal -->

And the html code that needs to be embedded in one of the static website pages:

<div class="ml-embedded" data-form="mL8ZYx"></div>

I followed the process outlined in the answer to that Stackoverflow question:

  1. Add a NextJS custom document.

  2. Create a JavaScript file containing
    the MailerLite universal tag code in ./public. I put mine in
    ./public/scripts/ml.js.

  3. Add a tag loading #2 in your custom
    _document.js file:

    import Document, { Html, Head, Main, NextScript } from 'next/document'
    
    class MyDocument extends Document {
      static async getInitialProps(ctx) {
        const initialProps = await Document.getInitialProps(ctx)
        return { ...initialProps }
      }
    
      render() {
        return (
          <Html>
            <Head>
              <script async src="/scripts/ml.js"></script>
            </Head>
            <body>
              <Main />
              <NextScript />
            </body>
          </Html>
        )
      }
    }
    
    export default MyDocument
    

While the test URL mailer lite gives to test the form subscription works, the solution from the SO post does not. What needs to change?

HTML/JS form not adding up values

I cannot get my form to add up the values of the components of a necklace to display a final price on my website.

This is my code:

<div class="c-query">
 <div class="c-title">
 <h2 class="js-split">
Select diamond size</h2>
 </div>
 <div class="c-reply">
 <div style="--order:1">
 <input type="radio" name="diamondsize" id="1ct" value="450">
 <label style="display:flex; align-items:center; justify-content:center;" for="design">
1 ct  <span style="font-size:30px;">○</span></label>
 </div>
 <div style="--order:2">
 <input type="radio" name="diamondsize" id="2ct" value="1000">
 <label style="display:flex; align-items:center; justify-content:center;"for="des&amp;dev">
2 ct  <span style="font-size:40px;">○</span></label>
 </div>
 <div style="--order:3">
 <input type="radio" name="diamondsize" id="3ct" value="1500">
 <label style="display:flex; align-items:center; justify-content:center;"for="mob-des">
3 ct  <span style="font-size:50px;">○</span></label>
 </div>
 </div>
 </div>
 <div class="c-query">
 <div class="c-title">
 <h2 class="js-split">
Select length</h2>
 </div>
 <div class="c-reply">
 <div style="--order:1">
 <input type="radio" name="chainlength" id="16in" value="16in">
 <label for="range1">
16 inch: neckline</label>
 </div>
 <div style="--order:2">
 <input type="radio" name="chainlength" id="18in" value="18in">
 <label for="range2">
18 inch: collarbone</label>
 </div>
 <div style="--order:3">
 <input type="radio" name="chainlength" id="20in" value="20in">
 <label for="range3">
20 inch: collar to bust</label>
 </div>
 <div style="--order:4">
 <input type="radio" name="chainlength" id="22in" value="22in">
 <label for="range4">
22 inch: bust</label>
 </div>
 </div>
 </div>
 <div class="c-query">
 <div class="c-title">
 <h2 class="js-split">
Select metal</h2>
 </div>
 <div class="c-reply">
 <div style="--order:1">
 <input type="radio" name="Source" id="ag925" value="299">
 <label for="awww">
Silver 925</label>
 </div>
 <div style="--order:2">
 <input type="radio" name="Source" id="au18" value="2999">
 <label for="insp">
Gold 18K</label>
 </div>
 <div style="--order:3">
 <input type="radio" name="Source" id="pl950" value="1999">
 <label for="behance">
Platinum 950</label>
 </div>
 <div style="--order:4">
 <input type="radio" name="Source" id="pd950" value="2999">
 <label for="other">
Palladium 950</label>
 </div>
 </div>
 </div>

<script>
  let diamondSizeValue = 0;
  let metalValue = 0;

  document.querySelectorAll('input[name="diamondsize"]').forEach(input => {
    input.addEventListener('change', function() {
      diamondSizeValue = this.value;
      console.log('Diamond size value:', diamondSizeValue);
      updateTotalPrice();
    });
  });

  document.querySelectorAll('input[name="Source"]').forEach(input => {
    input.addEventListener('change', function() {
      metalValue = this.value;
      console.log('Metal value:', metalValue);
      updateTotalPrice();
    });
  });

  function updateTotalPrice() {
    const totalPrice = parseInt(diamondSizeValue) + parseInt(metalValue);
    document.querySelector('#total_price').innerHTML = `Total price: $${totalPrice}`;
    console.log('Total price:', totalPrice);
  }
</script>

<h1 class="js-split">
Price with shipping to <p id="country-name">your home</p></h1>
<p class="js-split">
<p id="currency-sym"></p> <h2 id="total_price"></h2>

I expected this code to display a total price adding up the two values when the radio buttons are selected, but instead it reads: “$ ” and I’m not sure how to fix it. All help is appreciated.

Open a select-option menu with another button

I have a standard html select-option (drop down) menu on my site, which I would like to ‘open’ (show options) by clicking on another button. But I have no idea how to approach this.

Is there a javascript function that can do this?

<html>

<head>

</head>

<body>

<button id="selectMenu_Controller">Open Select Menu</button>

<select id="selectMenu" name="selectMenu" class="selectMenu">
 <option value="1">Option 1</option>
 <option value="2">Option 1</option> 
 <option value="3">Option 1</option> 
 <option value="4">Option 4</option>
</select>

</body>

</html>

Is there a way to make 2 strings(such as two time strings like “4:00” and “5:00”) comparable?

I want to be able to compare 2 time string like:

"4:00" > "5:00"

and, of course, this should return false.

Is there a way to be able to map or assign these strings with values in a linear manner( like “5:00 “should have a higher value than “4:00”)? No specific date is involved.

The way I could somewhat make this work is manually put this inside a typescript enum, which automatically adds incrementing values

enum time {
"01:00",
"02:00",..
}

console.log("Value is: "+time["01:00"])
console.log("Value is: "+time["02:00"])

which returns:

Value is: 0
Value is: 1

But this method only works on pre-defined times. In the example above, time(“04:21”) will not work.