How to send Google Analytics 4 e-commerce events using @next/third-parties/google package and sendGTMEvent function in Next.js?

We have a Next.js app that uses Pages Router. For the purposes of analytics, we implemented GA4 via GTM. This works fine for basic (and enhanced) tracking, but we need to send specific e-commerce events too, mostly add_to_cart and purchase events.

Next’s “third-parties” library exposes some components and functions, and their docs say that, for sending GA4 events, we shouldn’t use the “sendGAEvent” function (which also then needs GoogleAnalytics component too, which is not desired when GoogleTagManager component is already used), but instead, if we use Google Tag Manager for GA4 configuration, we should use that. For this the same library has “sendGTMEvent” function, but unlike sendGAEvent that accepts an array of arguments much like gtag function from Google itself, this function excepts Object…

Anyhow, in our _app.js file we initiate the GoogleTagManager:

import {GoogleTagManager} from '@next/third-parties/google';

return <>
  <GoogleTagManager gtmId='GTM-SOME_VALUE' />
</>

Now we need a way to use “sendGTMEvent” function to replace official code by google that uses gtag function, for example:

gtag("event", "add_to_cart", {
  currency: "USD",
  value: 30.03,
  items: [
    {
      item_id: "SKU_12345",
      item_name: "Stan and Friends Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 2.22,
      index: 0,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "green",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 10.01,
      quantity: 3
    }
  ]
});

My series data is not rendering the dates correctly in Highcharts

I am trying to do a forecast chart using highcharts but all my dates that say December in my second series are also showing up a November dates. Not sure why.

Highcharts.chart("container", {
  chart: { backgroundColor: "#fbfcf8", type: "line", zoomType: "x" },
  title: { text: "", align: "center" },
  accessibility: { enabled: false },
  credits: { enabled: false },
  legend: { enabled: true, itemStyle: { color: "#000" } },
  rangeSelector: { enabled: false },
  navigator: { enabled: false },
  scrollbar: { enabled: false },
  xAxis: {
    tickInterval: 2,
    categories: [
      "Nov 3, 2024",
      "Nov 4, 2024",
      "Nov 5, 2024",
      "Nov 6, 2024",
      "Nov 7, 2024",
      "Nov 8, 2024",
      "Nov 9, 2024",
      "Nov 10, 2024",
      "Nov 11, 2024",
      "Nov 12, 2024",
      "Nov 13, 2024",
      "Nov 14, 2024",
      "Nov 15, 2024",
      "Nov 16, 2024",
      "Nov 17, 2024",
      "Nov 18, 2024",
      "Nov 19, 2024",
      "Nov 20, 2024",
      "Nov 21, 2024",
      "Nov 22, 2024",
      "Nov 23, 2024",
      "Nov 24, 2024",
      "Nov 25, 2024",
      "Nov 26, 2024",
      "Nov 27, 2024",
      "Nov 28, 2024",
      "Nov 29, 2024",
      "Nov 30, 2024",
      "Dec 1, 2024",
      "Dec 2, 2024",
      "Dec 3, 2024",
      "Dec 4, 2024",
      "Dec 5, 2024",
      "Dec 6, 2024",
      "Dec 7, 2024",
      "Dec 8, 2024",
      "Dec 9, 2024",
      "Dec 10, 2024",
      "Dec 11, 2024",
      "Dec 12, 2024",
      "Dec 13, 2024",
      "Dec 14, 2024",
      "Dec 15, 2024",
      "Dec 16, 2024",
      "Dec 17, 2024",
      "Dec 18, 2024",
    ],
    labels: { style: { color: "#000" } },
    lineColor: "#000",
    lineWidth: 3,
  },
  yAxis: {
    gridLineColor: "#fbfcf8",
    lineColor: "#000",
    lineWidth: 3,
    labels: { style: { color: "#000" } },
    title: { text: "" },
    opposite: false,
  },
  tooltip: {
    backgroundColor: "#fbfcf8",
    style: { color: "#000" },
    shared: true,
    useHTML: true,
  },
  plotOptions: {
    series: {
      stacking: "normal",
      marker: { enabled: false, states: { hover: { enabled: true } } },
    },
  },
  series: [
    {
      name: "Change In Subscribers",
      data: [
        { name: "Nov 4, 2024", y: 20810 },
        { name: "Nov 5, 2024", y: 22300 },
        { name: "Nov 11, 2024", y: 16110 },
        { name: "Nov 20, 2024", y: 3439 },
        { name: "Nov 13, 2024", y: 15320 },
        { name: "Nov 8, 2024", y: 0 },
        { name: "Nov 12, 2024", y: 5300 },
        { name: "Nov 10, 2024", y: 5100 },
        { name: "Nov 15, 2024", y: 1100 },
        { name: "Nov 3, 2024", y: 5110 },
        { name: "Nov 22, 2024", y: 0 },
        { name: "Nov 23, 2024", y: 310 },
        { name: "Nov 26, 2024", y: 45200 },
        { name: "Nov 19, 2024", y: 3260 },
        { name: "Nov 21, 2024", y: 29300 },
        { name: "Nov 28, 2024", y: 9530 },
        { name: "Dec 2, 2024", y: 28410 },
        { name: "Dec 1, 2024", y: 14700 },
        { name: "Nov 18, 2024", y: 7350 },
        { name: "Nov 7, 2024", y: 14410 },
        { name: "Nov 29, 2024", y: 0 },
        { name: "Nov 30, 2024", y: 3301 },
        { name: "Nov 25, 2024", y: 18540 },
        { name: "Nov 9, 2024", y: 11207 },
        { name: "Nov 16, 2024", y: 0 },
        { name: "Nov 6, 2024", y: 16220 },
        { name: "Nov 17, 2024", y: 17710 },
        { name: "Nov 14, 2024", y: 7420 },
        { name: "Nov 27, 2024", y: 16110 },
        { name: "Nov 24, 2024", y: 5510 },
        { name: "Dec 3, 2024", y: 0 },
      ],
      color: "#6B8E23",
      yAxis: 0,
    },
    {
      name: "Forecast",
      data: [
        { name: "Dec 4, 2024", y: 11534.55 },
        { name: "Dec 5, 2024", y: 11562.05 },
        { name: "Dec 6, 2024", y: 11589.55 },
        { name: "Dec 7, 2024", y: 11617.06 },
        { name: "Dec 8, 2024", y: 11644.56 },
        { name: "Dec 9, 2024", y: 11672.06 },
        { name: "Dec 10, 2024", y: 11699.56 },
        { name: "Dec 11, 2024", y: 11727.07 },
        { name: "Dec 12, 2024", y: 11754.57 },
        { name: "Dec 13, 2024", y: 11782.07 },
        { name: "Dec 14, 2024", y: 11809.58 },
        { name: "Dec 15, 2024", y: 11837.08 },
        { name: "Dec 16, 2024", y: 11864.58 },
        { name: "Dec 17, 2024", y: 11892.08 },
        { name: "Dec 18, 2024", y: 11919.59 },
      ],
      color: "red",
      dashStyle: "LongDash",
      lineWidth: 2,
    },
  ],
})
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>

<figure class="highcharts-figure">
    <div id="container"></div>
</figure>

Why are my December dates showing up as November?

Is it possible to log the stack trace where a variable changes?

I want to change a certain variable every second. But the same variable is changing on multiple places of them, and one of them is resulting in NaN. I can’t seem to find out what exactly is causing that. Is there a way to log the stack trace where it changes? Take for example this code:

let foo = 0;

for (foo = 0; foo < 5; foo++) {
  // Do something
}

if (isNaN(foo)) {
  // Console.log the stack trace where the variable changes into NaN
}

Is it possible to do this in one, two or three lines without having to change too much logic or adding too much things in order for it to work? It is node.js-compatible, so it can be a NPM package if that’s easier.

Javascript in inline tags running multiple times in Oqtane – Blazor – 2sxc

I’m using the Oqtane CMS/Framework (with Blazor) with 2sxc apps.

I added this 2sxc app (made just for this test) to a single page with this content:

<div id="something">Something</div>

<script>
    const thisVar = "abc";
    document.querySelector("#something").style.display = "block";
</script>

If I move away from this page I get “Uncaught TypeError: Cannot read properties of null (reading ‘style’)”
So the script is executing again (in pages where the module does not exist), but the html content does not exist.

If I move away from this page and then access it again, I get: “Uncaught SyntaxError: Failed to execute ‘appendChild’ on ‘Node’: Identifier ‘thisVar ‘ has already been declared”.
Does the module retain the script execution after moving away from the page?

I know the optimal way to implement javascript in these apps is with external files, but I need to migrate the current working apps into Oqtane and then refactor them to better standards (there is a lot of dynamic razor code in these scripts).

Any good and simple guides or recommendations available on this subject?

NextUI Select Component not clickable when placed inside a Dialog element

I am trying to create a Form within a Modal in Next.js I have already created the Dialog component, and am working on the specific format of the Modal for this page. I copy and pasted the Select component code directly from NextUi, and when I first added it to my project, the select items showed up, but the format was wonky (unfortunately I am not currently able to recreate this issue). However now, they are just not showing up at all, and the Select component is seemingly not clickable. Can anyone tell if there is something I am missing?

const associates = getCallForwardAssociates();
        
<Dialog ref={dialogRef} title='Reassign Caller' onClose={onClose}>
            <Form action='/dashboard/home'>
                <Select
                    label="Select Caller"
                    placeholder=""
                    className="max-w-xs"
                >
                    {associates.map((associate) => (
                        <SelectItem key={associate.id} textValue={`${associate.firstName} ${associate.lastName}`}>
                            {associate.firstName} {associate.lastName}
                        </SelectItem>
                    ))}
                </Select>
            </Form>
        </Dialog>
  • Note: the Dialog component itself is rendering just fine, and the label/placeholder for the select component is visible. The Associates array is coming from an api that I have tested to ensure the getCallForwardAssociates function accurately produces the desired array of information.

Regex $1, $2 data type conversion issue [duplicate]

I’m trying to add YouTube Video Bookmark somewhere.

If my YouTube Video URL is: ‘https://www.youtube.com/watch?v=xxxxxx&t=12:13’
Then it should be convert as format: ‘https://www.youtube.com/watch?v=xxxxxx&t=25s’

Basically I changes the timer format: 12:13 to 733s (12*60 + 13)

I can do it simple way.
But I want to do it in a single line with regex validation like:

let url = 'https://www.youtube.com/watch?v=xxxxxx&t=12:13';

console.log(url.replace(/(d+):(d+)/g, '$1$2'));

let cUrl = url.replace(/(d+):(d+)/g, `${Number($1)*60 + Number($2)}s`);
console.log(cUrl);

Browser Console Output:

enter image description here
enter image description here

Can some guide me why it’s showing the NaN?
What I’m doing wrong ?

Building text editor from scratch in react

Followind is my TextArea component. I have created two components TextArea and Toolbar. I want to make changes only in a specific part of the text which is selected using toolbar but how can i make this work. I am using useContext hook for props drilling.

import { useContext, useRef, useState } from 'react'
import FormattingContext from './context/context';

function TextArea() {
    const [text, setText] = useState("");
    const [selectedText, setSelectedText] = useState(null)
    const { formatting } = useContext(FormattingContext);

    const textareaRef = useRef(null);

    const handleChange = (e) => {
        setText(e.target.value);
    }

    //capture the selected text
    const handleSelect = () => {
        const textarea = textareaRef.current;
        const { selectionStart, selectionEnd } = textarea;

        if (selectionStart !== selectionEnd) {
            setSelectionRange({ start: selectionStart, end: selectionEnd });
        }

    }

    // Maintain selection when clicking inside the textarea
    const handleFocus = () => {
        if (selectionRange) {
            const textarea = textareaRef.current;
            textarea.setSelectionRange(selectionRange.start, selectionRange.end);
        }
    };


    return (
        <textarea
            className='w-full h-[600px] bg-white p-10 resize-none'
            ref={textareaRef}
            name="text"
            id="text"
            cols={33}
            value={text}
            onChange={handleChange}
            onSelect={handleSelect}
            onFocus={handleFocus}
            autoCapitalize="sentances"
            autoCorrect="on"
            spellcheck="true"
            style={{
                fontFamily: formatting.fontFamily,
                fontSize: formatting.fontSize + "px",
                color: formatting.color,
                textAlign: formatting.alignment
            }}
        />
    )
}

export default TextArea

I guess first keeping the selected text onFocus and making changes in the toolbar will make possible changes but how will it work!

Writing a pure JS function for md4 hashing

I am trying to write a JavaScript script for md4 hashing. I am not sure why the code does not work as I have coded the appropriate endian conversion functions.

The full code is shown as below:

class Md4Context {
    constructor() {
        this.h = new Uint32Array([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476]);
        this.digest = new Uint8Array(16); // uint8_t
        this.x = new Uint32Array(16); // uint32_t
        this.buffer = new Uint8Array(64); // uint8_t
        this.size = 0;
        this.totalSize = BigInt(0); // uint64_t;
    }
}

// Helper functions for JS endian conversion
const LETOH32 = (value) => {
    return (
        ((value & 0x000000FF) << 24) |
        ((value & 0x0000FF00) << 8) |
        ((value & 0x00FF0000) >> 8) |
        ((value & 0xFF000000) >>> 24)
    );
}

const letoh32 = (buffer, offset) => {
    return (
        (buffer[offset] |
            (buffer[offset + 1] << 8) |
            (buffer[offset + 2] << 16) |
            (buffer[offset + 3] << 24)) >>>
        0
    );
};

const HTOLE32 = (value) => {
    return Uint8Array.from([
        value & 0xFF,
        (value >> 8) & 0xFF,
        (value >> 16) & 0xFF,
        (value >> 24) & 0xFF,
    ]);
};

const HTOLE32_BI = (value) => {
    if (typeof value !== 'bigint')
        throw new TypeError('Value must be a BigInt');

    let byteLength = value.toString(2).length;

    if (byteLength <= 0 || !Number.isInteger(byteLength))
        throw new RangeError('byteLength must be a positive integer');

    const byteArray = new Uint8Array(byteLength);
    let tempValue = value;

    for (let i = 0; i < byteLength; i++) {
        byteArray[i] = Number(tempValue & 0xFFn); // Extract the least significant byte
        tempValue >>= 8n; // Shift right by 8 bits to process the next byte
    }

    if (tempValue !== 0n)
        throw new RangeError('Value exceeds the specified byte length');

    return byteArray;
}

/* Start of Essential Process Functinos */
// Rotate 32-bit integer left
function ROL32(inputInt, rotationAmount) {
    return (inputInt << rotationAmount) | (inputInt >>> (32 - rotationAmount));
}

const F = (x, y, z) => ((x & y) | (~x & z)); // Round 1
const G = (x, y, z) => ((x & y) | (x & z) | (y & z)); // Round 2
const H = (x, y, z) => (x ^ y ^ z); // Round 3

// FF fn for round 1
const FF = (a, b, c, d, x, s) => {
    a += F(b, c, d) + x;
    a = ROL32(a, s);
    return a;
}

// GG fn for round 2
const GG = (a, b, c, d, x, s) => {
    a += G(b, c, d) + x + 0x5A827999;
    a = ROL32(a, s);
    return a;
}

// HH fn for round 3
const HH = (a, b, c, d, x, s) => {
    a += H(b, c, d) + x + 0x6ED9EBA1;
    a = ROL32(a, s);
    return a;
}
/* End of Essential Process Functinos */

// Initialize padding
const padding = new Uint8Array(64);
padding[0] = 0x80;

function md4Compute(data, length, digest) {
    // Check parameters
    if (data === null && length !== 0)
        throw new Error('ERROR_INVALID_PARAMETER');

    if (digest === null)
        throw new Error('ERROR_INVALID_PARAMETER');

    try {
        const context = new Md4Context(); // Allocate a memory buffer to hold the MD4 context
        md4Update(context, data, length); // Digest the message

        // Finalize the MD4 message digest
        let output = md4Final(context, digest);
        return output;
    } catch (error) {
        console.error('Error during MD4 computation:', error);
        return 'ERROR'; // Replace with specific error codes as needed
    } finally {
        // Clean up context if necessary (JavaScript handles memory management)
        context = null;
    }
}

function md4Update(context, data) {
    let n;

    while (data.length > 0) {
        // The buffer can hold at most 64 bytes
        n = Math.min(data.length, 64 - context.size);

        // Copy the data to the buffer
        for (let i = 0; i < n; i++) {
            context.buffer[context.size + i] = data[i];
        }

        // Update the MD4 context
        context.size += n;
        context.totalSize += BigInt(n);

        // Advance the data pointer
        data = data.slice(n);

        // Process message in 16-word blocks
        if (context.size === 64) {
            // Transform the 16-word block
            md4ProcessBlock(context);

            // Empty the buffer
            context.size = 0;
        }
    }
}

function md4Final(context, digest) {
    let paddingSize;
    const totalSize = context.totalSize * 8n;

    // Pad the message so that its length is congruent to 56 modulo 64
    if (context.size < 56) {
        paddingSize = 56 - context.size;
    } else {
        paddingSize = 64 + 56 - context.size;
    }

    // Append padding
    md4Update(context, padding, paddingSize);

    // Append the length of the original message in little-endian
    context.x[14] = HTOLE32_BI(totalSize & 0xFFFFFFFFn)[0];
    context.x[15] = HTOLE32_BI(totalSize >> 32n)[0];

    // Process the final block
    md4ProcessBlock(context);

    // Convert hash state to little-endian and store it in the digest
    for (let i = 0; i < 4; i++) {
        context.h[i] = HTOLE32(context.h[i]);
    }

    if (digest !== null && digest !== undefined) {
        digest.set(context.digest.slice(0, 16));
    }

    return context.digest;
}

function md4ProcessBlock(context) {
    let a = context.h[0];
    let b = context.h[1];
    let c = context.h[2];
    let d = context.h[3];

    let x = context.x;

    // Convert from little-endian byte order to host byte order (little-endian)
    for (let i = 0; i < 16; i++) {
        x[i] = letoh32(x[i]);
    }

    // Round 1
    a = FF(a, b, c, d, x[0], 3);
    d = FF(d, a, b, c, x[1], 7);
    c = FF(c, d, a, b, x[2], 11);
    b = FF(b, c, d, a, x[3], 19);
    a = FF(a, b, c, d, x[4], 3);
    d = FF(d, a, b, c, x[5], 7);
    c = FF(c, d, a, b, x[6], 11);
    b = FF(b, c, d, a, x[7], 19);
    a = FF(a, b, c, d, x[8], 3);
    d = FF(d, a, b, c, x[9], 7);
    c = FF(c, d, a, b, x[10], 11);
    b = FF(b, c, d, a, x[11], 19);
    a = FF(a, b, c, d, x[12], 3);
    d = FF(d, a, b, c, x[13], 7);
    c = FF(c, d, a, b, x[14], 11);
    b = FF(b, c, d, a, x[15], 19);

    // Round 2
    a = GG(a, b, c, d, x[0], 3);
    d = GG(d, a, b, c, x[4], 5);
    c = GG(c, d, a, b, x[8], 9);
    b = GG(b, c, d, a, x[12], 13);
    a = GG(a, b, c, d, x[1], 3);
    d = GG(d, a, b, c, x[5], 5);
    c = GG(c, d, a, b, x[9], 9);
    b = GG(b, c, d, a, x[13], 13);
    a = GG(a, b, c, d, x[2], 3);
    d = GG(d, a, b, c, x[6], 5);
    c = GG(c, d, a, b, x[10], 9);
    b = GG(b, c, d, a, x[14], 13);
    a = GG(a, b, c, d, x[3], 3);
    d = GG(d, a, b, c, x[7], 5);
    c = GG(c, d, a, b, x[11], 9);
    b = GG(b, c, d, a, x[15], 13);

    // Round 3
    a = HH(a, b, c, d, x[0], 3);
    d = HH(d, a, b, c, x[8], 9);
    c = HH(c, d, a, b, x[4], 11);
    b = HH(b, c, d, a, x[12], 15);
    a = HH(a, b, c, d, x[2], 3);
    d = HH(d, a, b, c, x[10], 9);
    c = HH(c, d, a, b, x[6], 11);
    b = HH(b, c, d, a, x[14], 15);
    a = HH(a, b, c, d, x[1], 3);
    d = HH(d, a, b, c, x[9], 9);
    c = HH(c, d, a, b, x[5], 11);
    b = HH(b, c, d, a, x[13], 15);
    a = HH(a, b, c, d, x[3], 3);
    d = HH(d, a, b, c, x[11], 9);
    c = HH(c, d, a, b, x[7], 11);
    b = HH(b, c, d, a, x[15], 15);

    // Update the hash value
    context.h[0] = (context.h[0] + a) >>> 0;
    context.h[1] = (context.h[1] + b) >>> 0;
    context.h[2] = (context.h[2] + c) >>> 0;
    context.h[3] = (context.h[3] + d) >>> 0;
}

The function is called as below and should return an Uint8Array which can then be converted to hex:

let main_string = new TextEncoder().encode('hello world');
let digest = new TextEncoder().encode('digest123');

console.log(md4Compute(main_string, main_string.length, digest));

However, it gives an error output of:

RangeError: offset is out of bounds

Any ideas on how this can be fixed?

non-firing onkeyup function

I have some javascript in my ASP.NET HTML who’s purpose is to fire a command whenever the Enter key is pressed in a related TextBox.

<asp:TextBox ID="txtFind" Style="z-index: 103; position: absolute; top: 306px; left: 192px; width: 133px;" TabIndex="1" runat="server" ToolTip="Enter the search criteria for the notes you wish to find" CssClass="aNorm" />
<asp:Button ID="cmdFind" Style="z-index: 105; position: absolute; top: 305px; left: 469px" TabIndex="-1" runat="server" Height="18" Width="45px" Font-Names="Verdana" Font-Size="XX-Small" Text="Find" ToolTip="Find notes that match your criteria (entered to the left of this button)" />
<script type="text/javascript">
<!--
    const txtFindElement = document.getElementById("txtFind");
    if (txtFindElement) {
        txtFindElement.onkeyup = function(e) {
            if (e.key === 'Enter' || e.keyCode === 13) {
                const cmdFindElement = document.getElementById("cmdFind");
                if (cmdFindElement) {
                    cmdFindElement.click();
                }
            }
        };
    }
// --> 
</script>

In the VB.NET code behind,

Private Sub cmdFind_Click(sender As Object, e As EventArgs) Handles cmdFind.Click

    Dim sV As String = txtFind.Text
    Dim sFindWhat$ = Trim(cboFindWhat.SelectedItem.Value)
    Dim attachments As New FTPService

There are no Javascript errors reported by the browser, but the breakpoint in the code-behind is not being caught.

How do I fix this?

I want to make modifications to the PTC page

I own a website, and when adding a link in the PTC section to display the site in an iframe, some sites appear and work, and there are sites that do not work, such as YouTube. When adding a video link, it does not work in the iframe.

I believe the solution to this problem is to create a condition that checks the link to see if it will work or not. If it will work, do nothing. If it will not work, make the link open in a new tab, and the previous page should have a countdown timer that counts the time the user should wait. After the countdown finishes, when the user returns to the previous page, the CAPTCHA will appear.

Can I send the page code and have someone help me write this condition so that everything works fine? The issue is with sites that do not work, showing a white page with a message that the site refused the connection. A timer runs, but the advertiser will not benefit from anything

`

<meta charset="utf-8" />
<title><?= $ads['name'] ?> | <?= $settings['name'] ?></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta content="<?= $settings['description'] ?>" name="description" />
<meta content="Vie Faucet Script" name="author" />
<!-- App favicon -->
<link rel="shortcut icon" href="<?= base_url() ?>assets/images/favicon.ico">

<!-- Bootstrap Css -->
<?php if ($settings['theme'] == 'light') {
    echo '<link href="' . base_url() . 'assets/css/bootstrap.min.css?v=' . VIE_VERSION . '" id="bootstrap-style" rel="stylesheet" type="text/css" />';
    echo '<link href="' . base_url() . 'assets/css/app.min.css?v=' . VIE_VERSION . '" id="bootstrap-style" rel="stylesheet" type="text/css" />';
} else {
    echo '<link href="' . base_url() . 'assets/css/bootstrap-dark.min.css?v=' . VIE_VERSION . '" id="bootstrap-style" rel="stylesheet" type="text/css" />';
    echo '<link href="' . base_url() . 'assets/css/app-dark.min.css?v=' . VIE_VERSION . '" id="bootstrap-style" rel="stylesheet" type="text/css" />';
}
?>
<!-- Icons Css -->
<link href="<?= base_url() ?>assets/css/icons.min.css" rel="stylesheet" type="text/css" />
<link href="<?= base_url() ?>assets/css/styles.css" rel="stylesheet" type="text/css" />

 <style>
    .fixed-banner {
        position: fixed;
        bottom: 10px; /* مسافة الإعلان عن أسفل الشاشة */
        left: 50%;
        transform: translateX(-50%);
        z-index: 9999;
        background-color: #fff; /* خلفية الإعلان */
        border: 1px solid #ccc; /* إطار */
        padding: 10px;
        box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
        text-align: center;
    }
    .fixed-banner img {
        max-width: 100%;
        height: auto;
    }
</style>
<div class="container-fluid ptc-header">
    <div class="row">
        <div class="col-md-6">
            <a class="btn btn-success" href="<?= base_url() ?>">Back to home</a>
        </div>
        <div class="col-md-6">
            <span class="font-size-15 text-truncate text-white" id="ptcCountdown">Please wait...</span>
        </div>
    </div>
</div>
<iframe id="ads" src="<?= $ads['url'] ?>" frameborder="0" style="width: 100%; height: calc(100vh - 75px);" sandbox="allow-same-origin allow-scripts allow-forms"></iframe>


 <!-- إعلان ثابت -->
<div class="fixed-banner">
  <script type="text/javascript">
atOptions = {
    'key' : '178694d86380d0eaf640c52262adfb82',
    'format' : 'iframe',
    'height' : 90,
    'width' : 728,
    'params' : {}
};

Complete the captcha to get reward

×

atOptions = {
‘key’ : ‘9850e3b059dd16c8a1a2a1e45f58eaa6’,
‘format’ : ‘iframe’,
‘height’ : 60,
‘width’ : 468,
‘params’ : {}
};

” method=”POST”>

” value=””>
Verify

<script type="text/javascript">
    var timer = <?= $ads['timer'] ?>;
    var url = '<?= $ads['url'] ?>';
</script>
<script src="<?= base_url() ?>assets/libs/jquery/jquery.min.js"></script>
<script src="<?= base_url() ?>assets/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="<?= base_url() ?>assets/libs/node-waves/waves.min.js"></script>
<!-- App js -->
<script src="<?= base_url() ?>assets/js/app.js"></script>
<script src="<?= base_url() ?>assets/js/vie/captcha.js"></script>
<script src="<?= base_url() ?>assets/js/vie/ptc.js"></script>
<?php if (isset($_COOKIE['captcha'])) { ?>
    <script>
        $('option[value=<?= $_COOKIE['captcha'] ?>]').attr('selected', 'selected');
    </script>
<?php } ?>
<?php
if (isset($_SESSION['sweet_message'])) {
    echo $_SESSION['sweet_message'];
}
?>
<?= $settings['footer_code'] ?>
<?php include 'adblock.php'; ?>

`

I tried more than once with GPT chat and more than one artificial intelligence model, but this problem was not solved. I am not a programmer. I purchased the script and the programmer does not want to respond.
enter image description here

GRIDJS: How to retrieve data from rows I select

I am using grid.js along with its selector plugin to make the user select a specific row or rows in the table.

A working example of the script is shown below.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link href="https://unpkg.com/gridjs/dist/theme/mermaid.min.css" rel="stylesheet" />
</head>

<body>
    <div id="table"></div>
    <button id="btn">Clicca</button>
    <script src="https://unpkg.com/[email protected]/dist/gridjs.production.min.js"></script>
    <script src="https://unpkg.com/[email protected]/plugins/selection/dist/selection.umd.js"></script>
    <script>
        let grid = new gridjs.Grid({
            pagination: true,
            columns: [{
                    id: 'select',
                    name: 'Select',
                    plugin: {
                        component: gridjs.plugins.selection.RowSelection
                    }
                },
                'Name', 'Language', 'Released At', 'Artist'
            ],
            server: {
                url: 'https://api.scryfall.com/cards/search?q=Inspiring',
                then: data => data.data.map(card => [card.name, card.lang, card.released_at, card.artist])
            }
        }).render(document.getElementById("table"));
        

        document.getElementById('btn').addEventListener("click", function() {
            let selectedIds = grid.config.store.state.rowSelection.rowIds;
            let key = Array.from(grid.config.pipeline.cache.keys())[2];
            let tableData = grid.config.pipeline.cache;

            for (let i = 0; i < selectedIds.length; i++) {
                for (let j = 0; j < tableData.length; j++) {
                    if (selectedIds[i] == tableData[j].id) {
                        console.log('Match: ', selectedIds[i], tableData[j].cells[1].data, tableData[j].cells[2]
                            .data)
                    };
                };
            };
        })
    </script>

</body>

</html>

Once I have selected the rows via checkbox and clicked on the button, I want it to print, for example in console, the data of the rows I have selected, (so for example Name, Released At and Artist).

I tried to use the example below, but it is not working for me.

Can someone help me solve this or show me a simpler solution?

Why is ‘npm start’ returning an error after cloning GitHub project?

I’m trying to run a React Vite project I cloned from GitHub but I did not have a Vite project prior to cloning. This is the error:

npm error Missing script: "start"
npm error
npm error Did you mean one of these?
npm error   npm star # Mark your favorite packages
npm error   npm stars # View packages marked as favorites
npm error
npm error To see a list of scripts, run:
npm error   npm run

I expected it to run in my browser.

How to prevent double-fetch while preserving interdependent dropdown and date picker functionality in React?

In my app, users can view data by configuring various filters, such as:
Selected Date (via a date swapper component)
Selected Period (options: Days, Weeks, Months)
Selected Fields
These filters are interdependent to enhance user experience. For example:
Changing the Selected Period automatically updates the Selected Date. For instance, switching to “Days” sets the date to today, and navigation options update accordingly (e.g., flipping through days, weeks, or months).

Also, to let user quickly switch between dates in date swapper we implemented useDebounce hook. This debounces the selectedDate state update by 1500 ms

The issue is:
When configuring only one filter (e.g., debouncedDate or Fields):
Everything works perfectly. The fetch function is called once, and the app behaves as expected.
However, when configuring both filters simultaneously (e.g., debouncedDate and Fields):
The handleDataFetch function is triggered twice:

  1. The first fetch uses outdated configuration values (the old selectedDate ).
  2. The second fetch uses the correct, updated configuration values.
    This double-fetch leads to wrong data being displayed
    Here are some code snippets for better understanding
useEffect(() => {
    handleDataFetch();
  }, [
    reportValues?.statusList,
    reportValues?.selectedFields,
    debouncedData,
    reportValues?.projectId,
    reportValues?.savedFilter,
    reportValues?.jql,
    currentProjectId
  ]);

const debouncedData = useDebounce(selectedDate, 1500, useDebounceForDate, setIsDebouncedDateUpdated);
export const useDebounce = (value, delay = 700, useDebounceForDate) => {
  const [debouncedValue, setDebouncedValue] = useState(value);
  useEffect(() => {
    if (useDebounceForDate) {
      const handler = setTimeout(() => {
        setDebouncedValue(value);
      }, delay);
      return () => {
        clearTimeout(handler);
      };
    } else {
      setDebouncedValue(value);
    }
  }, [value]);
  return debouncedValue;
};

export const useSetStartAndEndDate = ({ selectedPeriod, setSelectedDate, setUseDebounceForDate }) => {
  const globalSettings = useSelector(selectGlobalSettings);
  useEffect(() => {
    let newEndDate, newStartDate, newStartInMs;
    switch (selectedPeriod) {
      case "Days":
        newStartDate = moment().startOf("day").toDate();
        newEndDate = moment(newStartDate).add(1, "day").toDate();
        break;
      case "Weeks":
        newStartInMs = moment()
          .startOf("isoWeek")
          .add((globalSettings.firstDayOfTheWeek - 1) % 7, "days")
          .valueOf();
        newStartDate = moment(newStartInMs).toDate();
        newEndDate = moment(newStartDate).add(1, "week").toDate();
        break;
      case "Months":
        newStartDate = moment().startOf("month").toDate();
        newEndDate = moment(newStartDate).add(1, "month").toDate();
        break;
      case "Years":
        newStartDate = moment().startOf("year").toDate();
        newEndDate = moment(newStartDate).add(1, "year").toDate();
        break;
      default:
        return;
    }
    setSelectedDate([{ startDate: newStartDate, endDate: newEndDate }]);
    setUseDebounceForDate(false);
  }, [selectedPeriod, setSelectedDate]);

How can I prevent double-fetching while ensuring the fetch logic works seamlessly for both single and combined configurations?
Is there a better way to coordinate the debouncedDate and other state dependencies to avoid outdated fetch calls?

I added a condition to fetch data only after the debouncedDate is updated.
While this prevents double-fetching, it breaks functionality when only fields are configured (since no date is selected in this case, the condition fails, and the fetch never happens).

useEffect(() => {
    if (isDebouncedDateUpdated) {
      handleDataFetch();
      setIsDebouncedDateUpdated(false);
    }
  }, [
    reportValues?.statusList,
    reportValues?.selectedFields,
    debouncedData,
    reportValues?.projectId,
    reportValues?.savedFilter,
    reportValues?.jql,
    currentProjectId
  ]);

How to escape properly a text in alpinejs/Laravel?

I am using alpinejs and laravel, I stored in the database this text: F & M, this parte of my blade file:

.....
<input   type="text" name="title"   id="title"  x-model="title" required />
 ....

<script> 
document.addEventListener('alpine:init', () => {
      Alpine.data('MyForm', () => ({ 
              title: '{{ $post->title }}',
      })) 
 }) 
    </script> 

In the input text the title is displayed like this:

F &amp; M

I want it to be displayed like this: F & M . I don’t want to use {!! !!} because it may be unsafe for my website, What can I do?

How to retrieve the name of an Object passed as a Key to a Map?

I’m a newbie to Javascript. I wish to know how to get the key as ‘personObj’, ‘carObj, ‘workDetailsObj’, ‘displayFunction’ and ‘primitiveValue’ and print those values in console? Also, how to print the value of the function displayColors() as ‘Red Color’ in console?. Here is the code I tried.

const personObj = {
  fName: 'John',
  lName: 'Doe',
  age: 30
};
const carObj = {
  type: 'Fiat',
  model: 500,
  color: 'blue'
};
const workDetailsObj = {
  designation: 'Software Engineer',
  salary: 30000,
  company: 'GE'
};

function displayColors() {
  console.log(`Red Color`);
}
let primitiveValue = `Map Object's Contents`;

const mapObj = new Map();

mapObj.set(personObj, 1);
mapObj.set(carObj, 2);
mapObj.set(workDetailsObj, 3);
// mapObj.set(displayFunction, 4);
mapObj.set(primitiveValue, 5);

for (let key of mapObj.keys()) {
  console.log(key);
}

But I want the output to be printed as

personObj details: 

fName : 'John'
 lName : 'Doe' 
age : 30 

carObj details: 
type: 'Fiat' 
model: 500 
color: 'blue' 

workDetailsObj details: 
designation: 'Software Engineer' 
salary: 30000 
company: 'GE' 

displayFunction output: 
Red Color 

primitiveValue value 

: Map Object's Contents.