Puppeteer – check if a html element is visible ‘on-screen’

Hello

My goal is to imitate human behaviour and make sure that only scrolled-to links/hyperlinks are clicked with puppeteer. Just like a human would click only the hyperlinks they can see on the screen

My Specs

Puppeteer: 22.13.1
Puppeteer-extra: 3.3.6
NodeJS: 20.14.11
TypeScript: 5.5.3

Pseudo Code Example

if (element.isVisibleOnScreenAndScrolledTo()) {element.click()}

More Details

I am scrolling through a website using puppeteer and want to open only visible links like if a user was using the page

It doesn’t matter if the answer is in JS or TS as long as it’s correct.

I’ve Tried (to no avail)

  • Googled about this for 15 minutes
  • Read elementhandle api docs thrice
  • Discovered the scrollIntoView() method but it’s not exactly what I am looking for
  • Read the Frame class api docs
  • Implemented my temporary solution (read below)

Temporary Solution

For now I will do it the other way around:

  1. Get a list of all the elements I want to click
  2. Scroll to them using the scrollIntoView() method
  3. Click them

This solution does not suit me because I want to first scroll (‘explore’ new hyperlinks) then click them.

Clarification

Scrolling first and clicking only the ‘explored’ hyperlinks will inevetably skip some of the hyperlinks in the process. However I am okay with that

Answer expectation

All I expect from an answer is a way to check if a html element/ hyperlink is visible (If puppeteer scrolled down the page enough to be able to see it)

Monitor an images folder to get a live local html/javascript gallery

I need to get a live image gallery based on a permanently monitored folder. It will run on my local computer. Here is how it should work:

  • If an image file appears, it is automatically added to the gallery
  • If an image file disappear, it is automatically removed from the gallery
  • If an image file is modified, the image has to be refreshed in the gallery
  • Do not use of an automatique page refresh: Each image have to be clicked to be enlarged in the same full window
  • And, as said above, each image have to be clickable to be zoomed full size from the origin, in the same window (like here for sample: https://www.lightgalleryjs.com/demos/zoom-from-origin/)

Based on some samples founded in Stackoverflow, I’ve done that. But it doesn’t refresh img. And if I well understand the code, it will not remove an image if the file disappear. What do you think? (As you can see I’m not very used with new technologies… I’m an old html/css webmaster)

<!doctype html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <title>Titre de la page</title>
<link rel="stylesheet" href="style.css">

<script>

function refresh(node)
{
   var times = 1000; // gap in Milli Seconds;

   (function startRefresh()
   {
      var address;
      if(node.src.indexOf('?')>-1)
       address = node.src.split('?')[0];
      else 
       address = node.src;
      node.src = address+"?time="+new Date().getTime();

      setTimeout(startRefresh,times);
   })();

}

window.onload = function()
{
  var node = document.getElementsByClassName('img');
  refresh(node);
  // you can refresh as many images you want just repeat above steps
}

</script>

</head>
<body>

<div class="ajax-inserted-content">
    <section class="section gallery grid layout-4-col">
        <div class="container">
            <div class="row" id='gallery-items'>
            </div>
        </div>
    </section>
</div>
<script>
function doPortItem(n) {
    let img = document.createElement('img');
    img.src = './imgportfolio/test-' + n + '.jpg';
    img.addEventListener('load', () => {
        let div = `<div class="col-3 col-lg-4 col-md-6 col-sm-12">
     <div class="gallery-item">
       <div class="gallery-img">
         <img class="img" data-lazy-image data-src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzIDIiPjwvc3ZnPg==" src="${img.src}" alt="Demo img"> 
       </div>
     </div>
   </div>`;
        document.querySelector('#gallery-items').innerHTML += div;
        doPortItem(++n)
    })
}
doPortItem(1)
</script>

</body>
</html>

JavaScript compatible libraries for evaluating APL [closed]

Are there any JavaScript compatible libraries for evaluating APL? I’m hoping to find something that would let me include tiny APL snippets among JavaScript using tagged template literals. Consider the following code example. The tag function apl is responsible for providing an interface for calling the embedded APL code.

const occurenceRatio = apl`(+/=)÷(⍴⊢)`

I was able to find a few projects related to APL web integrations. However, none of them seemed to be focused on running APL locally without ahead of time compilation. Thus I don’t think they would be well suited for this purpose.

Is it possible to scrape a single text field from an external website URL & display that text on a WordPress site?

For context: I’d like to be able to scrape ‘Population’ data from publicly available Australian government census information for each suburb, and have that number display dynamically in a text field on a separate WordPress domain.

So rather than having to manually put in the population for every single suburb, simply refer to the appropriate data for that suburb.

E.g: rather than

Population: 12,658 (manually typed), something like

Population: [abs_population]

An example page from the gov’t website in question: https://abs.gov.au/census/find-census-data/quickstats/2021/SAL13297

That ‘People’ number field in bold at the top.

Is this possible if it’s not wrapped in any specific class etc?

Have tried searching & experimenting with existing WordPress plugins, but most of those are based around importing existing Google Sheets/CSV files that already contain the information centralised, rather than scraping an external site via a script dynamically.

How To Handle Lost Data Packets In TCP?

What are the proper ways to handle the TCP data packets lost during the transit?

I’m developing an instant messaging application with real-time chat feature. I rely mainly on TCP (Transmission Control Protocol) for instant messaging feature. However, even though my connection quality is good, when I send message to the receiver, some of the messages are lost during the transit. Here’s my Node.js code that utilizes net module for TCP protocol:

const net = require("net");
const clients = [];

net.createServer((socket) => {
    clients.push(socket);

    socket.on("close", () => clients.splice(clients.indexOf(socket), 1));

    socket.on("data", (data) => {
        clients.forEach((client) => client.write(JSON.parse(data.toString()).message);
    });
}).listen(8000, "185.255.95.248", () => console.log("TCP instance is running..."));

Any help would be appreciated. Thanks, regards…

Javascript and model app question regarding and If and And statement

my If/And Javascript code (connected to a model driven app form) which checks for the value selected in a dropdown column (a choice column) and also checks another column to see if the value in that column is greater than 10. If value is greater than 10 in column b and choice column(a) has value 1 selected (which is “Fresno”), then code is supposed to execute the next step. However, it’s not working.

function Logic5(executionContext)
{

    var formContext = executionContext.getFormContext();
    var active = formContext.getAttribute("cr166_fo").getValue();
    var value = formContext.getAttribute("cr166_moneyseized").getValue();
    if(active==1 && value > 10)
        {}
}

Tailwind gradient not working when using template literals

I’m trying to adjust the following gradient:

bg-gradient-to-r from-rose-400 to-rose-50 from-${percentage}% to-${percentage}%

where percentage is a changing variable.
When I replace the template literals and just write this:

bg-gradient-to-r from-rose-400 to-rose-50 from-10% to-10%

it works great, but then it’s not adaptive.

I looked in the devtools, and the div does seem to get the class (the class is identical in both cases), but the selector doesn’t seem to apply on it. (the class looks identical, but looking at the “styles” tab in devtools shows it’s not catching the right selector.

could it be the way tailwind works that doesn’t allow this? if so, what can I do to bypass that?

DOMException Error When Decoding Audio Data from .mov File in React App

I am working on a React application where I need to extract audio from a video file uploaded by the user. The video file is in .mov format, uploaded from iOS or macOS devices. However, I am encountering a DOMException error during the audio decoding process.

this is the image of the error i am getting

Here is my code:

const extractAudioFromVideo = async (file) => {
  return new Promise((resolve, reject) => {
    const audioContext = new (window.AudioContext || window.webkitAudioContext)();
    const reader = new FileReader();

    reader.onload = function () {
      const arrayBuffer = reader.result;
      console.log("File read successfully. Decoding audio data...");

      audioContext.decodeAudioData(arrayBuffer).then((decodedAudioData) => {
        console.log("Audio data decoded. Rendering offline audio context...");
        const offlineAudioContext = new OfflineAudioContext(
          decodedAudioData.numberOfChannels,
          decodedAudioData.duration * decodedAudioData.sampleRate,
          decodedAudioData.sampleRate
        );
        const soundSource = offlineAudioContext.createBufferSource();
        soundSource.buffer = decodedAudioData;
        soundSource.connect(offlineAudioContext.destination);
        soundSource.start();

        offlineAudioContext.startRendering().then((renderedBuffer) => {
          console.log("Offline audio rendering completed.");
          const wavBlob = audioBufferToWav(renderedBuffer);
          resolve(wavBlob);
        }).catch((err) => {
          console.error('Error during offline audio rendering:', err);
          reject(err);
        });
      }).catch((err) => {
        console.error('Error decoding audio data:', err); // This is where the DOMException is logged
        reject(err);
      });
    };

    reader.onerror = function (err) {
      console.error('Error reading file:', err);
      reject(err);
    };

    reader.readAsArrayBuffer(file);
  });
};

What I Have Tried:

  1. Testing with Different Files:

    • The code works perfectly with .mp4 files, but consistently fails with .mov files.
  2. Checking Audio Codec:

    • I have verified that the .mov file uses a common audio codec (AAC).

How can I ensure the image fits within a container without overlapping the input field, regardless of its size?

Description

Currently, if the user captures an image and pastes it, the image in the img-preview-container overlaps the userInput. This behavior can be explicitly observed when the user captures and pastes an image that has a longer height than its width to the chatbot.

Expected Behavior

Make the image shown inside the img-preview-container by clipping the image content at the border of the container element, regardless of the size of the image that the user pasted with using the ‘ctrl’ and ‘v’ keys.

Current Behavior

Currently, if the user utilizes the PrtSc key to capture the specific part of the screen and paste it in the text input field with ctrl+v, the pasted image overlaps the text input field.

img1

const promptInput = document.getElementById("userInput");
const chatContainer = document.getElementById("chatContainer");
const typingIndicator = document.getElementById("typingIndicator");
const sidebar = document.getElementById("sidebar");
const sidebarContent = document.getElementById("sidebarContent");
const imageContainer = document.getElementById("imageContainer");

async function sendMessage() {
  const prompt = promptInput.value.trim();
  if (!prompt && imageContainer.children.length === 0) {
    alert("Please enter a message or add an image.");  // Browser pop up message
    return;
  }

  // Collect image data
  const images = Array.from(imageContainer.querySelectorAll('.img-preview'))
    .map(img => img.src.split(',')[1]); // Extract base64 data

  addMessage(prompt, 'user', images);
  promptInput.value = "";

  showTypingIndicator();

  const generatedText = await generateText(prompt, images);
  addMessage(generatedText, 'bot');

  hideTypingIndicator();
  //clearImagePreviews(); Add this code if you want the image in the imageContainer disappear if the user sends the image.
}

async function generateText(prompt, images) {
  try {
    const response = await fetch("http://127.0.0.1:5000/generate_text_stream", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ prompt, images }),
    });

    if (!response.ok) {
      console.error("Error:", response.statusText);
      return "Error occurred while generating response.";
    }

    const reader = response.body.getReader();
    const decoder = new TextDecoder();
    let isFinished = false;
    let generatedTextContent = "";

    while (!isFinished) {
      const { done, value } = await reader.read();
      if (done) {
        isFinished = true;
        break;
      }
      generatedTextContent += decoder.decode(value, { stream: true });
    }

    return generatedTextContent;
  } catch (error) {
    console.error("Error:", error);
    return "An error occurred.";
  }
}

function addMessage(text, type, images = []) {
  const messageDiv = document.createElement("div");
  messageDiv.className = `message ${type}`;

  const messageContent = document.createElement("div");
  messageContent.className = "message-bubble fadeIn";
  messageContent.innerHTML = `<p>${text}</p>`;

  images.forEach(src => {
    const img = document.createElement("img");
    img.src = `data:image/png;base64,${src}`;
    img.classList.add("message-image");
    messageContent.appendChild(img);
  });

  messageDiv.appendChild(messageContent);
  chatContainer.appendChild(messageDiv);
  chatContainer.scrollTop = chatContainer.scrollHeight;
}

function clearImagePreviews() {
  while (imageContainer.firstChild) {
    imageContainer.removeChild(imageContainer.firstChild);
  }
  checkImageContainerVisibility();
}

let typingTimeout;

function showTypingIndicator() {
  clearTimeout(typingTimeout);
  typingIndicator.style.display = "inline-block";
}

function hideTypingIndicator() {
  typingTimeout = setTimeout(() => {
    typingIndicator.style.display = "none";
  }, 1000);
}

function handleKeyPress(event) {
  if (event.key === "Enter") {
    sendMessage();
  }
}

function toggleSidebar() {
  if (sidebar.style.width === "500px") {
    sidebar.style.width = "0";
    sidebarContent.style.display = "none";
  } else {
    sidebar.style.width = "500px";
    sidebarContent.style.display = "block";
  }
}

window.onload = () => addMessage("Hello! How can I assist you today?", 'bot');

document.addEventListener('DOMContentLoaded', () => {
  const textInput = document.getElementById('userInput');

  textInput.addEventListener('paste', (event) => {
    const items = (event.clipboardData || window.clipboardData).items;
    for (const item of items) {
      if (item.type.indexOf('image') !== -1) {
        const file = item.getAsFile();
        const reader = new FileReader();
        reader.onload = (event) => {
          displayImage(event.target.result);
        };
        reader.readAsDataURL(file);
        event.preventDefault();
      }
    }
  });

  function displayImage(src) {
    const imgContainer = document.createElement('div');
    imgContainer.classList.add('img-preview-container');

    const img = document.createElement('img');
    img.src = src;
    img.classList.add('img-preview');

    const removeButton = document.createElement('button');
    removeButton.classList.add('remove-button');
    removeButton.textContent = '✖';
    removeButton.addEventListener('click', () => {
      imgContainer.remove();
      checkImageContainerVisibility();
    });

    imgContainer.appendChild(img);
    imgContainer.appendChild(removeButton);
    imageContainer.appendChild(imgContainer);
    checkImageContainerVisibility();

    const all_images = imageContainer.querySelectorAll('.img-preview-container');
    all_images.forEach(img => img.style.width = `${100 / all_images.length - 10}%`);
  }

  function checkImageContainerVisibility() {
    if (imageContainer.children.length > 0) {
      imageContainer.classList.remove('hidden');
    } else {
      imageContainer.classList.add('hidden');
    }
  }

  // Initial check to hide image container if empty
  checkImageContainerVisibility();
});
body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: #f0f2f5;
    color: #333;
    margin: 0;
    padding: 0;
    text-align: center;
}

h1 {
    color: #333;
    text-align: center;
    margin: 20px 0;
}

/* Generate report button styling */
button, input[type="submit"] {
    padding: 12px 24px;
    background-color: #007bff;
    color: #fff;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-size: 16px;
    transition: background-color 0.3s, transform 0.3s;
}

button:hover, input[type="submit"]:hover {
    background-color: #0056b3;
    transform: translateY(-2px);
}

/* Form styling */
form {
    background: #fff;
    border-radius: 8px;
    padding: 20px;
    max-width: 600px;
    margin: 20px auto;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

label {
    display: block;
    margin-bottom: 8px;
    font-weight: 600;
    font-size: 16px;
}

select, input[type="submit"] {
    width: calc(100% - 22px);
    padding: 12px;
    margin-bottom: 20px;
    border-radius: 6px;
    border: 1px solid #ddd;
    font-size: 16px;
}

select {
    background-color: #f9f9f9;
}

/* Report page styling */
.report-container {
    background: #fff;
    border-radius: 8px;
    padding: 20px;
    max-width: 1000px;
    margin: 20px auto;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    overflow: auto;
}

a {
    color: #007bff;
    text-decoration: none;
    font-weight: 500;
}

a:hover {
    text-decoration: underline;
}

/* Section that will show report content */
.report-content {
    margin-top: 20px;
}

.report-content iframe {
    width: 100%;
    border: none;
    height: 600px;
}



/* Chat Bot */
.container {
    margin-top: 0;
    width: 90%;
    max-width: 450px;
    margin: 10px auto 0;
    background-color: #fff;
    border-radius: 12px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
    padding: 20px;
    transition: all 0.3s;
}

.chat {
    overflow-y: auto;
    height: 400px;
    margin-bottom: 20px;
    border-bottom: 2px solid #e2e2e2;
}

.message {
    display: flex;
    margin-bottom: 12px;
}

.message.user {
    justify-content: flex-end;
}

.message-bubble {
    padding: 12px 18px;
    max-width: 70%;
    border-radius: 20px;
    line-height: 1.6;
    font-size: 0.95rem;
}

.message.user .message-bubble {
    background-color: #3182ce;
    color: white;
}

.message.bot .message-bubble {
    background-color: #e2e2e2;
    color: #333;
}


.message-image {
    max-width: 100px; /* Set the maximum width for the image */
    max-height: 100px; /* Set the maximum height for the image */
    margin: 5px;
    display: inline-block;
    object-fit: cover; /* Ensures the image retains its aspect ratio */
}


input[type="text"] {
    flex: 1;
    padding: 12px 18px;
    border: 2px solid #e2e2e2;
    border-radius: 8px 0 0 8px;
    font-size: 1rem;
    outline: none;
    color: black;
}

.send-button {
    width: 110px;
    background-color: #3182ce;
    color: white;
    padding: 12px 18px;
    border: none;
    border-radius: 0 8px 8px 0;
    cursor: pointer;
    transition: background-color 0.3s;
}

.send-button:hover {
    background-color: #2c5282;
}

.footer {
    text-align: center;
    padding: 15px 0;
    font-size: 0.9rem;
    color: #666;
    position: static;
    border-top: 1px solid #e2e2e2;
    background-color: #fff;
    position: fixed;
    bottom: 0;
    width: 100%;
}

@keyframes fadeIn {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

.fadeIn {
    animation: fadeIn 1s;
}

@media (max-width: 600px) {
    .container {
        width: 95%;
        margin: 10px auto 0;
    }

    .chat {
        height: 300px;
    }

    .input-container {
        max-width: 95%;
    }

    input[type="text"],
    .send-button {
        padding: 10px 14px;
        font-size: 0.9rem;
    }

    .footer {
        font-size: 0.8rem;
        margin-top: 30px;
    }
}

.typing-indicator {
    display: none;
    align-items: center;
    justify-content: flex-end;
    margin-top: 8px;
    width: 10px;
    height: 10px;
    background-color: #333;
    border-radius: 50%;
    margin-left: 4px;
    animation: typing 1s infinite;
}

@keyframes typing {
    0%,
    100% {
        transform: scale(1);
        opacity: 1;
    }

    50% {
        transform: scale(1.2);
        opacity: 0.7;
    }
}

/* Side bar */
.sidebar {
    position: fixed;
    top: 10px;
    right: 10px;
    height: 100%;
    width: 100%;
    max-width: 500px;
    background-color: none;
    overflow-x: hidden;
    transition: 0.5s;
    padding-top: 60px;
    color: white;
}

.sidebar-content {
    display: none;
}

.sidebar-content h2 {
    text-align: center;
}

.sidebar-content p {
    padding: 10px;
}

.toggle-button {
    position: fixed;
    top: 10px;
    right: 10px;
    padding: 15px;
    background-color: #3182ce;
    color: white;
    border: none;
    cursor: pointer;
}

.toggle-button:hover {
    background-color: #2c5282;
}

img {
    max-width: 90%;
    margin: 20px 0;
    border: 1px solid #ddd;
    border-radius: 10px;
}

.image-container {
    width: 100%;
    /*padding: 12px 18px;*/


    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    background-color: #fff;
    /*border: 1px solid #444;*/
    min-height: 50px;
    max-height: 70px;
    margin-bottom: 10px;

    border: 2px solid #e2e2e2;
    border-radius: 8px 8px 8px 8px;
}

.hidden {
    display: none;
}

.img-preview-container {
    position: relative;
    display: inline-block;
    max-width: 15%;
}

.img-preview {
    max-width: 100%;
    border-radius: 5px;
}


.remove-button:hover {
    background-color: #45a049;
}

.remove-button {
    position: absolute;
    top: 5px;
    right: 5px;
    background-color: #ff4d4d;
    border: none;
    border-radius: 50%;
    color: white;
    cursor: pointer;
    width: 20px;
    height: 20px;
    font-size: 12px;
    line-height: 20px;
    text-align: center;
    padding: 0;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Portfolio Backtesting</title>
    <link
      rel="stylesheet"
      href="{{ url_for('static', filename='css/style.css') }}"
    />
  </head>
  <body>
    <h1>Portfolio Backtesting</h1>
    <form method="post" action="/">
      <label for="cs_model">Choose Cross-Sectional Model:</label>
      <select id="cs_model" name="cs_model">
        <option value="EW">Equal Weight (EW)</option>
        <option value="MSR">Maximum Sharpe Ratio (MSR)</option>
        <option value="GMV">Global Minimum Variance (GMV)</option>
        <option value="MDP">Minimum Drawdown Risk (MDP)</option>
        <option value="EMV">Equal Risk Contribution (EMV)</option>
        <option value="RP">Risk Parity (RP)</option>
      </select>

      <label for="ts_model">Choose Time-Series Model:</label>
      <select id="ts_model" name="ts_model">
        <option value="VT">Volatility Targeting (VT)</option>
        <option value="CVT">Conditional Value at Risk Targeting (CVT)</option>
        <option value="KL">Kelly Criterion (KL)</option>
        <option value="CPPI">
          Constant Proportion Portfolio Insurance (CPPI)
        </option>
      </select>

      <input type="submit" value="Generate Report" />
    </form>

    <div class="sidebar" id="sidebar">
      <button class="toggle-button" onclick="toggleSidebar()">☰</button>
      <div class="sidebar-content" id="sidebarContent">
        <div class="container bg-white rounded-lg shadow-md">
          <h1 class="text-3xl font-bold mb-4 text-center">ChatBot</h1>
          <div class="chat" id="chatContainer"></div>
          <div class="image-container hidden" id="imageContainer"></div>
          <div class="flex">
            <input
              type="text"
              id="userInput"
              placeholder="Type your message here..."
              class="outline-none"
              onkeyup="handleKeyPress(event)"
            />
            <button class="send-button" onclick="sendMessage()">Send</button>
          </div>
          <div class="typing-indicator" id="typingIndicator"></div>
        </div>
      </div>
    </div>
    <script src="{{ url_for('static', filename='js/script.js') }}"></script>
  </body>
</html>

express js urls calling same route.get()

"use strict"

const express = require("express")
const router = express.Router()
require("dotenv").config()

const current_file_version = process.env.CURRENT_APP_VERSION + ".js"

const site_pages_controller = "../controllers/app/site_pages/"
const homeRouter = require(site_pages_controller + "home/" + current_file_version)

router.use("/", homeRouter)

const users_controller = "../controllers/app/users/"
const profileRouter = require(users_controller + "profile/" + current_file_version)

router.use("/profile", profileRouter)

module.exports = router

Both of these urls are fetching code from site_pages/v1.js .. If I comment that, then both of the urls point to the /profile/v1.js

I tried commenting the codes in the controllers. Both urls point to the same GET every time. If I comment the route itself, then it works correctly. Please help.

How to Update the Contents of a Dropdown Based on the Selection of Another Dropdown

I am trying to update the contents of a particular dropdown box, based on the selection of another dropdown box. The contents of these boxes is coming from tables in an MSSQL database. Basically, I have a list of “Principals” (aka companies) in one box, and a “Description” box (aka different items) in a second box. My goal is that one you select a specific “Principal” (aka company), that only the selected Principal’s items populate the “Description” box. As it stands now, every item in the “Description” box displays, regardless of the “Principal” (aka company) selected. Just to give you an idea, below is a screenshot of the boxes I am referring to, as well as the relevant code currently being used. As you can obviously see, it’s written mainly in asp-classic/vbs, but Javascript is used as well. I am open to using ANY language/method necessary to accomplish this. Any help is greatly appreciated, if any other details are required I am happy to give them. Thank you very much.

enter image description here

And here is the relevant code for the page currently being used:

<%
Dim Conn, Rs, strPrincipleOptions, DistributorOptions, SalesRepOptions, DescriptionOptions, strSQL
Dim rsclient, OperatorNumber, oRequest

    OperatorNumber = Request("Operator_Num") '12600 'test operator number
    ProcessMe = Cbool(Request("ProcessMe"))

    If (OperatorNumber = "") then
        Call TryAgain
    ElseIf Cbool(ProcessMe) Then
    
        Set Conn = Application("Conn")
        Set Rs = Server.CreateObject("ADODB.RecordSet")

        For each oRequest in Request.Form
            If (oRequest <> "ProcessMe") AND (oRequest <> "submit") AND (Left(oRequest,4) <> "temp") then
                If (Request.Form(oRequest) <> "") Then
                    strNames = strNames & oRequest & ","
                    If (Left(oRequest,9) = "Principle") OR (Left(oRequest,11) = "Distributor") then 
                        strValues = strValues & Request.Form(oRequest) & ","
                    Else
                        strValues = strValues & "'" & Replace(Request.Form(oRequest),"'","") & "',"
                    End if
                End If
            End If
        Next
        strNames = Left(strNames,Len(strNames)-1) & ",[date]"
        strValues = Left(strValues,Len(strValues)-1) & ",'" & date() & "'"
        
        strSQL = "INSERT INTO Product (" & strNames & ") VALUES (" & strValues & ")"
        'Response.Write strSQL
        'Response.End
        
        Conn.Execute (strSQL)
        Set Conn = nothing

        Call SubmittedReport
        '+INSERT INTO "Product" ("Operator_Num", "Operator", "Address", "City", "State", "Zip", "Contact1", "Phone", "creation_date", "Type_Call", "Acc_Rep", "Sales_Rep", "Mgmt_Co", "Segment", "DSR_Pri", "DSRFullName_Pri", "Concept_Recipe", "Product1", "Product2", "Product3", "Product4", "Product5", "Product6", "Description1", "Description2", "Description3", "Description4", "Description5", "Description6", "Principle1", "Principle2", "Principle3", "Principle4", "Principle5", "Principle6", "Result1", "Result2", "Result3", "Result4", "Result5", "Result6", "Cases1", "Cases2", "Cases3", "Cases4", "Cases5", "Cases6", "Distributor1", "Distributor2", "Distributor3", "Distributor4", "Distributor5", "Distributor6", "Comments1", "Comments2", "Comments3", "Comments4", "Comments5", "Comments6", "FollowUp_Date", "FollowUp_Necessary")
        '+VALUES ('%Operator_Num%', '%Operator%', '%Address%', '%City%', '%State%', '%Zip%', '%Contact1%', '%Phone%', '%creation_date%', '%Type_Call%', '%Acc_Rep%', '%Sales_Rep%', '%Mgmt_Co%', '%Segment%', '%DSR_Pri%', '%DSRFullName_Pri%', '%Concept_Recipe%', '%Product1%', '%Product2%', '%Product3%', '%Product4%', '%Product5%', '%Product6%', '%Description1%', '%Description2%', '%Description3%', '%Description4%', '%Description5%', '%Description6%', '%Principle1%', '%Principle2%', '%Principle3%', '%Principle4%', '%Principle5%', '%Principle6%', '%Result1%', '%Result2%', '%Result3%', '%Result4%', '%Result5%', '%Result6%', '%Cases1%', '%Cases2%', '%Cases3%', '%Cases4%', '%Cases5%', '%Cases6%', '%Distributor1%', '%Distributor2%', '%Distributor3%', '%Distributor4%', '%Distributor5%', '%Distributor6%', '%Comments1%', '%Comments2%', '%Comments3%', '%Comments4%', '%Comments5%', '%Comments6%', '%FollowUp_Date%', '%FollowUp_Necessary%');
        
    Else        
        Set Conn = Application("Conn")
        Set rsclient = Conn.execute ("select * from FSA where Operator_Num = "& OperatorNumber)

        If rsclient.eof then
            Call TryAgain
        End If

        Call getDropdowns
        Call CallReport
    End If
            
Sub getDropdowns
    Set Conn = Application("Conn")
    Set Rs = Server.CreateObject("ADODB.RecordSet")

    strSQL = "SELECT DISTINCT(Principle), ID FROM Principal ORDER BY Principal.Principle"
    Rs.Open strSQL, Conn
    Do while not Rs.EOF
        strPrincipleOptions = strPrincipleOptions & "<option value=" & Rs.Fields("ID") & ">" & Rs.Fields("Principle") & "</option>" & vbcrlf
    Rs.MoveNext
    Loop
    Rs.Close
            
    strSQL = "SELECT DISTINCT(Distributor), ID FROM Distributors ORDER BY Distributor"
    Rs.Open strSQL, Conn
    Do while not Rs.EOF
        DistributorOptions = DistributorOptions & "<option value=" & Rs.Fields("ID") & ">" & Rs.Fields("Distributor") & "</option>" & vbcrlf
    Rs.MoveNext
    Loop
    Rs.Close
            
    strSQL = "SELECT DISTINCT(FullName) FROM sales_rep ORDER BY FullName"
    Rs.Open strSQL, Conn
    Do while not Rs.EOF
        SalesRepOptions = SalesRepOptions & "<option value=" & chr(34)  & Rs.Fields("FullName") & chr(34)  & ">" & Rs.Fields("Fullname") & "</option>" & vbcrlf
    Rs.MoveNext
    Loop    
    Rs.Close

    strSQL = "SELECT DISTINCT(Description) FROM Item_Desc ORDER BY Description"
    Rs.Open strSQL, Conn
    Do while not Rs.EOF
        DescriptionOptions = DescriptionOptions & "<option value=" & chr(34)  & Rs.Fields("Description") & chr(34)  & ">" & Rs.Fields("Description") & "</option>" & vbcrlf
    Rs.MoveNext
    Loop    
    Rs.Close

End Sub

Sub CallReport
    %>
    <html>
    <head>
    <title>FoodService Call Report</title>
    <script language=javascript>

    function on_load() {
            window.scroll(0,0);
            document.update.Sales_Rep.focus();
    }

    function getCreation_Date() {

        if (document.update.Sales_Rep.value == "") {
        alert ("You must select a Sales Rep before submitting document.");
                            window.scroll(0,0)
                            document.update.Sales_Rep.focus();
            return;
        }
            //date1 must be a 0 or 1        
            if (parseInt(document.update.temp2.value) > 12)  {
                            alert ("You did not enter a valid MONTH.");
                            document.update.temp2.value = "";
                            window.scroll(0,0)
                            document.update.temp2.focus();
                    return;
            } 
            //date3 must be a 0 or 1 or 2 or 3
            
            var temp_date =      document.update.temp2.value + "/" +
                                    document.update.temp4.value + "/" +
                                    document.update.temp5.value +
                                    document.update.temp6.value +
                                    document.update.temp7.value +
                                    document.update.temp8.value 
        if (temp_date.length < 8) {
                    alert ("You did not enter a correct Call Date. i.e. 01/01/2003");
                    window.scroll(0,0)
                    document.update.temp2.focus();
                    return;
            } else {
                    

            var creation_date = temp_date;
                    document.update.creation_date.value = temp_date;//creation_date
                    document.update.submit();
            }
    }

    //  <input type="button" value="Insert Record" name=jerry onClick="getCreation_Date();">&nbsp; &nbsp;
    //  &nbsp;<input TYPE="reset" VALUE="Clear" id=reset1 name=reset1></p>

    </script>
    </head>

<body BACKGROUND="../tabbkgnd.jpg" TEXT="#000000" LINK="#4E7F6E" VLINK="#1B4E3B">

    <b><font size="5" color="blue">

    <p align="center">FoodService Associates</font><br>
    <font size="3" color="black">Call Report Information (Use TAB key to move to next field)</font></b>
    <b>

     <table border="1" cellpadding="4" Width="95%" align="center">
        <!-- HIDE THE FORM SPACE -->
        <form action="updateclientA.asp" method="post" name="update">
          <input type="hidden" name="ProcessMe" value=1>
          <!--<input type="hidden" name="[Date]" value="<%=Date()%>">-->
          <input type="hidden" name="Operator_Num" value="<%response.write(rsclient("Operator_num"))%>">
          <input type="hidden" name="Acc_Rep" value="<%response.write UCASE(rsclient("Acc_Rep"))%>">
          <input type="hidden" maxlength=100 name="Operator" value="<%response.write UCASE(rsclient("Operator"))%>">
          <input type="hidden" maxlength=100 name="Address" value="<%response.write UCASE(rsclient("Address"))%>">
          <input type="hidden" maxlength=100 name="City" value="<%response.write UCASE(rsclient("City"))%>">
          <input type="hidden" maxlength=100 name="State" value="<%response.write UCASE(rsclient("State"))%>">
          <input type="hidden" maxlength=100 name="Zip" value="<%response.write UCASE(rsclient("Zip"))%>">
          <input type="hidden" maxlength=100 name="Contact1" value="<%response.write UCASE(rsclient("Contact1"))%>">
              
          <input type="hidden" maxlength=100 name="Phone" value="<%response.write UCASE(rsclient("Phone"))%>">
          <input type="hidden" name="Mgmt_Co" value="<%response.write UCASE(rsclient("Mgmt_Co"))%>">
          <input type="hidden" name="Segment" value="<%response.write UCASE(rsclient("Segment"))%>">

        <tr bgcolor="yellow">
          <td align="right">
            <b>Call Date: 
            mm<input type="text" value="<%=Month(date())%>" size="2" maxlength="2" name="temp2" onKeyUp="">/ 
            dd<input type="text" value="<%=day(date())%>" size="2" maxlength="2" name="temp4" onKeyUp="">/ 
            yy<input type="text" value="2" size="1" maxlength="1" name="temp5"> 
            <input type="text" value="0" size="1" maxlength="1" name="temp6"> 
            <input type="text" value="2" size="1" maxlength="1" name="temp7"> 
            <input type="text" value="4" size="1" maxlength="1" name="temp8">
            <input type="hidden" value="" name="creation_date"> 
            </b></td>
          <td align="right"><b>Operator/ Mgmt Co #:</b></td>
          <td><%=rsclient("Operator_num")%> &nbsp;</td>
          <td align="right"><b>Class:</b></td>
          <td><%=rsclient("A_Class")%> &nbsp;</td>
        </tr>
      </table>
      <table border="1" cellpadding="1" Width="95%" align="center">
        <tr>
          <td align="right"><font size="2"><b>Assigned Rep:</b></font></td>
          <td><%response.write UCASE(rsclient("Acc_Rep"))%> &nbsp;</td>
          <td align="right"><font size="2"><b>Sales Rep:</b></font></td>
          <td><select name="Sales_Rep" size="1">
            <option selected value="">Select</option>
            <%response.write SalesRepOptions%>
            <option value="Other">Other</option>
          </select></td>
        </tr>
        <tr>
          <td align="right"><font size="2"><b>Operator:</b></font></td>
          <td><%response.write UCASE(rsclient("Operator"))%> &nbsp;</td>
          <td align="right"><font size="2"><b>Mgmt Co.:</b></font></td>
          <td><%response.write UCASE(rsclient("Mgmt_Co"))%> &nbsp;</td>
        </tr>
        <tr>
          <td align="right"><font size="2"><b>Address:</b></font></td>
          <td><%response.write UCASE(rsclient("Address"))%> &nbsp;</td>
          <td align="right"><font size="2"><b>City:</b></font></td>
          <td><%response.write UCASE(rsclient("City"))%> &nbsp;</td>
        </tr>
        <tr>
          <td align="right"><font size="2"><b>State:</b></font></td>
          <td><%response.write UCASE(rsclient("State"))%> &nbsp;</td>
          <td align="right"><font size="2"><b>Zip Code:</b></font></td>
          <td><%response.write UCASE(rsclient("Zip"))%> &nbsp;</td>
        </tr>
        <tr>
          <td align="right"><font size="2"><b>Phone:</b></font></td>
          <td><%response.write UCASE(rsclient("Phone"))%> &nbsp;</td>
          <td align="right"><font size="2"><b>Fax:</b></font></td>
          <td><%response.write UCASE(rsclient("Fax"))%> &nbsp;</td>
        </tr>
        <tr>
          <td align="right"><font size="2"><b>1st Contact:</b></font></td>
          <td><%response.write UCASE(rsclient("Contact1"))%> &nbsp;</td>
          <td align="right"><font size="2"><b>2nd Contact:</b></font></td>
          <td><%response.write UCASE(rsclient("Contact2"))%> &nbsp;</td>
        </tr>
      
 <tr>
          <td align="right"><font size="2"><b>1st Contact Title:</b></font></td>
          <td><%response.write UCASE(rsclient("Contact_Title1"))%> &nbsp;</td>
          <td align="right"><font size="2"><b>2nd Contact Title:</b></font></td>
          <td><%response.write UCASE(rsclient("Contact_Title2"))%> &nbsp;</td>
        </tr>
<tr>
          <td align="right"><font size="2"><b>1st Contact Phone:</b></font></td>
          <td><%response.write UCASE(rsclient("Contact_P1"))%> &nbsp;</td>
          <td align="right"><font size="2"><b>2nd Contact Phone:</b></font></td>
          <td><%response.write UCASE(rsclient("Contact_P2"))%> &nbsp;</td>
        </tr>


        <tr>
          <td align="right"><font size="2"><b>1st Contact Email:</b></font></td>
          <td><a href = mailto:><%response.write (rsclient("Contact1_Mail"))%> &nbsp;</td></a>
          <td align="right"><font size="2"><b>2nd Contact Email:</b></font></td>
          <td><a href = mailto:><%response.write (rsclient("Contact2_mail"))%> &nbsp;</td></a>
                         
     </tr> 
         <td align="right"><font size="2"><b>Segment:</b></font></td>         
          <td><%response.write UCASE(rsclient("Segment"))%> &nbsp;</td></a>
          <td align="right"><font size="2"><b>Affiliation:</b></font></td>
          <td><%response.write UCASE(rsclient("Affiliation"))%> &nbsp;</td>
        </tr>
        <tr>
          <td align="right"><font size="2"><b>Pri. DSTR:</b></font></td>
          <td><%response.write UCASE(rsclient("DSR_Pri"))%> &nbsp;</td>
          <td align="right"><font size="2"><b>DSR Name:</b></font></td>
          <td><%response.write UCASE(rsclient("DSRFullName_Pri"))%> &nbsp;</td>
        </tr>
      </table>
      <font color="red"><b><div align="center"><center><p>CALL REPORT<font color="black">
      </center></div><table border="1" cellpadding="4" Width="95%" align="center">
        <tr bgcolor="yellow">
          <td><div align="center"><center><p><b>&nbsp; &nbsp;<font color="#FF0000">Is 
            this an "<i>issued</i>" SALES LEAD</font><font color="#FF00FF"> 
            </font>&nbsp; <input type="radio"
          name="Type_Call" Value="YES"> YES &nbsp; &nbsp; <input
          type="radio" name="Type_Call" Value=""> NO&nbsp; <font color="#FF0000">
            (&quot;issued&quot; defined as a formal Lead recorded with the Sales 
            Administrator in the office)</font></b></td>
        </tr>
        <tr align="center">
          <td> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </td>
        </tr>
         <tr bgcolor="yellow">
          <td><div align="center"><center><p><b>&nbsp; &nbsp;</font></font><font color="#FF0000">Check Only If a NOW OBJECTIVE Operator Call:</font> <font color="red">&nbsp; &nbsp; &nbsp; <input type="radio"
          name="Type_Call2" Value="NOW"> </font>NOW Objective Call  <font color="red">&nbsp; &nbsp; <input
          type="radio" name="Type_Call2" Value=""> </font><font color="#FF0000">
            <u>Not</u>
              </font>a<font color="#FF0000"> </font>NOW Objective</b>
          </div>
        </center></td>
        </tr><tr align="center"><td> &nbsp;&nbsp;<b>&nbsp;</font></b><font color="RED"><span style="font-style: normal; font-weight: 700">MARKED 
          FIELDS ARE REQUIRED ENTRIES ***</span></td></tr>
      </table>
      <font color="red">
      <div align="center"><center>
        <table border="1" width="95%" cellpadding="0" align="center">
        <tr bgcolor="yellow">
          <td width="23">&nbsp;</td>
          <td width="95"><b><font size="2">Product#<font color="#FF0000"> </font></font>
          </b></td>
          <td width="211"><b><font size="2">Description<font color="#FF0000">
          </font></font><font color="#FF0000">***</font></b></td>
          <td width="117"><b><font size="2">Principal<font color="#FF0000">
          </font></font><font color="#FF0000">***</font></b></td>
          <td width="95"><b><font size="2">Result<font color="#FF0000"> </font></font>
          <font color="#FF0000">***</font></b></td>
          <td width="70"><font size="2"><b>Cases</b></font></td>
          <td width="115"><font size="2"><b>Distributor</b></font></td>
          <td width="293"><font size="2"><b>Comments</b></font></td>
        </tr>
        <tr>
          <td width="23"><font size="2"><b>1:</b></font></td>
          <td width="95"><input type="text" size="6" maxlength="30" name="Product1"></td>
          <td width="211"><select name="Description1" size="1">
            <option selected value="0">select</option>
            <%response.write DescriptionOptions%>
            <option value="">55</option>
          </select></td>
          <td width="117"><select name="Principle1" size="1">
            <option selected value="0">select</option>
            <%response.write strPrincipleOptions%>
            <option value="">55</option>
          </select></td>
          <td width="250"><select name="Result1" size="1">
            <option selected value="Select">Select</option>
            <option value="Sold">Sold</option>
            <option value="Testing">Testing</option>
            <option value="Interest">Interest</option>
            <option value="Using">Using</option>
            <option value="Intent To Use">Intent To Use</option>
            <option value="No Taste">No Taste</option>
            <option value="No Price">No Price</option>
            <option value="No Pend Dist">No Pend Dist</option>
            <option value="No Nutrition">No Nutrition</option>
            <option value="No Scratch">No Scratch</option>
            <option value="No Menu Fit">No Menu Fit</option>
            <option value="Follow Up Needed">Follow Up Needed</option>
            <option value="re-Order (sold)">re-Order (sold)</option>
            </select></td>
          <td width="70"><input type="text" size="4" maxlength="30" name="Cases1"></td>
          <td width="115"><select name="Distributor1" size="1">
            <option selected value="0">select</option>
            <%response.write DistributorOptions%>
          <option value="67">Other</option> 
          </select></td>
          <td width="290">
          <input type="text" size="36" maxlength="100" name="Comments1"></td>
        </tr>
        <tr>

Attribute value html encoded when added to custom tag builder

I’m trying to add an OnClick attribute to a custom tag helper, but the value doesn’t render properly. It looks like it gets encoded.

AddAttribute:

icon.AddAttribute("onclick", $"togglePasswordVisible('{this.InputControlName}');");

Page source:

onclick="togglePasswordVisible(&#x27;TesterPass&#x27;);"

How can I keep the formating of the value?

My Vue API client is getting data OK, and I have the logic to turn it into .csv, but I can’t seem to work out how to download the file

DiscogsCSV is intended to do the following:

  • Take as input a .csv file, the first column of which contains valid discogs release IDs
  • Look these release IDs up on discogs API https://api.discogs.com/
  • Return as output a new .csv file, with discogs release data for various columns appended to the release IDs:

release_id
artist
format
qty
format descriptions
label
catno
country
year
genres
styles
barcode
tracklist

Here is my code:

App.vue

<template>
    <div>
        <button @click="downloadSampleInputFile">Download sample file</button>
    </div>

    <div>
        <FileUpload @file="setFile" />
    </div>

    <div>
        <p v-for="row of data" :key="row">
            {{ row }}
        </p>
    </div>

</template>

<script lang="ts">
import { defineComponent } from 'vue';
import FileUpload from '@/components/FileUpload.vue';
import { fetchRelease, parseCsvToArray } from "@/parser";
import { prepareDownload } from './components/PrepareDownload';
import { downloadSampleInputFile } from './components/DownloadSampleInputFile';

export default defineComponent({
    name: 'App',
    components: {
        FileUpload,
    },
    data() {
        return {
            data: null as null | string[],
        }
    },
    methods: {
        async downloadSampleInputFile() {
            const link = document.createElement('a');
            link.href = '/src/assets/test_5_lines.csv';
            link.target = '_blank';
            link.download = 'test_5_lines.csv';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        },
        async setFile(file: File) {
            this.data = await parseCsvToArray(file)
            console.log(this.data)
        },
        async fetchReleases(idList: string[]) {
            try {
                const releases = await fetchRelease(idList)
                console.log('Fetched releases from Discogs', releases)
                return releases
            } catch (err) {
                console.log('Failed fetching releases', err)
            }
        },
        async downloadCSV(releases: any[]) {
            prepareDownload(releases)
        },
        
    },
    watch: {
        data(data) {
            this.fetchReleases(data)
        }
    },
});
</script>

fetchRelease.ts

import { DiscogsClient } from '@lionralfs/discogs-client';
import { processReleaseData } from './ProcessReleaseData';

export default  {
  name: 'FetchRelease',
  methods: {
    fetchRelease
  }
}

const db = new DiscogsClient().database();

async function fetchRelease(releaseId: string): Promise<any[] | { error: string }> {
  try {
    const { data } = await db.getRelease(releaseId);
    return processReleaseData(releaseId, data);
  } catch (error) {
    return {
      error: `Release with ID ${releaseId} does not exist`
    };
  }
}

PrepareDownload.ts

import { ROW_NAMES } from './RowNames';

export default  {
  name: 'PrepareDownload',
  methods: {
    prepareDownload
  }
}

export function prepareDownload(releases: any[]) {
    const csvContent = "releases:text/csv;charset=utf-8," + ROW_NAMES.join(",") + "n" + releases.map(e => e.join(",")).join("n");
    const encodedUri = encodeURI(csvContent);
    const link = document.createElement("a");
    link.setAttribute("href", encodedUri);
    link.setAttribute("download", "my_data.csv");
    document.body.appendChild(link); // Required for Firefox
    link.click();
  }

https://github.com/d0uble-happiness/DiscogsCsvVue

I can get as far as console.log('Fetched releases from Discogs', releases), just fine, the data is in the console. But this bit isn’t working. Any help please? TIA

    async downloadCSV(releases: any[]) {
        prepareDownload(releases)

fallback element not coming when lazy prop is used – ReactRouterV6

I am using ReactRouterV6 to lazy load a router,

When I use lazy prop, in this case my fallback element defined in RouterProvider not coming up.

Fallback Element only comes when I go directly to the path, but when I push the path using navigate or Link , then the fallback element is not coming.

const router = createBrowserRouter(
  createRoutesFromElements(
    <>
      <Route
        path="/"
        lazy={() => import("./pages/detail")}
        element={<Suspense fallback={<h1>hello</h1>}>{/* <X /> */}</Suspense>}
      />
      <Route path="/a" element={<PageA />} action={foromAction} />
      <Route path="/b" element={<PageB />} action={foromAction} />
    </>
  )
);
   <RouterProvider
          history={history}
          fallbackElement="Loading..2222."
          router={router}
        />

And When I change my syntax like this:

 const X = lazy(() => import("./pages/detail"));

<Route
        loader={loader}
        path="/" //lazy={() => import("./pages/detail")}
        element={
          <Suspense fallback={<h1>hello</h1>}>
            <X />
          </Suspense>
        }
      />

then the fallback UI is coming,

Now the problem with this approach is that, I have to pass loader explicitly.i
and also I am curious why fallback UI is not coming with lazy prop.

In My ./pages/detail Component, I have exported Component,loader and a default export for component.

Copy to clipboard using `writeText` fails in Chrome in cross-origin “ container

I have a cross-origin <object data="{my-cross-origin-url}"> container that contains a copy to clipboard button for an email address with the code:

navigator.clipboard.writeText("[email protected]")

Clicking on the copy to clipboard button works in Safari on my Mac (I can successfully click to copy and then paste the email value). Sadly, it fails on Chrome! The error message is as follows in my Chrome console:


[Violation] Permissions policy violation: The Clipboard API has been blocked because of a permissions policy applied to the current document. See [URL_removed because Stack_Overflow wouldn’t allow it, it’s below] for more details.


https://www.chromium.org/Home/chromium-security/deprecating-permissions-in-cross-origin-iframes/

The thing is, it’s all references to iframes in that link and I do not use iframes, but a HTML object tag with data attribute value that refers to a site that is cross-origin (I own both the parent site and the one that is being embedded using the object tag). I don’t see anywhere that I can add an allow attribute on the object tag and am reluctant to lest I break things in Chrome and Safari.

How can I get copy to clipboard working in my cross-origin embed with HTML object tag?