How to “stop” an element after scrolling to another element

I am trying to emulate the “Engage. Involve. Connect” widget on this page: https://themeworks.com/. Basically, that widget stays set to the bottom of the page until the user scrolls, where it then parks itself right above the “Experiences shape us.” text.

I am currently working on creating a similar widget at https://williamh117.sg-host.com/. I’m struggling finding a way to get the #widget / #unanchored element to “stop” upon scrolling to “.xp”, a class that is contained by the “Experiences shape us.” element.

Here is my current JavaScript:

window.addEventListener('scroll', function() {
  var widget = document.getElementById('widget');
  var xpElement = document.querySelector('.xp');
  var widgetHeight = widget.offsetHeight;
  var xpPosition = xpElement.getBoundingClientRect().top;
  var windowHeight = window.innerHeight;

  var distance = xpPosition - windowHeight + widgetHeight;

  if (distance <= 0) {
    // If the widget encounters the '.xp' element, un-anchor it and let it scroll with the page content
    widget.classList.add('unanchored');
  } else {
    // If the widget is still anchored, position it fixed at the bottom of the viewport
    widget.classList.remove('unanchored');
  }
  
  // Set the height of .xp element dynamically
  xpElement.style.setProperty('--xp-height', widgetHeight + 'px'); // Set xpHeight to widgetHeight
});

Here is my HTML:

<h3 id="widget" class="wp-block-heading has-text-align-center frontpage ticss-f97cde6c has-white-color has-text-color has-background" style="background-color:#00000087;font-size:39px">Engage. &nbsp; Involve. &nbsp; Connect.<br><span class="text frontpage2" style="font-weight: 200 !important;">We fuse Art + Engineering to create world-class experiences.</span><br><a href="https://williamh117.sg-host.com/#spacestop"><i class="arrow down"></i></a></h3>

Here is my CSS:

.unanchored {
  position: fixed !important; /* Change position to fixed */
  bottom: 300px !important;
  top: calc(100% - var(--widget-height) - 30px); /* Adjust this value to set the desired distance from .xp */
  left: 0 !important;
    margin-bottom:0px !important;
}

.xp {
  --widget-height: 30px; /* Adjust this value to match the height of your widget */
  position: relative; /* Keep position relative */
}

#widget {
  position: fixed;
  bottom: 0;
  left: 0;
  background-color: #f0f0f0;
  width: 100%;
  text-align: center;
  transition: bottom 0.3s ease-in-out;
    z-index:1000 !important;
    scroll-behavior: smooth !important;
}

Thank you in advance for any and all advice.

Move elements to first position in nested array

I want to move an element to first position from an inner array like below

{
 "activeContainerId": "955bd18f-6561-44b4-ba8f-7094e4e183b8",
  "amendCartContainers": [],
  "data": [
    {
        "id": "955bd18f-6561-44b4-ba8f-7094e4e183b8",
        "categoryName": "My_Category_Name",
        "categoryId": "cat_spc_my_category",
        "sections": [
            {
                "id": "cat_spc_my_id",
                "title": "APPLE",
                "items": [
                    {
                        "id": "a6d89ee2-6832-43e4-85ea-6ec541f06c36",
                        "action": "add",
                        "title": "Apple iPhone 11",
                        "characteristics": [
                            ----
                        ],
                        "promotions": [],
                        "quantity": 1,
                        "oneTimePrice": [
                            {
                                ----
                            }
                        ],
                        "recurringPrice": [],
                        "totalOneTimePrice": [
                            {
                                ----
                            }
                        ],
                        
                    }
                ]
            },
            {
                "id": "cat_spc_my_id2",
                "title": "My_Title2",
                "items": [
                    {
                        "id": "0ea7cade-96e0-4e5d-8baf-ace2f7ce123f",
                        "action": "add",
                        "title": "My Inner title2",
                        "characteristics": [],
                        "promotions": [],
                        "quantity": 1,
                        "addedBySCRuleEngine": true,
                        "oneTimePrice": [
                            {
                                ----
                            }
                        ],
                        "recurringPrice": [],
                        "totalOneTimePrice": [
                            {
                                ----
                            }
                        ],
                        "totalPriceRecurring": []
                    }
                ]
            },
            {
                "id": "cat_spc_my_special_id",
                "title": "my_special_title",
                "items": [
                    {
                        "id": "870d3871-6a0c-42f2-b123-9d75a3f3e3ee",
                        "action": "add",
                        "title": "my inner title3",
                        "characteristics": [],
                        "promotions": [
                            {
                                ----
                            }
                        ],
                        "quantity": 1,
                        "itemTerm": [
                            {
                                "duration": {
                                    "amount": 12,
                                    "units": "Month"
                                }
                            }
                        ],
                        "oneTimePrice": [
                            {
                                -----
                            }
                        ],
                        "recurringPrice": [
                            {
                                -----
                            }
                        ],
                        "totalOneTimePrice": [
                            {
                                -----
                            }
                        ],
                        "totalPriceRecurring": [
                            {
                                -----
                            }
                        ]
                    }
                ]
            },
            {
                "id": "cat_spc_my_id4",
                "title": "my_title4",
                "items": [
                    {
                        "id": "1011730c-d8d2-45ac-8ee2-98f981184a85",
                        "action": "add",
                        "title": "my_title4",
                        "characteristics": [],
                        "promotions": [],
                        "quantity": 1,
                        "oneTimePrice": [
                            {
                                -----
                            }
                    }
                ]
            }
        ],
        "totalPriceOneTime": [
            {
                ----
            }
        ],
        "totalPriceRecurring": [
            {
                ----
            }
        ],
        "promotions": [],
        "notes": [],
        "processContext": "ACQ",
        "visibilityInSection": {
            "id": "bo_lov_visibilityinsection_section1",
            "name": "Section 1",
            "visibilityOrder": 1
        }
    }
],
"applyCouponStatus": null,
"promotions": [],
"totalPriceOneTime": [
    {
        "dutyFreeAmount": {
            "unit": "price_unit",
            "value": 479.68
        },
        "taxIncludedAmount": {
            "unit": "price_unit",
            "value": 580.41
        },
        "dutyFreeAlteredAmount": {
            "unit": "price_unit",
            "value": 479.68
        },
        "taxIncludedAlteredAmount": {
            "unit": "price_unit",
            "value": 580.41
        },
        "taxAmount": 100.73,
        "amountPayable": {
            "unit": "price_unit",
            "value": 580.41
        }
    }
],
"totalPriceRecurring": [
    {
        "dutyFreeAmount": {
            "unit": "price_unit",
            "value": 41.32
        },
        "taxIncludedAmount": {
            "unit": "price_unit",
            "value": 50
        },
        "dutyFreeAlteredAmount": {
            "unit": "price_unit",
            "value": 24.79
        },
        "taxIncludedAlteredAmount": {
            "unit": "price_unit",
            "value": 30
        },
        "taxAmount": 5.21,
        "amountPayable": {
            "unit": "price_unit",
            "value": 30
        }
    }
 ]
}

There are 4 items currently in the above array and I want to filter and move the id ‘cat_spc_my_special_id’ from ‘data.sections to the top of list. Keyword that I want to use is ‘special’ in this case.

I have tried below

Try1:

let filterKey = 'special';
const shoppingBagNew = shoppingBag?.data?. 
[0]?.sections.filter(function(x,y){
   return x == filterKey ? -1 : y == filterKey ? 1 : 0;
})

Try2:

const sections = shoppingBag?.data?.[0]?.sections;
const RedIndex = shoppingBag?.data?.[0]?.sections.findIndex(section => 
section.name == 'special');
 shoppingBag?.data?.[0]?.sections.push(...sections.splice(0, RedIndex));
 console.log('shoppingBag after filter',shoppingBag);

I knew that moving to the top of list is possible for only normal array of items which is not a nested array but Is this possible for a nested array like above? Any help would be appreciated..! Thanks.

Firestore onSnapshot() is being called on getDocs(). how to prevent that? [duplicate]

My expectation is to observe the changes of my collection only when there is a WRITE/DELETE action. By doing some search I understood onSnapshot() method does that. But this method unexpectedly is being called when I’m reading my documents by getDocs().
Here is my code:

// Firestore instance is defined and collection reference is accessible

const db = getFirestore();
const todosCollection = collection(db, 'todos');

// For the sake of testing I even tried to stop the observer at the fetch method by using a boolean variable
let areTodosFetched = false;

function onTodosChange() {
    if (!areTodosFetched) {
      console.log('should return');
      return;
    }
    onSnapshot(todosCollection, (snapShot) => {
      snapShot.docChanges().forEach((change) => {
        if (change.type === 'added') {
          // The code drops in this block!
          console.log('New todo: ', change.doc.id);
        }
        if (change.type === 'modified') {
          console.log('Modified todo: ', change.doc.id);
        }
        if (change.type === 'removed') {
          console.log('Removed todo: ', change.doc.id);
        }
      });
    });
  }


async function getTodos() {
    try {
      await getDocs(todosCollection);
      areTodosFetched = true;
    }
    catch (error) {
      console.error('Error getting documents: ', error);
    }
  }


// In a component I'm executing them
await getTodos();
onTodosChange();

I removed all side effects of getTodos() method and I’m only calling await getDocs(todosCollection);

But still the observer is being called.

The file name when I downloaded it was object object

Here is body request enter image description here
Here is my code

fetch(`${proxy()}${dataUrlExport}`, {
      method: "POST",
      headers: {
        "content-type": "application/json",
        Accept:
          exportType === "excel"
            ? "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            : "text/csv",
      },
      body: JSON.stringify(exportBody),
    })
      .then((res) => res.blob())

      .then((blob) => {
        if (exportType === "csv") {
          const bom = new Uint8Array([0xef, 0xbb, 0xbf]);
          const withBom = new Blob([bom, blob], { type: "text/csv" });
          blob = withBom;
        }
        const url = window.URL.createObjectURL(blob);
        ////////console.log(1300, url)
        const a = document.createElement("a");
        a.style.display = "none";
        a.href = url;

        const datetimeString = getCurrentDateTimeForFilename();

        const segments = page.page_title.split("/");
        const lastSegment = segments[segments.length - 1]; //tĂȘn
        const result = lastSegment.replace(/-/g, "");
       
        a.download =
          exportType === "excel"
            ? `DATA_${result.toUpperCase()}_${exportBody.criteria}_${datetimeString}.xlsx`
            : `DATA_${result.toUpperCase()}_${datetimeString}.csv`;

        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
        setLoadingExportFile(false);
        setSelectedFields([]);
        setSelectAll(false);

I want it to be included when I download the file name is exportBody.criteria: RF20243220001 but I get object

How do I get it and assign it to the filename?

tks guys

Looking for a way to sort a specific section alphabetically

An old acquaintance assisted me with the code below for occupation claims for writing forum and currently it alphabetizes names pulled from a member list but I would like it to alphabetized by EMPLOYER (.employer) instead, which appears beneath each “job-list” section.

Currently it sorts alphabetically by character/name:

“District Businesses

Labrinyth John Doe

Cascade Karen Doe”

but I would like it to be alphabetical by employer:

“District Businesses

Cascade Karen Doe

Labrinyth John Doe”

    const name1 = [
        ["Name1 Businesses"]
    ];
    const name2 = [
        ["Name2 Businesses"]
    ];
    const name3 = [
        ["Title1"],
        ["Name 3 Businesses"]
    ];
    const name4 = [
        ["Title2"],
        ["Name 4 Businesses"]
    ];
    
    const jobslist = [name1, name2, name3, name4];

    function getCharacters() {
        $.get("/index.php?act=Members&max_results=1000&", function (data) {
            var doc = new DOMParser().parseFromString(data, 'text/html');
            $(".claims-info:not(.Admin):not(.Staff):not(.OOC):not(.Archived):not(.Applying)", doc).each(function () { 
                let job = $(this).find('.employer').text(); 
                if (job == '') job = "Other";
                let claim = $(this).find('.occupation').text(); 
                let employer = $(this).find('.employer').text(); 
    
                jobslist.forEach((district) => {
                    district.forEach((e) => {
                        if (e[0] == job) {
                            e.push(`${claim} ${$(this).find('.name').html()}</p>`)
                        }
                    });
                });
            });
                    
            let group = 0
            jobslist.forEach((district) => {
                    listName = getList(group)[1];
                    jobs = getList(group)[0];
                    district.forEach((job) => {
                        $('#dirjobs' + listName).append(`<div class="contentnote" id="${job[0].replace(/[ ']/g, '')}"><h2>${job[0]} <line></line></h2><div class="job-list"></div></div>`);
                        job.slice(1).forEach((claim) => {
                            $(`#${job[0].replace(/[ ']/g, '')} .job-list`).append(claim);
                        });
                    });
                    group++;
                });
        });
    }
    
    function getList(a) {
        switch (a) {
            case 0:
                return [name1, 'name1']
                break;
            case 1:
                return [name2, 'name2']
                break;
            case 2:
                return [name3, 'name3']
                break;
            case 3:
                return [name4, 'name4']
                break;
        default:
            console.log('list not defined')
        }
    }
        
        getCharacters();

I’ve tried implementing sort elements but with no luck, likely because I am not targeting the correct thing (as I have managed to change other sections, but not the employer section I’m trying to change). I am VERY MUCH a novice but learning quite a bit as I go but this is beyond my abilities at the moment. Can anyone assist with suggestions on how to best do this? Thank you in advance!

OpenAI Beta Assistant stream response in NextJS

I’m developing an App using the OpenAI API. I’m using the assistant API because I’m training an assistant to answer based on one specific document I’ve already uploaded at https://platform.openai.com/playground?assistant.

The documentation of OpenAI about the streaming answers leads me to this code:

   const { messages } = await request.json();
   const userMessage = messages && messages[messages.length - 1];

   const thread = await openai.beta.threads.create();
   
   const message = await openai.beta.threads.messages.create(thread.id, {
      ...userMessage,
   });

   let resp = '';

   const run = openai.beta.threads.runs.createAndStream(thread.id, {
      assistant_id: process.env.OPENAI_TABLE_23A_ASSISTANT_ID as string,
   });

   const stream = run.on('textDelta', (textDelta) => {
      // console.log(textDelta.value);
      resp = resp + textDelta.value!;
      return textDelta.value;
   });

   await run.finalRun();

I tested it and the streaming is working on run.on() but I need to pass that response as a stream to the user interface chat section.

At client I’m using:

   // Vercel AI imports
   import { useChat } from 'ai/react';

   export default function ChatIpunt({ isDrawerOpen }: ChatInputProps) {
      const {
         input,
         handleInputChange: aiInputChange,
         handleSubmit,
         isLoading: aiIsLoading,
         messages,
      } = useChat();

      // ...rest of my code

I’m just missing how to pass the stream to the client.

I’ll be so grateful with your help and I hope this can also help other developers

This is my full code

   import { NextRequest, NextResponse } from 'next/server';
   import { openai } from '@/lib/openai';

   export const runtime = 'edge';

   export async function POST(request: NextRequest, response: NextResponse) {
      try {
         const { messages } = await request.json();

         const userMessage = messages && messages[messages.length - 1];

         const thread = await openai.beta.threads.create();

         const message = await openai.beta.threads.messages.create(thread.id, {
            ...userMessage,
         });

         console.log(message);

         let resp = '';

         const run = openai.beta.threads.runs.createAndStream(thread.id, {
            assistant_id: process.env.OPENAI_TABLE_23A_ASSISTANT_ID as string,
         });

         const stream = run.on('textDelta', (textDelta) => {
            // console.log(textDelta.value);
            resp = resp + textDelta.value!;
            return textDelta.value;
         });

         await run.finalRun();

         return new NextResponse(resp);
   } catch (error) {
      console.error('Error occurred:', error);

      return {
         status: 500,
         body: JSON.stringify({ error: 'An error occurred' }),
         headers: {
            'Content-Type': 'application/json',
         },
      };
   }
}

How to disable mobile input auto zoom like some websites and Stack Overflow

On iPhone if text input’s font-size is less than 16px, it automatically zooms in. I didn’t wanted to add since its not recommended, but tried the meta viewport hacks, but it didn’t worked too, here is my viewport:

<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1, user-scalable=no" />

But I’ve saw many websites that has input less than 16px and it doesn’t zoom in to input on my mobile, even without viewport values user-scalable=no or maximum-scale=1 and one of that websites is Stack Overflow.

Stack Overflow example here with 13px input size and doesn’t has particular viewports tags that every post on internet says its needed to disable input zoom in.

enter image description here

Is there some knowledge that passess in secret to disable this zoom? I’ve checked many articles but all of them is limited to what I tried/mentioned above. I’m guessing there might be a JavaScript hack for this but my attempts of preventDefault on focus, click etc. failed.

Why is this component rerendering?

I’m was trying to ensure my knowledge of how React compares states and rerenders components and I’ve struggled to understand why this behaviour takes place:
I have simple component with two buttons and two state variables. Increment button is for incrementing counter, and Re-render button for triggering rerender. Counter state is an object with value property, which is an actual numeric counter. Trigger is just a boolean, which value is not used anywhere. Increment state update is done intentionally wrong just to check how the state is compared.

function App() {
  const [counter, setCounter] = useState({
    value: 0,
  })
  const [trigger, setTrigger] = useState(false)
  console.log('Rendered ', Date.now())
  console.log('State: ', {counter, trigger})
  return (
    <>
      <h1>Object State</h1>
      <p>Counter: {counter.value}</p>
      <button onClick={() => {
        counter.value++
        setCounter(counter)
      }}> Increment</button>
      <button onClick={() => {
        setTrigger(!trigger)
      }}> Re-render</button>
    </>
  )
}

Clicking Increment does nothing as expected. When I click Re-render button, component is rerendered as expected and current counter value is shown. At this point all works as expected. But if after clicking Re-render, I click Increment, I see in console that the component was invoked, although displayed counter value wasn’t updated. It seems like the output is discarded. Clicking Increment after that does not have any effect and the component is not invoked. Why this unexpected invoke is happening and why it’s happening only once util next Re-render click?

I expect component to never invoke on Increment click. Actually it’s being invoked once on Increment click after Re-render click.

“Encrypt/Decrypt” is not defined while exporting nodule to an HTML file from a JS file

I am creating a program that emulates the Vigenere cipher algorithm in JavaScript. I am also creating an HTML page that would allow a user to type in a plain text phrase and encrypt/decrypt the message. When I type my plaintext message and enter in a key value, I get an error message ‘encrypt is not defined.’ I do not believe that my .js file is importing my functions correctly, or if the file is importing the functions, then I am not seeing my error. Could I get some insights into why I am not reaching my desired output?

function encrypt(plaintext, key) {
    if (!plaintext || !key || typeof plaintext !== 'string' || typeof key !== 'string' || key.match(/[^a-zA-Z]/)) {
        throw new Error('Invalid input: plaintext and key must be non-empty strings containing only alphabetic characters.');
    }

    var ciphertext = "";
    var keyIndex = 0;

    for (var i = 0; i < plaintext.length; i++) {
        var char = plaintext[i];

        if(/[a-zA-Z]/.test(char)) {
            var isUpperCase = char === char.toUpperCase();
            var plainCharCode = char.toUpperCase().charCodeAt(0) - 65;
            var keyCharCode = key[keyIndex % key.length].toUpperCase().charCodeAt(0) - 65;
            var encryptedCharCode = (plainCharCode + keyCharCode) % 26 + 65;

            ciphertext += isUpperCase ? String.fromCharCode(encryptedCharCode) : String.fromCharCode(encryptedCharCode).toLowerCase();
            keyIndex++;
        } else {
            ciphertext += char;
        }
    }

    return ciphertext;
}

function decrypt(ciphertext, key) {
    if (!ciphertext || !key || typeof ciphertext !== 'string' || typeof key !== 'string' || key.match(/[^a-zA-Z]/)) {
        throw new Error('Invalid input: ciphertext and key must be non-empty strings containing only alphabetic characters.');
    }

    var plaintext = "";
    var keyIndex = 0;

    for (var i = 0; i < ciphertext.length; i++) {
        var char = ciphertext[i];

        if (/[a-zA-Z]/.test(char)) {
            var isUpperCase = char === char.toUpperCase();
            var cipherCharCode = char.toUpperCase().charCodeAt(0) - 65;
            var keyCharCode = key[keyIndex % key.length].toUpperCase().charCodeAt(0) - 65;
            var decryptedCharCode = (cipherCharCode - keyCharCode + 26) % 26 + 65;

            plaintext += isUpperCase ? String.fromCharCode(decryptedCharCode) : String.fromCharCode(decryptedCharCode).toLowerCase();
            keyIndex++;
        } else {
            plaintext += char;
        }
    }

    return plaintext;
}

export { encrypt, decrypt };
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Assignment 4 - JavaScript</title>
  <script src="vigenere.js"></script>
  <style>
    .container {
      width: 50%;
      margin: auto;
    }
    .result {
      margin-top: 20px;
    }
    .error {
      color: red;
    }
  </style>
</head>
<body>
  <div class="container">
    <h2>Vigenere Cipher</h2>
    <form id="cipherForm">
      <div>
        <label for="plaintext">Plaintext:</label><br>
        <textarea id="plaintext" name="plaintext" rows="4" cols="50"></textarea>
      </div>
      <div>
        <label for="key">Key:</label><br>
        <input type="text" id="key" name="key">
      </div>
      <div>
        <button type="button" onclick="encryptText()">Encrypt</button>
        <button type="button" onclick="decryptText()">Decrypt</button>
      </div>
      <div class="result">
        <label for="ciphertext">Ciphertext:</label><br>
        <textarea id="ciphertext" name="ciphertext" rows="4" cols="50" readonly></textarea>
      </div>
      <div class="error" id="errorMessage"></div>
    </form>
  </div>

  <script>
    function encryptText() {
      var plaintext = document.getElementById("plaintext").value;
      var key = document.getElementById("key").value;
      try {
        var ciphertext = encrypt(plaintext, key);
        document.getElementById("ciphertext").value = ciphertext;
        document.getElementById("errorMessage").textContent = ""; // Clear any previous error messages
      } catch (error) {
        document.getElementById("errorMessage").textContent = error.message;
      }
    }

    function decryptText() {
      var ciphertext = document.getElementById("ciphertext").value;
      var key = document.getElementById("key").value;
      try {
        var plaintext = decrypt(ciphertext, key);
        document.getElementById("plaintext").value = plaintext;
        document.getElementById("errorMessage").textContent = ""; // Clear any previous error messages
      } catch (error) {
        document.getElementById("errorMessage").textContent = error.message;
      }
    }
  </script>
</body>
</html>

Elements jumping on the screen non-stop, when element is on the edge of being in intersection (Intersection Observer)

I have a page with a sticky footer with stacked buttons, when the footer is not entirely on viewport I hide one of the buttons, when the footer is in place I show the buttons, the problem is when the container is on the edge, because then it starts flickering.

it flickers because the container gets bigger as we add the second button (when it enters fully viewport), and because it gets bigger, it makes the container not be fully visible again.

Is there a way to go around it? I’ve added a gif and a codepen to the issue.

https://codepen.io/felipefernand3s/pen/OJGgMOK

I just want to have a footer with stacked buttons, the footer and one of the buttons are always visible, but when the footer is pinned (it means it’s in it’s correct html place instead of “floating”, I want to show all stacked buttons.

const el = document.querySelector(".myElement")
const observer = new IntersectionObserver( 
  ([e]) => e.target.classList.toggle("is-pinned", e.intersectionRatio < 1) || console.log(e.intersectionRatio),
  { threshold: [0] }
);

observer.observe(el);

Group Bar chart tooltips showing time data as points instead of formatted HH:MM:SS in React Chart.js

I’m working on a React application that utilizes Chart.js to display bar charts. I’m encountering an issue where the tooltips in the bar chart display time data as points instead of the desired formatted HH:MM:SS. I’ve tried several approaches to format the tooltips correctly, but none of them have worked so far.

Details:

When hovering over the bars in the chart, the tooltips display the time data in points (e.g., 1.5, 2.3) instead of the desired format HH:MM:SS (e.g., 01:00:00, 02:00:00).

I’ve implemented a custom tooltip callback function within the Chart.js options to convert the total seconds to HH:MM:SS format. However, this approach hasn’t resolved the issue.

Code:

import {
    BarElement,
    CategoryScale,
    Chart as ChartJS,
    Legend,
    LinearScale,
    Title,
    Tooltip,
} from 'chart.js';
import React from 'react';
import { Bar } from 'react-chartjs-2';

ChartJS.register(
    CategoryScale,
    LinearScale,
    BarElement,
    Title,
    Tooltip,
    Legend
);
export function convertTimeFormat(fractionalHour) {
  // Convert fractional part to minutes
  var minutes = Math.floor((fractionalHour % 1) * 60);

  // Extract whole number part as hours
  var hours = Math.floor(fractionalHour);

  // Convert remaining decimal part to seconds
  var seconds = Math.floor(((fractionalHour % 1) * 60 - minutes) * 60);

  // Format the time as HH:MM:SS
  var formattedTime = padZero(hours) + ":" + padZero(minutes) + ":" + padZero(seconds);

  return formattedTime;
}

const options = {
    responsive: true,
    maintainAspectRatio: false,

    plugins: {
        legend: {
            display: false,
            position: 'top',
        },
    },
    tooltip: {
        callbacks: {
            label: function (tooltipItem, data) {
                return convertTimeFormat(tooltipItem.parsed);
            },
        }
    },
    scales: {
        x: {
            ticks: {
                autoSkip: true,
                // maxTicksLimit: 12, // Set the maximum number of x-axis ticks
            },
            grid: {
                display: false, // Hide vertical grid lines
            },
        },
        y: {
            ticks: {
                min: 0, // Set the minimum value for the y-axis
                max: 20, // Set the maximum value for the y-axis
                maxTicksLimit: 6, // Set the maximum number of x-axis ticks

                callback: function (value, index, values) {
                    
                    return value
                },
            },
        },
    },
};


// Initialize the usedColors array outside the component or wherever you are managing state
const usedColors = [];


// Function to generate a random color
function getRandomColor() {
    const colors = ["#FFD147", "#BD9AF8", "#B6F09C", "#FF9C9C", "#9ADBF8", "#9CF8E8", "#F8E89A", "#F89A9A", "#F89AD3", "#9AF8B5"];

    // Filter out used colors
    const availableColors = colors.filter(color => !usedColors.includes(color));

    // If there are available colors, use one of them; otherwise, generate a new light color
    if (availableColors.length > 0) {
        const randomIndex = Math.floor(Math.random() * availableColors.length);
        const color = availableColors[randomIndex];
        usedColors.push(color);
        return color;
    } else {
        const lightColor = generateLightColor();
        usedColors.push(lightColor);
        return lightColor;
    }
}

function generateLightColor() {
    const letters = '89ABCDEF';
    let color = '#';
    for (let i = 0; i < 6; i++) {
        color += letters[Math.floor(Math.random() * 8)];
    }
    return color;
}
export function DashGroupBarChart({ styles, barData }) {
    
    const dates = barData?.map(entry => entry?.date);
    const usernames = Array.from(new Set(barData.flatMap(entry => entry.data.map(item => item.username))));
    const datasets = usernames.map(username => ({
        label: username,
        data: dates.map(date => {
            const dateEntry = barData.find(item => item.date === date);
            const userData = dateEntry ? dateEntry.data.find(item => item.username === username) : null;
            return userData ? userData.totalWorkTimeInSeconds / 3600 : 0;
        }),
        backgroundColor: getRandomColor(),
        borderWidth: 0,
        barPercentage: 1,
        categoryPercentage: 0.5,
        borderRadius: 3,
    }));
    const data = { labels: dates, datasets };
    return <div style={{ width: "100%", height: "100%", ...styles }}>
        <Bar options={options} data={data} />
    </div>;
}

DashGroupBarChart.defaultProps = {
    styles: {},
    barData: []
}

And the data format i am passing to CharComponent

[
    {
        "date": "2024-03-18",
        "data": [
            {
                "username": "smith",
                "totalWorkTimeInSeconds": 12260
            },
            {
                "username": "alena",
                "totalWorkTimeInSeconds": 12727
            },
            {
                "username": "nadir",
                "totalWorkTimeInSeconds": 2759
            },
            {
                "username": "noman",
                "totalWorkTimeInSeconds": 7878
            },
            {
                "username": "adam",
                "totalWorkTimeInSeconds": 11758
            }
        ]
    },
    {
        "date": "2024-03-19",
        "data": [
            {
                "username": "alena",
                "totalWorkTimeInSeconds": 31609
            },
            {
                "username": "jhon",
                "totalWorkTimeInSeconds": 1449
            },
            {
                "username": "noman",
                "totalWorkTimeInSeconds": 4745
            },
            {
                "username": "adam",
                "totalWorkTimeInSeconds": 14266
            },
            {
                "username": "atif",
                "totalWorkTimeInSeconds": 7
            },
            {
                "username": "bob",
                "totalWorkTimeInSeconds": 5086
            }
        ]
    },
    {
        "date": "2024-03-20",
        "data": [
            {
                "username": "smith",
                "totalWorkTimeInSeconds": 13979
            },
            {
                "username": "alena",
                "totalWorkTimeInSeconds": 1492
            },
            {
                "username": "noman",
                "totalWorkTimeInSeconds": 8335
            },
            {
                "username": "adam",
                "totalWorkTimeInSeconds": 7532
            },
            {
                "username": "bob",
                "totalWorkTimeInSeconds": 3839
            }
        ]
    },
    {
        "date": "2024-03-21",
        "data": [
            {
                "username": "smith",
                "totalWorkTimeInSeconds": 11300
            },
            {
                "username": "alena",
                "totalWorkTimeInSeconds": 26813
            },
            {
                "username": "adam",
                "totalWorkTimeInSeconds": 13168
            },
            {
                "username": "bob",
                "totalWorkTimeInSeconds": 1386
            }
        ]
    },
    {
        "date": "2024-03-22",
        "data": [
            {
                "username": "smith",
                "totalWorkTimeInSeconds": 5281
            },
            {
                "username": "alena",
                "totalWorkTimeInSeconds": 21844
            },
            {
                "username": "jhon",
                "totalWorkTimeInSeconds": 20251
            },
            {
                "username": "adam",
                "totalWorkTimeInSeconds": 1987
            },
            {
                "username": "bob",
                "totalWorkTimeInSeconds": 15102
            }
        ]
    },
    {
        "date": "2024-03-23",
        "data": [
            {
                "username": "smith",
                "totalWorkTimeInSeconds": 7635
            },
            {
                "username": "bob",
                "totalWorkTimeInSeconds": 14660
            }
        ]
    },
    {
        "date": "2024-03-24",
        "data": [
            {
                "username": "smith",
                "totalWorkTimeInSeconds": 17819
            },
            {
                "username": "alena",
                "totalWorkTimeInSeconds": 17999
            },
            {
                "username": "jhon",
                "totalWorkTimeInSeconds": 3235
            },
            {
                "username": "bob",
                "totalWorkTimeInSeconds": 10241
            }
        ]
    },
    {
        "date": "2024-03-25",
        "data": [
            {
                "username": "smith",
                "totalWorkTimeInSeconds": 11338
            },
            {
                "username": "adam",
                "totalWorkTimeInSeconds": 3325
            }
        ]
    }
]

Sending functions as props to Shadcn UI Table

I am using a Data Table from Shadcn in a React project with Typescript. I wanted to an Actions menu with a Dropdown list as listed in the example.

"use client";

import { ColumnDef } from "@tanstack/react-table";
import { MoreHorizontal } from "lucide-react";
import { dataRowRow } from "../../common/Types";

import { Button } from "../ui/button";
import "./Columns.css";

import {
    DropdownMenu,
    DropdownMenuContent,
    DropdownMenuItem,
    DropdownMenuLabel,
    DropdownMenuSeparator,
    DropdownMenuTrigger,
} from "../ui/dropdown-menu";

export const columns: ColumnDef<dataRowRow>[] = [
    {
        accessorKey: "locationName",
        header: "Location",
    },
    {
        accessorKey: "status",
        header: "Status",
    },

    {
        id: "actions",
        header: "Actions",
        cell: ({ row }) => {
            const dataRow = row.original;

            return (
                <DropdownMenu>
                    <DropdownMenuTrigger asChild>
                        <Button variant="ghost" className="h-8 w-8 p-0">
                            <span className="sr-only">Open menu</span>
                            <MoreHorizontal className="h-4 w-4" />
                        </Button>
                    </DropdownMenuTrigger>
                    <DropdownMenuContent align="end">
                        <DropdownMenuLabel>Actions</DropdownMenuLabel>
                        <DropdownMenuItem onClick={() => console.log(dataRow)}>
                            Edit dataRow
                        </DropdownMenuItem>
                        <DropdownMenuItem>Delete dataRow</DropdownMenuItem>
                        <DropdownMenuItem>Generate URL</DropdownMenuItem>
                        <DropdownMenuSeparator />
                        <DropdownMenuItem
                            onClick={() =>
                                navigator.clipboard.writeText(dataRow.url)
                            }
                        >
                            Copy upload URL
                        </DropdownMenuItem>
                    </DropdownMenuContent>
                </DropdownMenu>
            );
        },
    },
];

The copy to clipboard function works without a hitch. However, how could I send another function as a parameter to the component to manage for example the deletion of a row?

Like saving the row in a state and opening a modal that manages the API call for example?

jQuery appended html code CSS not working

My code html code:

<head>
    <link rel="stylesheet" href="Stylesheet.css">
</head>
<body>
    <div id="mydiv">
        <p class="myclass">hello world</p>
    </div>
</body>

works perfectly fine and my css styling gets applied correctly.

But when I try to add the html via jquery (or java script innerHtml), the CSS styling doesn’t get applied:

 <head>
    <link rel="stylesheet" href="Stylesheet.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script src="Javascript.js"></script>
</head>
<body>
    <div id="mydiv">
    </div>
</body>

Javascript.js:

$( document ).ready(function() {
   $('#mydiv').append('<p class="myclass">hello world</p>');
});

Is there any way to fix this? Or better way of doing it?

Hack to love of life [closed]

Pretend to be love and basic human need of independence love,how does it effect human nature?
Easy way to hack into human nature principles should be dedicated
Does love discipline the world.

Positive feedback with clear possibility if any.