How can I build a Chrome extension that allows users to capture a specific area of a webpage as an image?

I’m working on a Chrome extension to capture a specific area of a webpage as an image. I’ve tried several approaches, including using the html2Canvas,, and manipulating the DOM to select the area, but I keep running into various issues and errors. Either the selected area isn’t captured correctly, or sometimes it able to capture but failed on second attempt. I’ve spent a lot of time troubleshooting, but I’m still not able to get it to work as expected. Any guidance or suggestions on how to implement this feature would be greatly appreciated!

Know someone who can answer? or Share a link of your code if you already have build something like this

enter image description here

import React, { useState } from "react";

const ScreenCaptureComponent: React.FC = () => {
  const [screenCapture, setScreenCapture] = useState<string | null>(null);

  const handleCapture = () => {
    chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
      if (tabs[0].id) {
        chrome.scripting.executeScript(
          {
            target: { tabId: tabs[0].id },
            files: ["content.js"],
          },
          () => {
            chrome.tabs.sendMessage(
              tabs[0].id!,
              { message: "capture" },
              (response) => {
                if (chrome.runtime.lastError) {
                  console.error("Error:", chrome.runtime.lastError);
                } else if (response && response.imgData) {
                  setScreenCapture(response.imgData);
                } else {
                  console.error("Failed to capture screen");
                }
              }
            );
          }
        );
      }
    });
  };

  const handleSave = () => {
    if (screenCapture) {
      const a = document.createElement("a");
      a.href = screenCapture;
      a.download = "screenshot.png";
      a.click();
    }
  };

  return (
    <div>
      <button onClick={handleCapture}>Capture</button>
      {screenCapture && (
        <div>
          <img src={screenCapture} alt="Screen Capture" />
          <button onClick={handleSave}>Download</button>
        </div>
      )}
    </div>
  );
};

export default ScreenCaptureComponent;

Dayjs behave wired between mobile and web application

I am using this function to parse wall time of future event to user local timezone:

export const parseGatheringDate = (
  timeZone: string,
  gatheringData: {
    date: string;
    time: string;
    timeZone: string;
  }
) => {
  const eventDateTime = `${gatheringData.date}T${gatheringData.time}:00`;

  const gathering = dayjs.tz(eventDateTime, gatheringData.timeZone);

  const eventInLocalTime = gathering.tz(timeZone);

  const formattedEventTime = eventInLocalTime.format("YYYY-MM-DD HH:mm");

  return formattedEventTime;
};

And on web I am getting:

2024-08-21 02:00
2024-08-21 08:00

Which are correct values.
But on IOS simulator in react-native for the same code I am getting:

2024-08-21 06:44
2024-08-21 06:44

Test code is:

console.log(
      "DATE 1",
      parseGatheringDate("Europe/Belgrade", {
        date: "2024-08-21",
        time: "08:00",
        timeZone: "Europe/Belgrade",
      })
    );
    console.log(
      "DATE 2",
      parseGatheringDate("America/New_York", {
        date: "2024-08-21",
        time: "08:00",
        timeZone: "Europe/Belgrade",
      })
    );

I created a function to write with Firebase, but there is a problem with implementing the search function

I made a writing function with Firebase, but when I search for the title, if it’s ice cream, it comes out when I search for ice cream, but it doesn’t come out when I search for cream I’ve tried a plug-in called searchflex, but it doesn’t work.
I asked the method I ordered on the Internet and AI, but I can’t do what I was told, so I have a question left.

import { db } from './firebaseConfig.js';
import { collection, getDocs } from 'firebase/firestore';
import { PostListManager } from './PostListManager.js';

export async function setupSearch() {
    const searchButton = document.getElementById('searchBtn');
    const searchInput = document.getElementById('searchInput');
    const resultsContainer = document.getElementById('results');

    const postListManager = new PostListManager('results');


    async function loadData() {
        try {
            const querySnapshot = await getDocs(collection(db, 'posts'));
            const posts = querySnapshot.docs.map(doc => ({
                id: doc.id,
                ...doc.data()
            }));
            return posts;
        } catch (error) {
            console.error('Error loading data from Firestore:', error);
            return [];
        }
    }

  
    async function performSearch() {
        const searchText = searchInput.value.trim().toLowerCase();
        if (searchText === "") {
            console.log("Empty search text.");
            return;
        }

        try {
            const posts = await loadData();
            const filteredPosts = posts.filter(post => {
                const titleMatch = post.title && post.title.toLowerCase().includes(searchText);
                const descriptionMatch = post.description && post.description.toLowerCase().includes(searchText);
                const contentMatch = post.content && post.content.toLowerCase().includes(searchText);
                return titleMatch || descriptionMatch || contentMatch;
            });

            if (filteredPosts.length === 0) {
                console.log('No matching documents found.');
            } else {
                console.log(`Found ${filteredPosts.length} matching documents.`);
            }

            postListManager.renderPosts(filteredPosts, false);
        } catch (error) {
            console.error('Error during search:', error);
        }
    }

    // 검색 버튼 클릭 이벤트
    searchButton.addEventListener('click', performSearch);

    // 엔터 키 입력 시 검색 수행
    searchInput.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') {
            performSearch();
        }
    });
}

Why is this javascript code is unable to send data to this flutter web page on local host?

I am developing a project on ecommerce where i have need of sending the data from html to flutter web page using javascript. I tried ways of sending data using EncodedURIComponent to creating a web socket to send data to the flutter site. But, none of that work . Can somebody tell me how to send data from a html site to flutter web page using javascript?

params.id is the value that want to send.

//sample js and dart code

//js

 function sendData() {
        const id = `${params.id}`; // Example ID
    

        // Construct the URL with query parameters
        const flutterUrl = `http://localhost:50759/#/productbrand?id=${encodeURIComponent(id)}}`;
        
        // Redirect to the Flutter web app with the query parameters
        window.location.href = flutterUrl;
    }
      document
        .getElementById("send-product-id")
        .addEventListener("click", sendData);

//dart
this one is the route code where i have already given required parameter in the ui file.

case productbrand:
    final id = uri.queryParameters['id'];
    return MaterialPageRoute(
      builder: (_) => Productbrandpage(id: id ?? 'Unknown ID'),
    );

I have a route name code which put up a name for each page displayed in the search bar.

 Productbrandpage.route: (context) => Productbrandpage(
    id: '',
  ),

Thank you.

Quill editor color controls only work the first time

Using Quill Editor, when I highlight some text, and change the color, the text-change event fires and updates my html. After I cancel-quill and reopen the window, inline style changes no longer fire the text-change event however, typing new text into the editor does. I’ve also console.log(quill) and its always created but the inline style changes only work once.

        <div class='quill-editor-container shadow' id='editor-container'>
        <div id="toolbar" class="toolbar">
            <span class="ql-formats">
                <button class="ql-bold"></button>
                <button class="ql-italic"></button>
                <button class="ql-underline"></button>
            </span>
            <span class="ql-formats">
                <button class="ql-header" value="1"></button>
                <button class="ql-header" value="2"></button>
            </span>
            <span class="ql-formats">
                <select class="ql-size"></select>
            </span>
            <span class="ql-formats">
                <select class="ql-color"></select>
                <select class="ql-background"></select>
            </span>
            <span class="ql-formats">
                <button class="ql-list" value="ordered"></button>
                <button class="ql-list" value="bullet"></button>
                <button class="ql-indent" value="-1"></button>
                <button class="ql-indent" value="+1"></button>
            </span>
            <span class="ql-formats">
                <button class="save-quill" id="save-quill"><i class="fa-solid fa-check text-success"></i> <span class="text-sm">Save</span></button>
                <button class="cancel-quill" id="cancel-quill"><i class="fa-solid fa-xmark text-danger"></i> <span class="text-sm">Cancel</span></button>
            </span>
        </div>
        <div id="editor" class="editor"></div>
    </div>

    <script>
    var quill;
    var chunk_bu = '';
    var activeChunk = '';
$(document).on('dblclick', '[data-chunk="text"]', function() {
    chunk_bu = $(this).html();
    activeChunk = $(this).attr('id');

    $('#editor').empty();

    $('#editor-container').css({
        height: '300px',
        width: '500px',
        visibility: 'visible',
        'z-index': 4
    });
    if (!quill) {
        quill = new Quill('#editor', {
            theme: 'snow',
            modules: {
                toolbar: '#toolbar'
            }
        })
    }

    quill.clipboard.dangerouslyPasteHTML(chunk_bu);
    quill.on('text-change', function() {
        var chunk = document.getElementById(activeChunk)
        chunk.innerHTML = quill.root.innerHTML;
        console.log(quill.root.innerHTML)
    });
});

document.getElementById('cancel-quill').addEventListener('click', function() {
    if (quill) {
        quill.off('text-change'); // Remove event listeners
        quill = null; // Reset Quill instance
    }
    $('#editor').empty();
    $('#editor-container').css({
        height: "0px",
        width: "0px",
        visibility: 'hidden',
        'z-index': -2
    });
    activeChunk = '';
});
</script>

Convert Excel sheet with multiple formulas to Javascript (AI?)

I would like to ask if it is possible to easily convert various Excel formulas that follow each other into Java script in a simple form (such as some kind of artificial intelligence). The resulting javascript would be used for functionality on the web page.

I asked IT and they said it would take dozens of hours. I assume there is a way to shorten it other than simplifying the formulas, but I haven’t found anything.

Datatable dynamic column add issue

I am trying to add a dynamic column with a value to a data table, but it gives an error during datatable initialization. In first time only ajax call is called .after that ajax call is not working. Please review my code and update for solution.

How can I create a mask that covers the entire page and reveals content when clicked?

I’m working on a React component where I want to implement a mask that covers the entire viewport and reveals some content when clicked. Currently, I have a component that uses GSAP for animation and Framer Motion for handling the mask state. However, I’m having trouble doing this

import { useEffect, useRef } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import gsap from 'gsap';

const Mask = () => {
  const delayedEffect = useRef({ x: 0, y: 0 });
  const mouse = useRef({ x: 0, y: 0 });

  const lerp = (x, y, a) => x * (1 - a) + y * a;

  const moveCircle = (x, y) => {
    gsap.set('.mask', { maskPosition: `${x}px ${y}px` });
  };

  useEffect(() => {
    const animate = () => {
      const { x, y } = delayedEffect.current;
      delayedEffect.current = {
        x: lerp(x, mouse.current.x, 0.08),
        y: lerp(y, mouse.current.y, 0.08),
      };
      moveCircle(delayedEffect.current.x, delayedEffect.current.y);
      window.requestAnimationFrame(animate);
    };

    const handleMouseMove = (e) => {
      const { clientX, clientY } = e;
      const { scrollX, scrollY } = window;
      mouse.current = {
        x: clientX + scrollX,
        y: clientY + scrollY,
      };
      moveCircle(mouse.current.x, mouse.current.y);
    };

    window.addEventListener('mousemove', handleMouseMove);

    animate();

    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
    };
  }, []);

  return (
    <AnimatePresence>
      <motion.div
        className="mask"
        initial={{ opacity: 1 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
        onClick={() => console.log('Mask clicked')} // Handle click event as needed
      >
        <div className="content">
          {/* Content to be revealed */}
        </div>
      </motion.div>
    </AnimatePresence>
  );
};

export default Mask;

CSS

.mask {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1000;
  width: 100vw;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  mask-image: url('../../public/ellipse.svg');
  mask-repeat: no-repeat;
  mask-size: 100px 100px;
  mask-position: center;
}

  • Currently the SVG is a circle as the mask, but I’m running into an issue where, even if I increase the size of the mask, the circular shape of the SVG limits the coverage due to its radius.

  • How can I modify the SVG circle or the mask settings so that it can cover the whole page? Should I consider a different approach or a different mask shape?

Future date transform to user timezone failed

enter code hereI am trying to make a function that parse event date and present it to use based on his timezone. SO this is the function:

import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";
dayjs.extend(utc);
dayjs.extend(timezone);

export const parseEventDate = (
  timeZone: string,
  eventData: {
    date: string;
    time: string;
    timeZone: string;
  }
) => {
  const eventDateTime = `${eventData.date} ${eventData.time}`;

  const gathering = dayjs.tz(eventDateTime, eventData.timeZone);

  const eventInLocalTime = gathering.tz(timeZone);

  const formattedEventTime = eventInLocalTime.format("YYYY-MM-DD HH:mm");

  return formattedEventTime;
};

This is how I test it:

log(
      "DATE 1",
      parseEventDate("Europe/Belgrade", {
        date: "2024-08-21",
        time: "16:00",
        timeZone: "Europe/Belgrade",
      })
    );
    log(
      "DATE 2",
      parseEventDate("America/New_York", {
        date: "2024-08-21",
        time: "16:00",
        timeZone: "Europe/Belgrade",
      })
    );

But instead of date time presented in timezone of the user I get for both: "2024-08-21 14:38".
I bang my head whole morning on this.
If it’s important I am using this in react-native and I am getting user timezone from phone but in this case (1st parameter) I hardcoded it to test.
Second parameter is object that contain information about event when and in what timezone it’s saved.
It should be different for New_York.

Giving complex names in css with webpack. But the classes in html do not change

I want to give complex class names in css with webpack, I have already done this. My current situation is that I import my css file to a js file and perform dynamic operations using the original names. When I build, it gives complex names that I use in the css and js files as I want. I also want to change the names of the classes in the tags used in the content of the html file I want, how can I do this?

original

.main {
  width:100%;
}
import styles from "./style.css"

document.body.className = styles.main // styles["main-lg"]

compiled

.vZzj7FyRHQ9JWz9k32ms {
    width:100%;
}
(()=>{"use strict";document.body.className="vZzj7FyRHQ9JWz9k32ms"})();

Configurations I used in my webpack.config.js file

const HtmlWebpackPlugin = require("html-webpack-plugin");
// const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");
//const webpack = require("webpack");

const isDevelopment = process.env.NODE_ENV === "development";


const rules = [{
        test: /.css$/,
        use: [
            { loader: isDevelopment ? "style-loader" : MiniCssExtractPlugin.loader },
            {
                loader: "css-loader",
                options: {
                    sourceMap: true,
                    importLoaders: 1,
                    modules: true,
                },
            },
            { loader: "postcss-loader" },
        ],
    },
    {
        test: /.html$/i,
        use: [{
                loader: "html-loader", // HTML dosyasını yükler
                options: {
                    sources: false,
                },
            },
        ],
    },
 
    {
        test: /.js$/,
        exclude: /node_modules/,
        //type: "javascript/esm",
        use: {
            loader: "babel-loader",
            options: {
                presets: ["@babel/preset-env"],
                plugins: ["@babel/plugin-syntax-top-level-await"],
            },
            // loader: "babel-loader",
            // options: {
            //   plugins: ["@babel/plugin-syntax-top-level-await"],
            // },
        },
    },
];

module.exports = {
 entry: {
        index: path.resolve(__dirname, "src", "index.js"),
    },
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "[contenthash].js",
    },
    module: { rules: rules },
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            filename: "index.html",
            template: "./src/index.html",
            hash: true,
            minify: {
                removeAttributeQuotes: true,
                collapseWhitespace: true,
                removeComments: true,
            },
        }),
        new MiniCssExtractPlugin({
            filename: "[contenthash].css",
            chunkFilename: "[name].css",
        }),
    ],
    optimization: {
        minimizer: [
            new TerserPlugin(),
            // new UglifyJsPlugin({
            //     uglifyOptions: {
            //         output: {
            //             comments: false,
            //         },
            //     },
            // }),
        ],
    },
};

All I want now is to change the classes in html just like in javascript.

The names in the css file and javascript changed with css-loader, but I could not change the classes in the html file.

React Chart.js is not rendering lines when state changes

I am using React Chart.js V2 and I am trying to update my chart when the state changes. However it is only rendering the y-labels on the left side and is not drawing the lines. The dataset and label syntax is completely fine (see the image). If i take the console logged result and take it as the initial chart js state value it works fine, but still doesn’t update on state change.

Dataset image

This is my code:

import { Line } from "react-chartjs-2";
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend,
} from 'chart.js';

ChartJS.register(
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend
);

const chartOptions = {
  responsive: true,
  interaction: {
    mode: 'index',
    intersect: false,
  },
  plugins: {
    title: {
      display: true,
      text: 'Chart.js Line Chart - Multi Axis',
    },
  },
  scales: {
    x: {
      ticks: {
        maxTicksLimit: 6
      }
    }
  }
};

export default function Home({ ranking }) {
  const refreshChart() => {
    ...
    console.log({
      datasets,
      labels: dateLabels
    })
    setChartData({
      datasets,
      labels: dateLabels
    })
  }

  useEffect(() => {
    if (!statisticsLoading)
      refreshChart()
  }, [statisticsTimeSpan, statisticsLoading])


    return (
        ...
        <Line
            className="mb-4"
            options={chartOptions}
            data={chartData}
            redraw
        />
    )
}

Problem with a component no re-rendering in a React app

I am learning React and I am currently working on a simple weather app as a way to practice. It works fine but I have been stuck on a problem for quite a while now.

The app has 2 pages (using react-router-dom), a home page with an input form to look for a city (using api.mapbox.com). When a city is clicked from the results list, there is a preview of the city weather (api.openweathermap.org), then the user can click on a + button to save this city (using local storage). The saved cities are showing as cards on the home page. It is possible to remove a city from the saved cities using a button at the bottom of the weather page. It simply removes the city from the array stored in the local storage, then it redirects to the home page.

The problem is that I still see the “removed” city card after the redirection, I have to refresh the page to see it removed. I think I need to use the useEffect hook to re-render the city list after having the city removed, but I can’t get it to work. I am missing something, but can’t figure out what.
Below is my CityList.jsx component, the one that renders the saved cities of the home page :

import { CityListCard } from "./CityListCard";

let savedCities

const getCities = async () => {
    if (localStorage.getItem('savedCities')) {
        savedCities = JSON.parse(localStorage.getItem('savedCities'))
        const OWMAppId = 'xxxxxxxxxxxxxxxxxxxxx'
        const units = 'metric'
        const langapi = 'en'

        savedCities.map(async (city, index) => {
            const response = await fetch(`https://api.openweathermap.org/data/3.0/onecall?lat=${city.coords.lat}&lon=${city.coords.lng}&exclude={part}&appid=${OWMAppId}&units=${units}&lang=${langapi}`, {
                headers: {
                    'Accept': 'application/json; charset=UTF-8'
                }
            })
            const data = await response.json()
            savedCities[index].weather = data
        })
    }
}

await getCities()

export function CityList() {
    return <div className="flex flex-col gap-4">
        {savedCities &&
            savedCities.map(city => (
                <CityListCard key={city.id} city={city} />
            ))
        }
    </div>
}

I think I have to add a useEffect with a dependency on savedCities, but as a hook cannot be inside a function, I don’t know how to make it work.

Any help appreciated

nodejs. read and execute function from file into another file

I created 10 js scripts that perform scraping actions (nodejs). They are composed as follows:

  • initial part: login
  • final part: specific actions for each script.

How can I externalize the login procedure in another file and include it? So that in case of changes, I would only change one file?

If it could be useful, I don’t need the file to be included to be .js. Even the “include txt” procedure, explode the content and run it, would be fine for me.

import test from './login_portale.js';


test()

JS Toast Notification Function – “element.classList is undefined” Error

I’m implementing a toast notification function in JavaScript. The code is very simple, so it’s self-explanatory:

HTML

<div id="notifications"></div>

JS

const notify = (type, text, autohide = true) => {
  const box = `<div class="notification ${type}">${text}<span onclick="notifyHide(parentNode)"></span></div>`;
  notifications.insertAdjacentHTML("afterbegin", box);
  if (autohide) setTimeout(() => {
    notifyHide(box);
  }, 5000);
};

const notifyHide = el => {
  el.classList.add("hide");
  setTimeout(() => {
    el.remove();
  }, 500);
};

THE ISSUE

When “autohide” is false, there’s no problem: clicking on “X”, the div element disappears (thanks to the added class “hide”), then is removed from the DOM.

Instead, when “autohide” is true, I get the following error: “Uncaught TypeError: el.classList is undefined”.

What’s the reason of that error?

const notify = (type, text, autohide = true) => {
  const box = `<div class="notification ${type}">${text}<span onclick="notifyHide(parentNode)"></span></div>`;
  notifications.insertAdjacentHTML("afterbegin", box);
  if (autohide) setTimeout(() => {
    notifyHide(box);
  }, 5000);
};

const notifyHide = el => {
  el.classList.add("hide");
  setTimeout(() => {
    el.remove();
  }, 500);
};

notify("success", "This works", false);
notify("error", "This doesn't work");
#notifications {
  bottom: 20px;
  max-width: calc(100% - 30px);
  position: fixed;
  right: 20px;
  width: 500px;
}

.notification {
  align-items: center;
  animation: grow 0.5s ease-in forwards;
  background-color: var(--bc);
  border-radius: 3px;
  box-shadow: 1px 1px 3px 0 rgba(0, 0, 0, .75);
  color: white;
  display: flex;
  font-size: 18px;
  justify-content: space-between;
  margin-top: 15px;
  padding: 15px;
  text-align: left;
}

.notification span {
  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABCklEQVQ4jYWTsYrDMBBEtzLG1XEYE/L/jbkqGJMimFRHOFKFVPmKI1w/L0WsnCxp4wUVlpan8c7IzMyATtIJ6CVV9qaACuiBb6ANmx1w5b8GoHYANTBGvVegNeCHvEZJC5CkGtgXek8231yqMSiaFZQAADsDGmCSRGGNkj4k7cMeEJ8fXoqBRtLRAf3G3xFkAhpL/rkBPFAKmSQtAdH0X4rCjYl8gFxBWpJaSXdniHfg8y1gxYXMtZKCOnZhZWU5WgP8rYJ4voXRkT5J6oCjcz5Iqgz48gDBBZ6B9EC9SToXpGY5YLYfSHvPBmyAW5SJA04OSJ4IcAM2YbBb4ALsXPuWoEHSBdiamT0AyQw4IRLJeTkAAAAASUVORK5CYII=);
  cursor: pointer;
  height: 17px;
  margin-left: 20px;
  width: 17px;
}

.notification.success {
  --bc: #55B559;
}

.notification.error {
  --bc: #EA4333;
}

.notification.hide {
  animation: shrink 0.3s ease-out forwards;
  pointer-events: none;
}

@keyframes grow {
  from {
    opacity: 0;
    transform: scale(0.8);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes shrink {
  to {
    opacity: 0;
    transform: scale(0.8);
  }
}
<div id="notifications"></div>

Is there a waitTime like paramter in react-speech-recognition library?

I am using react-speech-recognition for speech-to-text.
I want my code to only stop listening when the user has not spoken for 3 continuous seconds. For now, it stops listening as soon as the user stops speaking. Is there already a workaround available for this?

My cuurent implementation is const { transcript, resetTranscript, listening } = useSpeechRecognition({ commands, });

if (isUserCalling.current) { SpeechRecognition.startListening({ language: selectedLanguage }); }

My react and javascript knowledge is at the beginner level. Please do let me know if further details are needed.

For reference, I am trying to implement this repo: https://github.com/shihui-huang/react-voice-chatbot?tab=readme-ov-file