How can i change the space between one column and another in the tempusdominus-bootstrap-4 library?

I am using this library tempusdominus_bootstrap4 in one of my projects. The problem however is that the calendar is not shown correctly, perhaps due to other rules that i have set. How can I change the width by ignoring any rules I have in the main style file?

In the picture i set the sideBySide option, but have the same effect even without it

enter image description here

Using jest’s fake timer breaks an already working test, why?

Following is a custom hook that I wish to test:

import { useEffect, useState } from "react";

export const useAlert = () => {
  const [alert, setAlert] = useState(null);

  useEffect(() => {
    let timerId = setTimeout(() => {
      console.log("Timeout, removing alert from DOM");
      setAlert(null);
    }, 200);

    return () => clearTimeout(timerId);
  }, [alert]);

  return {
    renderAlert: alert ? alert : null,
    setAlert,
  };
};

It simply allows a component to set alerts and clears it automatically after 300ms.

This is a working test for the above hook

import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { useAlert } from "../components/useAlert";

// jest.useFakeTimers();

function FakeComponent() {
  const { renderAlert, setAlert } = useAlert();

  return (
    <div>
      <button onClick={() => setAlert("fake alert")}>Set Alert</button>
      <p>{renderAlert}</p>
    </div>
  );
}

test("testing", async () => {
  const user = userEvent.setup();
  render(<FakeComponent />);
  const button = screen.getByRole("button", { name: /set alert/i });

  await user.click(button);
  expect(screen.getByText(/fake alert/i)).toBeInTheDocument();

  await waitFor(() => {
    expect(screen.queryByText(/fake alert/i)).not.toBeInTheDocument();
  });
});

My doubt is that I want to use jest’s fake timers inside the test but if I uncomment the line jest.useFakeTimers(), the test breaks saying that the test timed out as the default timeout value is 5000ms consider increasing the timeout if it’s a long running test.

I don’t understand why this happens, any help please!

Major size difference between Blob.size of recorded video with browser mediaRecorder and downloaded file

I have used MediaRecorder to record webcam video with very restrictive constraint of 5fps max and maximum width 720p. The Blob.size returned from MediaRecorder for 10 min video is about 500MB while downloading same file with URL.createObjectUrl is abount 5MB

Why there is such a major difference between blob and downloaded file?
How can i compress or reduce blob size since i want to upload the blob to a server.

how to draw nested/complex/multiple routes to another point in google-map-react?

I’m trying to draw multiple/nested paths between different points on the map using google-map-react.
I know how to draw simple paths but was unsuccessful in drawing the path as in the screenshot attached.

I’ve tried bypassing the multiple arrays of paths to polygon and polyline but all in vain.

my current pathHandler’s code:

    var flightPath = new google.maps.Polyline({
      path: [
        {
          lat: 14.55683,
          lng: -90.73362,
        },
        {
          lat: 6.4049,
          lng: -75.98329,
        },
        {
          lat: 51.594976,
          lng: -0.112939,
        },
        {
          lat: 46.88303,
          lng: 9.87583,
        },
      ],
      // path: ingredientMapPathLatLng,
      geodesic: true,
      strokeColor: "#F89C26",
      strokeOpacity: 1,
      strokeWeight: 3,
    });

    flightPath.setMap(google.map);
  };

What I want to draw

Pause and resume functionality for current uploading process to Azure block block storage

I am implementing functionality to upload large files (upto 10gb in azure block blob storage) via breaking them into small blocks and then committing them through commitblicklist .I have achieved this functionality in front end( article which i took for my reference is:https://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/) but now how to implement functionality of pause and resume of currently uploading file . I couldn’t find any reference to that function in any website/article. Please if anyone has any leads into it let me know.

onchange event not handling button click event

I’m working on saving textarea value on browser refresh. When there’s a change to textarea by keyboard events, the value gets stored in local storage. However, When the textarea value gets changed indirectly…like button clicks, the value doesn’t get saved. That’s the problem, So, I changed my event handler from onkeyup to onchange. Still, This remains a problem. Do anyone have a better idea for this. Here’s the code –

<textarea id="thetext" class="" value="Write some value, and off focus this input. Refresh the browser, and see the text getting saved." onchange="saveValue(this);"></textarea><br/><br/>
<button id="thebutton" onclick="change()">Change</button>
<script>
document.getElementById("thetext").value = getSavedValue("thetext");
function saveValue(e){
            var id = e.id;  
            var val = e.value;  
            localStorage.setItem(id, val);
        }
       function getSavedValue (v) {
            if (!localStorage.getItem(v)) {
                return "";
            }
            return localStorage.getItem(v);
        };
function change() {document.getElementById("thetext").value = "This value doesn't get saved if there's no keyboard action. But I want this to get saved on button click."}
</script>
<style>
textarea{height:100px;width:100%}
</style>

Can you do a recursive, memoized Fibonacci function using a js generator?

The most elegant Fibonacci function I have found isn’t even recursive:

async function* fib(x) {
  let x1 = 0;
  let x2 = 1;
  let i = 0;
  while (i < x) {
    [x1, x2] = [x2, x1 + x2];
    i += 1;
  }
  yield x1;
}

Generators are great.
That being said – they also lend themselves to recursive tasks, since you can execute them ‘lazily’.

And traditionally, Fibonacci functions are textbook examples for recursion or memoization.

This is what I came up with so far:

function* genFib (x, values = []) {
    if (x in values) return Math.max(...values)
    if (x <= 2 ) return 1

    values.push(x)

    const last = yield* genFib(x-1,values)
    const lastBefore = yield* genFib(x-2,values)
    yield last + lastBefore
}

But it doesn’t work.

So I was wondering:
How would you do a recursive, memoized Fibonacci generator function in javascript?

Adding HTMLOptGroup dynamically

I’m currently adding options to a select element dynamically like this:

   const jobs = [{...},{...},{...}];
   const jobsInput = document.querySelector(...);

   jobs.forEach(job => {
        const option = new Option(`${job.title}`, job.id);
        jobsInput.add(option, undefined);
    });

I’d like to be able to add an <optgroup> each time a property of the job object (job.companyName) changes. Pretty sure the logic behind that is easy enough, but I don’t know the syntax. Mozilla talks of an HTMLOptGroupElement, but I don’t know how to use it. When I try I get an illegal constructor error.

I’d have thought you add it like this:

const optGroup = new HTMLOptGroupElement('title');
jobsInput.add(optGroup);
optGroup.label = 'title';

but obviously I’m just making this up and it doesn’t work 🙂 I can’t find anything explaining how to implement the element. If I had to guess it’s because it’s an interface, but that still doesn’t help me

Thanks

I want to convert html table values to variable in php

I have a html table below here is some values in table i want to store all values in variable in PHP For example <tr>PAN No.ABCDE1234F I want $pan_number=”ABCDE1234F”;
Like This All Please Help Anybody Can Tell Thank You Class Of Table Is tbl

<table border="1" style="border-collapse: collapse;align:center;"`enter code here`  class="tbl">    
                    <tr><th colspan="8" class="trHead">Income Tax Department Level PAN Query</th></tr>           
                    <tr>
                        <td class="labelsMIS" colspan="8">Enter Pan No :
                        <input type="text" name="selectedPan" value="" id="selectedPan" class="fe_1" onkeyup="makeUpper(this)"/>
                       <input type="submit" value="Search" id="genRepo" class="mybtn" onclick="return showDetails();"/>
 </td>
                    </tr>
          ````<div id="hideData">        
                
  
                    <tr><td colspan="4" class="stt">PAN Alloted Date</td><td colspan="4" class="sttb">11/03/2020</td></tr>
                    <tr><td colspan="4" class="stt">PAN No.</td><td colspan="4" class="sttb">ABCDE1234F</td></tr>
                    <tr><td colspan="4" class="stt">Applicant First Name</td><td colspan="4" class="sttb">FIRST NAME</td></tr>
                    <tr><td colspan="4" class="stt">Applicant MidName</td><td colspan="4" class="sttb"></td></tr>
                    <tr><td colspan="4" class="stt">Applicant SurName</td><td colspan="4" class="sttb">LAST NAME</td></tr>
                    <tr><td colspan="4" class="stt">Father's First Name</td><td colspan="4" class="sttb">FATHER FIRST NAME</td></tr>
                    <tr><td colspan="4" class="stt">Father's MidName</td><td colspan="4" class="sttb">FATHER MIDDLE NAME</td></tr>
                    <tr><td colspan="4" class="stt">Father's SurName</td><td colspan="4" class="sttb">FATHER LAST NAME</td></tr>
                    <tr><td colspan="4" class="stt">Gender</td><td colspan="4" class="sttb">Male</td></tr>
                    <tr><td colspan="4" class="stt">Applicant Category</td><td colspan="4" class="sttb">Individual Applicant</td></tr>
                    <tr><td class="stt">Area Code</td><td class="sttb">&nbsp;LKN</td>
                    <td class="stt">Range Code</td><td class="sttb">&nbsp;72</td>
                    <td class="stt">AO Code</td><td class="sttb">&nbsp;4&nbsp;</td>
                    <td class="stt">AO Type</td><td class="sttb">&nbsp;W&nbsp;</td></tr>
            
         </div>     
             </table> ````

Add more than one values in chart

I have issue with my chart. I would like to add more than one value in my chart which is generating from table(Add gold,gas) . Can anybody gives me any ideas to solve a problem?(chartjs library)

<table id="fetch" cellspacing="5" cellpadding="8" class="table" >
            <tr>
                <th>Date</th>
                <th>Prize</th>
                
            </tr>
          
        <script type="text/javascript">
              var dane = [
                            ["2019-08-01",6.25],
                            ["2019-09-01",4.15],
                             ["2019-10-01",10.23],
                            ["2019-11-01",7.56],
                              ["2019-12-01",0.00],
                            ["2020-01-01",12.43],
                             ["2020-02-01",11.25],
                             ["2020-03-01",13.64],
                             ["2020-04-01",10.20],
                             ["2020-05-01",15.32]],
            
                    fetch = document.getElementById('fetch');
            for(var i=0; i <dane.length; i++){
                var newRow = fetch.insertRow(fetch.length);
                for(var j=0; j<dane[i].length; j++){
                    var cell = newRow.insertCell(j);
                    cell.innerHTML = dane[i][j];
                }
            }    
        </script>
<script>
       const labels = [];
  const data = {
    labels: labels,
    datasets: [{
      label: 'Oil',
      backgroundColor: 'rgb(255, 99, 132)',
      borderColor: 'rgb(255, 99, 132)',
      data: dane,
    }]
  };
 

  const config = {
    type: 'line',
    data: data,
    options: {
    },
  };
  </script>

example

How to pass parent state as a prop to a child component and modify the state using child?

  • I have a parent component which contains 4 buttons which I used to set a payment state. I want to pass the payment state to a a text field child component and also make it possible to use the text field to edit the state.
  • I have tried to use something like this how to update parent state in child component and pass to parent state back? which works but I am using formik with yup validation in parent component and it does not seem to detect the change of value from the text field child component.
  • Parent Component:
import React from "react";
import Child from 'path';

const animals = {
    {
        key:'1',
        label:'Elephant',
        isDefault:false
    },
     {
        key:'2',
        label:'Lion',
        isDefault:false
    },
     {
        key:'3',
        label:'Bear',
        isDefault:false
    },
}

const Parent = () =>{
    const defaultAnimalBtn = animals.some(choice => choice.isDefault === true);
    const [ animalState, setAnimalState ] = useState({value: defaultAnimalBtn.label});

    const handleAnimal = (index) => {

        const selectedAnimal = animalState[index];
        setAnimalState({value: selectedAnimal.label});
        
    };

    const handleAnimalChange = (event)=>{
        event.preventDefault();
        setAnimalState({value: event.target.value});
    };

    return(
        <>
            {
                animals.map(({ key, label }, index)=>(
                    <Button
                        key={key}
                        variant={`${label === animalState.value ? 'contained':'outlined'}`}
                        onClick={() => handlePayment(index)}
                    >
                        {label}
                    </Button>
                ))
            }
            <Child
                id="animal"
                name="animal"
                label="Animal"
                amount={animalState.value}
                onChange={handleAnimalChange}
            />
        </>
    );
}
  • Child Component:
import React from "react";
import { Field, useField } from 'formik';

const Child = ({ id, label, ...props })=>{

    const [ field, meta ] = useField(props);

    return(
        
        <Field component={FormControl} fullWidth sx={{ mt: 3}} variant="standard">
            <InputLabel htmlFor={id}>{label}</InputLabel>
            <Input
                id={id}
                name={props.name}
                onChange={props.onChange}
                value={props.amount}
                { ...props }
                startAdornment={<InputAdornment position="start">$</InputAdornment>}
                label={label}
            />
            {_renderHelperText()}
        </Field >
    );
}
export default Child;

Note: I am using React MUI as my component library. I am also rendering the Parent component inside a custom MultiStepForm using Formik and yup for form validation.
I followed this tutorial(Video:Formik Multi-Step Form with Material UI) to create the MultiStepForm.

How to prevent redirect loop when using chrome’s declarativeNetRequest?

I would like to create a flexible redirect rule that reorders parts of the url around. Here is the code I am using:

const allResourceTypes = ["main_frame", "sub_frame", "stylesheet", "script", "image", "font", "object", "xmlhttprequest", "ping", "csp_report", "media", "websocket", "other"];
chrome.declarativeNetRequest.updateDynamicRules({
    removeRuleIds: [1],
    addRules: [
        {
            id: 1,
            action: {
                type: "redirect",
                redirect: {
                    // regexSubstitution: "http://localhost:8080/c/b/a"
                    regexSubstitution: "http://localhost:8080/\3/\2/\1"
                }
            },
            condition: {
                resourceTypes: allResourceTypes,
                // regexFilter: "http://localhost:8080/a/b/c"
                regexFilter: "http://localhost:8080/(.*)/(.*)/(.*)"
            }
        }
    ]
})

When I browse to http://localhost:8080/a/b/c I get a “too many redirects” error, obviously because the rule is matching itself over and over. Is there any way to prevent this? It should just redirect me to http://localhost:8080/c/b/a and stop.

Puppeteer scrape value generated in javaScript

How do I scrape a value that is generated within Javascript.
I have been trying to figure this out for a few days and now I’m stuck. I have the page login stuff working.
The page looks like this in a browser and I want to extract the SoC% value and nothing else. In this example the value is 92.16%
enter image description here

This page will auto update every 10 minute.

I can see the part of the JS that returns the value but I don’t know how to scrape this value into a variable in my script.

if ('battery_soc' in d.last) {
  content+="<td>"+d.last.battery_soc+"%</td>";
}
else {
   content+="<td class='hidden-xs'>&mdash;</td>";
}

Here is the full html page if that helps.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=9;IE=10;IE=Edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta name="Description" content="Select.Live is web based SCADA for SP Pro inverters and its system" />
        <meta name="Author" content="Selctronic Australia Pty Ltd" />
        <title>Select.Live Portal | Selectronic Australia</title>
        <link href="https://fonts.googleapis.com/css?family=Titillium+Web" rel="stylesheet">
        <link href="/css/bootstrap.min.css" rel="stylesheet" />
        <link href="/css/zebra_datepicker.min.css" rel="stylesheet" />
        <link href="/css/ad-style.css" rel="stylesheet" />
        <script src="/js/jquery.min.js"></script>
        <script src="/js/bootstrap.min.js"></script>
        <script src="/js/zebra_datepicker.min.js"></script>
        <script src="/js/user_geolocation.js"></script>
        <script type="text/javascript">
         var geocodeKey = "";
        </script>
    </head>

    <body>
    <div class="ad-header">
        <button type="button" class="side-toggle left hidden-sm hidden-md hidden-lg" data-toggle="open">
            <span class="bar"></span> <span class="bar"></span> <span class="bar"></span>
        </button>
        <div class="header-logo left"></div>
        <div class="clear"></div>
    </div>

    
<div class="section">

  <div align="center" class="side-menu">
    <ul>
      <li><a href="/systems"><span class="glyphicon glyphicon-list"></span><span class="hideit">Systems</span></a></li>
      <li><a href="/myprofile"><span class="glyphicon glyphicon-user"></span><span class="hideit">My Profile</span></a></li>
      <li><a href="/logout"><span class="glyphicon glyphicon-log-out"></span><span class="hideit">Logout</span></a></li>
    </ul>
  </div>
  <script type="text/javascript">
    $(".side-menu li:nth-child(1)").addClass("active");
  </script>


  <div class="main-content container-fluid">
    <div class="row">
      <div id="map" style="height: 300px;"></div>
    </div>

    <!-- My Systems -->
    <div class="row">
      <div class="col col-md-12 main-content-padding">
        <div class="main-content-inner">
          <div class="main-content-header">
            <h3>My Systems</h3>
          </div>
          <div class="main-content-body">
            <table id="ownerSystems" class="table table-hover table-responsive table-striped">
              <thead>
                <tr>
                  <th>System Name</th>
                  <th>Status</th>
                  <th>SoC</th>
                  <th class="hidden-xs">Production</th>
                  <th class="hidden-xs">Purchased</th>
                  <th class="hidden-xs">Consumption</th>
                </tr>
              </thead>
              <tbody>
              </tbody>
            </table>
            <div align="right"> <a href="#" class="add_system btn btn-primary btn-lg"><span class="glyphicon glyphicon-plus"></span> Add a System</a> </div>
          </div>
        </div>
      </div>
    </div>

    <!-- Other systems (have installer access to these) 0 -->
    <div id="otherSystems" class="row hidden" >
<div class="col col-md-12 main-content-padding">
        <div class="main-content-inner">
          <div class="main-content-header">
            <h3>Other Systems</h3>
          </div>
          <div class="main-content-body">
            <table id="installerSystems" class="table table-hover table-responsive table-striped">
              <thead>
                <tr>
                  <th>System Name</th>
                  <th>Status</th>
                  <th>SoC</th>
                  <th class="hidden-xs">Production</th>
                  <th class="hidden-xs">Purchased</th>
                  <th class="hidden-xs">Consumption</th>
                </tr>
              </thead>
              <tbody>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>

    <div class="clear"></div>
  </div>
</div>
<div class="overlay">
  <div class="container">
    <div class="row">
      <div class="col-sm-12">
        <div class="overlay_content" style="overflow-y: auto;">
          <div class="overlay_header">
            <div class="right"> <a href="#" class="overlay_close"><span class="glyphicon glyphicon-remove"></span></a> </div>
            <div class="clearfix"></div>
          </div>
          <div class="overlay_body">
            <h3>Add a new System to your profile</h3>
            <p>Connect your Select.Live Device to your SP PRO and set it up so that it is connected to the Internet.</p>
            <p>Please find the Device ID and Serial number on the LCD screen of your Select.Live Device as shown in the example,
            and copy those details into the form below.
            </p>
            <img src="images/LCD_claim_Selectronic.png">
            <form id="claim_form" style="clear:both;">
              <div class="form-group">
                <label for="claim_code">Device ID</label>
                <input type="text" id="claim_code" class="form-control" name="devhash" placeholder="id">
              </div>
              <div class="form-group">
                <label for="claim_serial">Serial</label>
                <input type="text" id="claim_serial" class="form-control" name="serialnum" placeholder="serial number">
              </div>
              <div class="form-group">
                <label for="claim_type">Access Required</label><br>
                <label class="radio-inline"><input type="radio" name="claim_type" value="owner" checked> Owner</label>
                <label class="radio-inline"><input type="radio" name="claim_type" value="installer"> Installer</label>
              </div>
              <button type="button" id="add_claim" class="btn btn-primary" value="Add">Add System</button>
            </form>
            <br /><br /><br />
            <div id="claim_failed"></div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDl070Qq1sR3HnNr3LegChHPV8c7WWjZM4"></script>
<script type="text/javascript">
    var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 10,
        center: {lat: -37.7621346, lng: 145.3132782 },
        gestureHandling: 'cooperative',
        streetViewControl: false,
        fullscreenControl: false
    });
    var getData=function(installer) {
        $.ajax({
            url:'systems/list'+(installer ? '/installer' : '/owner'),
            type:'get',
            dataType: 'json',
            cache: false,
            success:function(data) {
                var tableID = data.installer ? 'installerSystems' : 'ownerSystems';
                // data=JSON.parse(data);
                if(data.systems.length) {
                    var content="";
                    var time_diff;
                    data.systems.forEach(function(d) {
                        content+="<tr onmouseover='zoom("+d.lat+","+d.lng+")' onmouseout='zoomout()'>";
                        content+="<td><a href='/dashboard/"+d.did+"'>"+d.name+"</a></td>";
                        content+="<td>";
                        var con_stat="<span class='glyphicon glyphicon-ok-sign color-green s-large' style='vertical-align:middle;'></span> ";
                        if (d.events) con_stat="<span class='glyphicon glyphicon-exclamation-sign color-yellow s-large' style='vertical-align:middle;'></span> ";
                        if (d.last) {
                            time_diff = d.delta_ts;
                            console.log("time_diff="+time_diff);
                            if(time_diff<60) {
                                con_stat+="<span>"+Math.round(time_diff)+" seconds ago</span>";
                            }
                            else if(time_diff<1200) {
                                con_stat+="<span>"+Math.round(time_diff/60)+" minutes ago</span>";
                            }
                            else if(time_diff<3600) {
                                con_stat="<span class='glyphicon glyphicon-remove-sign color-red s-large' style='vertical-align:middle;'></span> ";
                                con_stat+="<span>"+Math.round(time_diff/60)+" minutes ago</span>";
                            }
                            else if(time_diff<86400) {
                                con_stat="<span class='glyphicon glyphicon-remove-sign color-red s-large' style='vertical-align:middle;'></span> ";
                                con_stat+="<span>"+Math.round(time_diff/3600)+" hours ago</span>";
                            }
                            else {
                                con_stat="<span class='glyphicon glyphicon-remove-sign color-red s-large' style='vertical-align:middle;'></span> ";
                                con_stat+="<span>"+Math.round(time_diff/86400)+" days ago</span>";
                            }
                            content+=con_stat;
                            content+="</td>";
                            if ('battery_soc' in d.last) {
                                content+="<td>"+d.last.battery_soc+"%</td>";
                            }
                            else {
                                content+="<td class='hidden-xs'>&mdash;</td>";
                            }
                            if ('solar_wh_total' in d.last) {
                                content+="<td class='hidden-xs'>"+d.last.solar_wh_total.toFixed()+" kWh</td>";
                            }
                            else {
                                content+="<td class='hidden-xs'>&mdash;</td>";
                            }
                            if ('grid_in_wh_total' in d.last) {
                                content+="<td class='hidden-xs'>"+d.last.grid_in_wh_total.toFixed()+" kWh</td>";
                            }
                            else {
                                content+="<td class='hidden-xs'>&mdash;</td>";
                            }
                            if ('load_wh_total' in d.last) {
                                content+="<td class='hidden-xs'>"+d.last.load_wh_total.toFixed()+" kWh</td>";
                            }
                            else {
                                content+="<td class='hidden-xs'>&mdash;</td>";
                            }
                        }
                        else {
                            content += "<span class='glyphicon glyphicon-remove-sign color-red s-large' style='vertical-align:middle;'></span>";
                            content += "<span>No Measurements Recorded</span></td>";
                            content += "<td>&mdash;</td><td class='hidden-xs'>&mdash;</td><td class='hidden-xs'>&mdash;</td><td class='hidden-xs'>&mdash;</td>";
                        }
                        content+="</tr>";
                        var marker=new google.maps.Marker({position: {lat: d.lat, lng: d.lng}, map: map, title:d.name});
                    });
                    $('table#'+tableID+' tbody').html(content);
                    if (data.installer) $('div#otherSystems.hidden').removeClass('hidden');
                }
                else if (!data.installer) {
                    $('table#'+tableID+' tbody').html("<tr><td colspan='7'>You don't have any SP Pro Systems</td></tr>");
                }
            }
        });
    }
    var addSystem=function() {
        var serial = $('#claim_serial').val();
        var code = $('#claim_code').val();
        var access = $('input[name=claim_type]:checked').val();
        console.log('Attempting to claim with serial='+serial+', code='+code+', access='+access);
        $.ajax({
            url:'systems/claim',
            type:'post',
            data: { code: code, serial: serial, access: access },
            dataType: 'json',
            cache: false
        })
          .done(function(data) {
                  var is_installer = (data.access == 'installer') ? true : false;
                  $('.overlay').hide();
                  $('div#claim_failed').html('');
                  $('form#claim_form input').val('');
                  getData(is_installer);
                })
          .fail(function(data) {
                  if (data.responseJSON.reason.match(/No matching inverter/i)) {
                      $('div#claim_failed').html('<p>&nbsp;</p><h3 class="text-danger">Could not find a matching inverter</h3>'
                                                +'<p class="text-danger">Please check the following to fix this error:</p>'
                                                +'<ul class="text-danger" style="padding-left:20px;">'
                                                +'<li>Check that the Select.Live Device is powered on with text visible on the screen'
                                                +'<li>Check that the Select.Live Device screen shows "Cloud: OK" and an IP address'
                                                +'<li>If the Select.Live Device screen shows "Cloud: ERROR" or "Cloud: NO LAN":'
                                                +'<ul style="padding-left:50px;">'
                                                +'<li>for WiFi connection, check your WiFi router is operating correctly, and reset it if necessary'
                                                +'<li>for WiFi connection, check that there is a good WiFi signal at your Select.Live device<br>'
                                                +      '(use your mobile phone or tablet to confirm that the WiFi signal is present)'
                                                +'<li>for Ethernet connection, check that the cable is plugged in firmly at both ends;'
                                                +     ' also check using another device, e.g. a laptop computer, that the cable is working.'
                                                +'</ul></ul>'
                                                +'<p class="text-danger">If you have checked all the above and still get this error when you '
                                                +'attempt to add the system, you will need to reset your Select.Live device and start the '
                                                +'setup process again.  To reset your Select.Live Device, press and hold the black reset button '
                                                +'for 10 seconds.</p>');
                  }
                  else if (data.responseJSON.reason.match(/Access Denied/i)) {
                      $('div#claim_failed').html('<p>&nbsp;</p><h3 class="text-danger">Access denied by owner</h3>'
                                                +'<p class="text-danger">The owner of this SP PRO has not given permission for you to have access.</p>'
                                                +'<p class="text-danger">Please check you entered the correct <b>Device ID</b> and <b>Serial number</b>.'
                                                +' If you think they are correct, you will need to ask the owner of this SP PRO to grant access.</p>');
                  }
                  else if (data.responseJSON.reason.match(/No Owner/i)) {
                      $('div#claim_failed').html('<p>&nbsp;</p><h3 class="text-danger">Access Denied</h3>'
                                                +'<p class="text-danger">Installer access to this SP PRO is not allowed.</p>');
                  }
                  else {
                      $('.overlay').hide();
                      alert(data.responseJSON.reason);
                  }
                });
    };
    $('a.add_system').on('click',function(){
        $('.overlay').show();
    });
    $('a.overlay_close').on('click',function(){
        $('.overlay').hide();
    });
    $('#add_claim').on('click',addSystem);
    $('button.side-toggle').on('click',function(){
        if($(this).hasClass("openned")) {
            $(this).removeClass("openned");
            $(".side-menu").removeClass("in");
        }
        else {
            $(this).addClass("openned");
            $(".side-menu").addClass("in");
        }
    });
    var zoom=function(x,y) {
        map.panTo({lat:x,lng: y});
        map.setZoom(18);
    }
    var zoomout=function() {
        map.setZoom(10);
    }
    $(window).ready(function() {
        getData(false);
    });
    $(window).resize(function(){
    });
</script> 

    </body>
</html>

Here is my script so far

const scrapePersons = async () => {
    // import launchChrome and newPage from the browser.js file in the same directory
    const { launchChrome } = require("./browser");

    // Flow 1 => Launching chrome and opening a new tab/page
    const [newPage, exitChrome] = await launchChrome();
    const [page] = await newPage();

    const emailSelector="input[name=email]";
    const pwdSelector="input[name=pwd]";
    const btnSelector=".btn";

    // exit the function if the tab is not properly opened
    if (!page) return;

    // Flow 2 => Visiting a website's home page
    const url = "https://select.live/";
    console.log("Opening " + url);
    try {
        await page.goto(url, {
        waitUntil: "networkidle0", // wait till all network requests has been processed
        });
    } catch(e) {
        console.error("Unable to visit " + url, e);
        await exitChrome(); // close chrome on error
        return; // exiting the function
    }

    //Perform the Login
    await page.waitForSelector(emailSelector);
    console.log('40 Found name="email" on page');

    await page.waitForSelector(pwdSelector);
    console.log('50 Found name="pwd" on page');

    await page.waitForSelector(btnSelector);
    console.log('55 Found the button with class namne btn');

    await page.type(emailSelector, 'Username Goes Here');
    await page.type(pwdSelector, 'Password Goes Here');
    console.log('60 Entered email and password');

    //Click the Login Butotn
    try{
        await page.click(btnSelector);
        console.log('70 Clicked the Login Button');
    }
    catch(e){
       console.error('Unable to click the login button' + btnSelector + ' ', e)
    }

    // Find the Power Percentage Value
    

    await exitChrome(); // close chrome
    console.log('900 Exited Chrome')
};

module.exports = scrapePersons;

How to trim() keys from object in javascript?

I have object like this :

const output = 
[
  {
    Email: '[email protected]',
    KolomB: 'Haha',
    KolomC: '6',
    'Kolom D': '3.000.000',
    KolomE: '2 Jan 22'
  },
  {
    Email: '[email protected]',
    KolomB: 'Haha',
    KolomC: '6',
    'Kolom D': '3.000.000',
    KolomE: '2 Jan 22'
  }
]

I want to use trim() for removing space if occurs in object keys.

I was trying with this :

let keys = Object.keys(output[0])
      for (let i = 0; i < keys.length; i++) {
        keys[i].trim()
      }
console.log(keys)

but the result was like this :

keys = [ 'Email', 'KolomB', 'KolomC', 'Kolom D', 'KolomE' ]

The space in Kolom D is still there.

How to do solve that, where’s my mistake for processing the data ?

Please let me know if you need more information if it’s still not enough to solve that.

Confusion around reference type varaible in javascript

let user = {
  name: "John",
  age: 30,
  sayHi() {
    alert( this.name ); 
  }
};
let admin = user;
user = null; // overwrite to make things obvious
admin.sayHi(); // John

Here user variable should be a reference type variable and not primitive. So when we assign user variable to admin varaiable so we are not deeply coping the user variable. Therefore both should point to the same location in the heap memory.

So when we assign user = null. So admin variable should also be equal to null since they both should point to the same location in heap memory.

But still admin object is able to access sayHi() method. Can anyone please explain why?