How to get environmental variable in Javascript from Python Flask server? [duplicate]

I’m relatively new to coding. I’m trying to learn by attempting to create a simple checkout page using Stripe. For this, I’m using one of their samples which uses HTML & JS for the client side and Python (Flask) for the server.

I’m struggling with the async side of the JS code. Especially fetching environmental varialbes from the server.

I have an .env file that contains my Stripe account’s API keys. In the JS file, I need to fetch the Publishable Key from here, in order to initialize the Stripe instance and use Stripe Elements.

This seems very simple in my mind, but it is the first time I’m learning Javascript and I seem to can’t wrap my mind on asynchronous code.

My server has the following route:

@app.route('/publishable-key', methods=['GET'])
def get_stripe_public_key():
    publicKey = os.getenv('STRIPE_PUBLISHABLE_KEY')
    return jsonify(publicKey)

So I’m trying to use fetch to make a GET request to this endpoint and store the Publishable Key in a variable that I can use later on to initialize Stripe:

var stripePublicKey;

fetch('/publishable-key')
  .then(function(response) {
    return response.json();
  })
  .then(function(responseJson) {
    stripePublicKey = responseJson;
  })
  .catch(function(error) {
    console.error("Error retrieving Stripe public key: " + error);
  });

However, when trying to initialize Stripe later on in the code with: const stripe = Stripe(stripePublicKey) I always get an error as stripePublicKey is not defined.

I understand that this happens because fetch is async, and therefore, when I attempt to initialize Stripe later, stripePulicKey hasn’t been defined yet. So I tried to do something like this instead:

let stripePublicKey;

async function getStripePublicKey() {
  try {
    const response = await fetch('/publishable-key');
    const responseJson = await response.json();
    stripePublicKey = responseJson
  } catch (error) {
    console.error("Error retrieving Stripe public key: " + error);
  }
}

getStripePublicKey();

but it still doesn’t work. In this case getStripePublicKey() only returns a Promise, but not the value of it. Is there any way to store the value of the promise in a variable, in this case?

Or alternatively, what should I be doing to fetch this key?

thank you

Eslint error (xxx is not defined) using airbnb style

i’ve error with eslint when type npm run lint
the error show that

books is not defined

here my books.js

books = [];
module.exports = books;

my .eslintrc.json

{
    "env": {
        "commonjs": true,
        "es2021": true,
        "node": true
    },
    "extends": "airbnb-base",
    "overrides": [
    ],
    "parserOptions": {
        "ecmaVersion": "latest"
    },
    "rules": {
        "no-console": "off",
        "indent": [1,4],
        "no-unneeded-ternary":0,
        "linebreak-style": 0,
        "max-len":"off"
    },
}

and 1 more error that show

Expected 1 empty line after require statement not followed by another require

the error refers to that code :
const routes = require('./routes');

Why I only received first message in WebSocket connection

I have my client (React.js) – server (Nest.js) app. My goal is to use WebSocket for sending data from client to server, make some complex computations on the server side, send info about computation progress from server to client (in loop, after every iteration) and at the end, send final results to client.

My problem is, when I try to emit messages in loop, only first message is reveived by client. I simplify my code in order to check if I can emit messages in loop, but it still doesn’t work.

Here’s my client code:

const socket = io('http://localhost:5000');

socket.emit('correlate', {
    formData
});

socket.on('correlate', (d) => {
   console.log(d); // Here only first message is logged
});

And my server code:

import {
    ConnectedSocket,
    MessageBody,
    SubscribeMessage,
    WebSocketGateway,
    WebSocketServer,
} from '@nestjs/websockets';
import * as papa from 'papaparse';
import { Server } from 'socket.io';
import {AppService} from "./app.service";
import {HttpException} from "@nestjs/common";

@WebSocketGateway({
    cors: {
        origin: '*',
    },
    maxHttpBufferSize: 500 * 1024 * 1024
})
export class EventsGateway {
    constructor(
        private readonly appService: AppService
    ) {
    }

    @WebSocketServer()
    server: Server;

    @SubscribeMessage('correlate')
    async correlate(@MessageBody() data: any, @ConnectedSocket() client) {
        for(let i=0; i<10; i++) {
            client.emit('correlate', 'test' + i);
        }
    }
}

Is it possible to use iframe or embed still to link external websites in a div?

I am looking to link my github and linkedin in a div so when I click a button it opens a div with either my github or linkedin in while staying in the same url and not opening a new tab.

Ive looked around quite a bit and seen over and over to use iframe or embed, but they are all post from quite a few years go and give me the x-frame denied or do not load. I am trying to use this for my portfolio website, so I want to make it accessible to not just my local drive.

Is this still possible to do without being blocked?

Thanks -Newbee

How to check if an image exists in pages of a website?

We have a website new.mihanstore.net that is a shop.
And we have an image file mihanstore.net/pic/available.gif this image file says that product is available.

I need to check which products are available by checking which pages contain that image file.
This is product url format: new.mihanstore.net/product.php?id=*** *** can be any number from 50 to 1700.

What can I do to find which pages contain that image file? And get url of those pages saved somewhere?

I used IDM site grabber and no chances.

Loop needed for javascript function

I am using datatables and when row is clicked, I want to show details table just below.
Code works fine, but I am trying to populate the Details Table (when row clicked) with data from a field in the row which I need splitted.

Here is the code…
The var names = d[11] is the field which I need splitted then shown below.
The code below works fine, but the details table created is just dummy data…
I have not been able to create the loop to put the different ‘charges’ within the splitted string

In summary, each string which needs to be splitted, needs to be separated first by | character.
Then each ‘charge’ needs to be separated by the ^ character and put on each table cell to display it like the current dummy data.
Each record row/string to split can have a different number of charges (separated by |). So not all have the same (some have 2 charges, other 5 charges, other 10 charges)

Look forward to your comments.

code:

<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<link href="https://nightly.datatables.net/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
<script src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>
<meta Content-Type: text/html; charset=ISO-8859-1>
<title>INTERMODAL</title>
</head>
<BODY>
<style>

td.dt-control {
  background: url("https://www.datatables.net/examples/resources/details_open.png") no-repeat center center;
  cursor: pointer;
}
 
tr.dt-hasChild td.dt-control {
  background: url("https://www.datatables.net/examples/resources/details_close.png") no-repeat center center;
}


.dataTables_wrapper {float: none; text-align:left; font-family: Verdana, Geneva, Tahoma; font-size: 13px;}
</style>
<h3 style='font-family:arial,georgia,garamond,serif;'>DATABASE (06-mar-23 15:12)</h3>
<h4 style='font-family:arial,georgia,garamond,serif;'>You can search by Location Name or ZipCode</h4>
<div class='demo-html' style=width:70%>
<table id='example' width='100%' class='table compact stripe'></table>
</div>

<script>


/* Formatting function for row details - modify as you need */
function format ( d ) {

    //  HERE IS AN EXAMPLE OF WHAT THE STRING THAT NEEDS TO BE SPLITTED FIRST BY |THEN BY ^ LOOKS KIKE....
    //d[11] = 'Taxes and Duties^150^150^150^USD|Handling Charge^111^111^111^USD|Destination Charges^111^111^111^USD'
   
    var names = d[11]
    var nameArr = names.split('|');
    var names2 =nameArr[1]
    var nameArr2 = names2.split('^');    

    // LOOP NEEDED TO LOOP BY NameArr, then again by NameArr2 and add to table

    return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:750px;">'+
    
// this table creation is dummy code, which I tried several way but couldn't work it out

    
    '<tr>'+
            '<td style="width:150px;bold:true;">Charge Description</td>'+
        '<td style="width:50px;">CUR</td>'+
            '<td style="width:50px;">20GE</td>'+
        '<td style="width:50px;">40GE</td>'+
        '<td style="width:50px;">40HC</td>'+
            '<td style="width:50px;">basis</td>'+
        '</tr>'+    
        '<tr>'+         
        '<td style="width:150px;">Freight</td>'+
        '<td style="width:50px;">USD</td>'+
            '<td style="width:50px;">1500</td>'+
        '<td style="width:50px;">2500</td>'+
        '<td style="width:50px;">2500</td>'+
        '<td style="width:50px;">CNTR</td>'+
        '</tr>'+
        '<tr>'+
            '<td>Origin Charge</td>'+
        '<td style="width:50px;">USD</td>'+
            '<td>150</td>'+
            '<td>300</td>'+
            '<td>300</td>'+
        '<td style="width:50px;">CNTR</td>'+
        '</tr>'+
        '<tr>'+
            '<td>Middle Charges</td>'+
'<td style="width:50px;">EUR</td>'+
            '<td>150</td>'+
            '<td>300</td>'+
            '<td>300</td>'+     
        '<td style="width:50px;">CNTR</td>'+       
        '</tr>'+
    '<tr>'+
             '<td>Other Charges</td>'+
'<td style="width:50px;">USD</td>'+
            '<td>150</td>'+
            '<td>300</td>'+
            '<td>300</td>'+
        '<td style="width:50px;">CNTR</td>'+
        '</tr>'+
    '<tr>'+
            '<td>'+nameArr2[0]+'</td>'+
        '<td>'+nameArr2[4]+'</td>'+
            '<td>'+nameArr2[1]+'</td>'+
            '<td>'+nameArr2[2]+'</td>'+
            '<td>'+nameArr2[3]+'</td>'+
        '<td style="width:50px;">CNTR</td>'+
        '</tr>'+

    '</table>';
}      

var IntermodalSet = [
['Algeciras', '(CADIZ)', 'ES-11201;ES-11202;ES-11203;ES-11204;ES-11205;ES-11206;ES-11207;ES-11390;ES-11391', '5', 'ALGECIRAS', 'MAIN PORT', 'EUR', '€100', '€100' , '€100', '', 'Taxes and Duties^150^150^150^USD|Handling Charge^111^111^111^USD|Destination Charges^111^111^111^USD'], 
['SAN ROQUE ', '(CADIZ)', 'ES-11310;ES-11311;ES-11312;ES-11313;ES-11314;ES-11360;ES-11368;ES-11369', '15', 'ALGECIRAS', 'MAIN PORT', 'EUR', '€100', '€100' , '€100', '', 'Taxes and Duties^150^150^150^USD|Handling Charge^111^111^111^USD|Destination Charges^111^111^111^USD'],
['CASTELLAR DE LA FRONTERA', '(CADIZ)', 'ES-11350', '26', 'ALGECIRAS', 'MAIN PORT', 'EUR', '€100', '€100' , '€100', '', 'Taxes and Duties^150^150^150^USD|Handling Charge^111^111^111^USD|Destination Charges^111^111^111^USD'],
['LOS BARRIOS', '(CADIZ)', 'ES-11370;ES-11379', '21', 'ALGECIRAS', 'MAIN PORT', 'EUR','€100', '€100' , '€100', '', 'Taxes and Duties^150^150^150^USD|Handling Charge^111^111^111^USD|Destination Charges^111^111^111^USD'],
['JIMENA DE LA FRONTERA', '(CADIZ)', 'ES-11320;ES-11330;ES-11339;ES-11340', '42', 'ALGECIRAS', 'MAIN PORT', 'EUR', '€100', '€100' , '€100', '', 'Taxes and Duties^150^150^150^USD|Handling Charge^111^111^111^USD|Destination Charges^111^111^111^USD'],
['CASARES', '(MALAGA)', 'ES-29690;ES-29692', '55', 'ALGECIRAS', 'MAIN PORT', 'EUR', '€100', '€100' , '€100', '', 'Taxes and Duties^150^150^150^USD|Handling Charge^111^111^111^USD|Destination Charges^111^111^111^USD|Additional Charges^30^60^60^USD'],
];
  
    
$(document).ready(function () {
var table =$('#example').DataTable({
'bFilter':true,
'pageLength': 20, 
data: IntermodalSet,
'order': [[ 2, 'asc' ], [ 8, 'asc' ]], 
columns: [
    { title: 'LOCATION' },
    { title: '(PROVINCE)' },
    { title: 'ZIPCODE' },
    { title: 'KMS' },
    { title: 'PORT' },
    { title: 'MAIN' },
    { title: 'CUR' },
    { title: 'PRICE1' },
    { title: 'PRICE2' },
    { title: 'PRICE3' },
    { title: 'TOLL' },
    { title: 'ALLIN' },
    { title: 'Details', className: 'dt-control', orderable: false, data: null, defaultContent: '',},
    
 ],
'bAutoWidth': false, 
'dom': 'Qlfrtip',

'columnDefs': [{searchBuilder: {defaultCondition: '='},targets:[0]}],

'columnDefs': [

               {'width':'20%'  , visible: true, 'targets':[0], 'searchable': true }, 
               {'width':'100px', visible: true, 'targets':[1],  'searchable': false}, 
               {'width':'23%'  , visible: true, 'targets': [2], 'searchable': true},  
               {'width':'25px' , visible: true, 'targets':[3],  'searchable': false, className:'dt-right'},  
               {'width':'0px'  , visible: false, 'targets':[6], 'searchable': false, className:'dt-right'} , 
               {'width':'100px', visible: true,  'targets':[4], 'searchable': false} , 
               {'width':'0px'  , visible: false, 'targets':[5],  'searchable': false} , 
               {'width':'65px' , visible: true,  'targets': [7,8,9,10], 'searchable': false, className:'dt-right'},  
           {'width':'1px' , visible: false, 'targets': [11], 'searchable': false, className:'dt-right'}, 
        
            
], 
 });

 // Add event listener for opening and closing details
    $('#example tbody').on('click', 'td.dt-control', function () {
        
        var tr = $(this).closest('tr');
        var row = table.row(tr);

        if (row.child.isShown()) {
            // This row is already open - close it
            row.child.hide();
            tr.removeClass('shown');
        } else {            
            // Open this row
            row.child(format(row.data())).show();
            tr.addClass('shown');
        }
    });
   

});    

</script>

</body>
</html>

How to set manual timezone offset for specific region

As you know Node.js gets its timezone data from the ICU library, aka International Components for Unicode. recently our region (Asia/Tehran) timezone daylight rules has been changed.

console.log(new Date().toString())
Sat Mar 25 2023 17:05:18 GMT+0430

the correct output should be like this:

Sat Mar 25 2023 16:05:18 GMT+0330

I dont want to use external Date library like moment. is there any solution to override timezone offset for whole node environment? or is there any way to force nodejs to use OS timezone?

How can I add a marker to Open Layers map?

Currently building a map app. Trying all the methods I find in the internet to add a marker, still doesn’t work. Am I doing it wrong?

Here’s my Angular code:

Somehow, it’s much easier with Leaflet, but I don’t want to abandon Open Layers that early.

export class MapComponent implements OnInit{
  
  map! : Map;
  marker! :any;
  center = fromLonLat([5.5697, 50.6330]);
  iconFeature = new Feature({
    geometry : new Point(fromLonLat([5.5697, 50.6330]))
  })
  
  ngOnInit(): void {

    this.map = new Map({
      view : new View({
        center : this.center,
        zoom : 0
      }),
      layers : [

         new LayerVector({
          source : new SourceVector({
            features : [this.iconFeature]
          }),
          style : new Style({
            image : new Icon({
              anchor : [0.5, 46],
              src : '../assets/istockphoto-1153114937-2048x2048-removebg-preview.png'
            })
          })
         })
         new TileLayer({
       source : new OSM()
         })
      ],
      target :  "map"
    })   
  }

}

Responsive centering in dense grid layout with repeat auto-fit

I have a responsive grid in which each item has its own details section, which is hidden by default. A click on the item adds a class to the details section to show it.

The HTML/CSS looks roughly like this:

<div class="grid">
    <div class="item">Item 1</div>
    <div class="details">Item 1 Details</div>

    <!-- ... -->

    <div class="item">Item n</div>
    <div class="details">Item n Details</div>
</div>
.grid {
    display: grid;
    grid-auto-flow: dense;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}

.item {
    /* nothing relevant */
}

.details {
    grid-column: 1 / -1;
    max-height: 0;
    padding: 0;
    opacity: 0;
    overflow: hidden;
}

.details.selected {    
    max-height: unset;
    padding: 1rem 2rem;
    opacity: 1;
}

The details span an entire row, and the dense auto-flow allows other items to fill the gaps.

This works well and looks great with enough items.

However, let’s assume a width of 1000px, meaning 5 items can fit next to each other. If there are only 1 or 2 items, there is too much empty space to their right. I would like to center these items, but with this current CSS, the grid fills in empty cells. This seems to be caused by grid-column: 1/ -1.

So, this is how it currently looks with only 2 items:
This is how it currently looks

This is how I would like it to look:
This is how I would like it to look

In both cases, with more than 5 items it would look like this, which is fine. I’d also be fine with the bottom row being centered too, in case there’s a flex solution.
More than 5 items

How can I achieve this behavior?
It doesn’t need to be grid. Can be flex too, or really any other solution, if the dense behavior can be achieved with it.


Somewhat related question, not my focus right now, but would be nice to have:

I would like to add a fade effect to the details, which is why it uses padding, max-height and opacity instead of just setting it to display: none. If one item is selected and I select another item in the same row, both details containers are displayed for the transition duration, which causes weird shifts in the grid layout.

JS solutions would be okay. It doesn’t need to be pure CSS.

State array not rerendendering component

I have the following code :

import { useContext, useState, useEffect } from 'react';
import React from 'react';
import { RoomContext } from '../context/RoomContext';

let nextMessageID = 0

export default function Chat({roomId}) {
    const { socket } = useContext(RoomContext)

    const [messagesReceived, setMessagesReceived] = useState([]);

    useEffect(() => {
        socket.on('receive_message', (data) => {
            console.log(data.message);
            setMessagesReceived([
                ...messagesReceived,
                { id: nextMessageID++, content: data.message}
            ]);
        })
    }, [socket, messagesReceived])

    return (
        <div>
            <h1>Received messages :</h1>
            <ul>
                {messagesReceived.map(message => {
                    <li key={message.id}>{message.content}</li>
                })}
            </ul>
        </div>
    )
}

which is heavily inspired from the react documentation here : https://react.dev/learn/updating-arrays-in-state#adding-to-an-array

I can see that this code updates my state array “messagesReceived” correctly by adding a button that logs it to the console

<button onClick={() => {
    console.log(messagesReceived);
}}>Log messages</button>

but it does not update my component. How can I fix that ?

Also I’m not sure why I need to also execute my effect hook when “messagesReceived” changes but not doing so makes my array only contain the last message. I’d appreciate any explanation on this.

Thank you very much !

Websockets with many large items in memory in Cloudflare Workers

We want to use websockets with Cloudflare Workers.

For each user who connects, we would load several items from R2 to make user-specific responses via the websocket. Per user, the size of loaded items in memory would be in the region of, say, 60 MB.

Hence, my question is, how can we make that happen for thousands of users, that connect simultaneously?

Populate textboxes with Json Data returned from Spring Rest Controller @GetMapping method

Please see my below code –

Rest Controller –

@GetMapping(value = "/l/{cprimarykey}")
//VO stands for value object 
        public LaVO populate(HttpServletRequest request, @PathVariable("cprimarykey") int cprimarykey) {
            LdVO ldVO = new LdVO();
            LaVO laVO = new LaVO();
            ldVO.setcprimarykey(cprimarykey);
            try {
                List<LdVO> LdVOs = getLdManager(request).displayCL(ldVO);
                laVO.setLdVO(ldVO);
                laVO.setCreatedLeaves(LdVOs);
            } catch (ServiceException serviceException) {
                LOGGER.logError(serviceException);
            }catch(Exception e) {
                LOGGER.logError(ControllerUtility.UNEXPECTED_ERROR_MSG, e);
            }
            return laVO;
    }

This controller is returning a JSON Output with multiple variables and values accordingly

JSON Output –

{"lumpDefinitionVO":{
  "lId":null,
  "lPrimaryk":null,
  "cpId":null,
  "cpPrimaryk":1,
  "strtdt":null,
  "enddt":null,
  "errrind":"N",
  "dsname":null,
  "userId":null,
  "isList":false,
  "sUnit":"N",
  "aType":"Y",
  "minPrchaseCri":"Y",
  "refundabe":"N",
  "minLenstaycri":"N",
  "arrivlDOWcri":"Y",
  "additservice":"N",
  "yldbl":"Y",
  "minPrchaseCri":"1,3,8",
  "minLenstaycri":null,
  "arrivlDOWcri":"12345,67",
  "lPrimarykey":null,
  "lName":null,
  "lDescription":null,
  "lConfigPrimarykey":"39",
  "deletedelimtedstr":null,
  "luPrimarykey":null,
  "deleteLuPrimarykeystr":null
  
}

I want to populate these values into textboxes and checkboxes
WebPage

I have tried writing ajax code but it’s not displaying anything and it has made my minpurchasecri and minlenstaycri textbox unclickable.

Ajax code –

function getLeafCrtieria() {
    $.ajax({
        type: "GET",
        url: cpro / endpoint / leaf / leaves / +carParkPk
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        success: function(data) {
            //We will convert the data to a JSON string
            var json = JSON.stringify(data);
            //Set the value of the textbox to the JSON string
            $("#minPurchaseCri").html(data.minPurchaseCri);
            $("#minLenStayCri").html(data.minLenStayCri);
            $("#arrivalDOWCri").html(data.arrivalDOWCri);
        },
        error: function(jqXHR, textStatus, errorThrown) {
            console.log("AJAX error:" + textStatus + " - " + errorThrown);
        }
    });

Google form input (impossible to dispatch)?

How do I simulate a regular keypress of a character ‘a’ in google search input box?
So i can see the suggestions below…
I tried this:

element.dispatchEvent(new KeyboardEvent('keypress',{'key':'a'}));

but it returns ‘true’ instead of actually typing the character ‘a’

How to do it in JS?

Input of character ‘a’ into the search box of google.com in Chrome browser, latest version