Make iOS Capacitor CAPPluginCall notifyListener to wait for reactjs async indexdb “put” call

I have a capacitor plugin to bridge Swift and Reactjs, basically to run a PWA on an iOS device, but some part of the code is written in Swift in this app, thus when I switch from Reactjs to Swift, the javascript main thread is blocked by swiftui screens, and all the background async task in javascript comes to a halt. Here in Swift, I have defined some listeners using the capacitor notifyListener function, which sends notifications to Reactjs when some event occurs in Swift, one such listener is responsible for setting some data in the Reactjs indexedDB, but since the main thread is blocked (according to my knowledge), that indexedDB updation async call is thrown into some queue, and I do not get any response back from the DB, but when I close the swiftui screens and come back to the Reactjs code, the updation happens and I get the desired response.

So my question here is, is there some way by which I can wait in Swiftui, till that DB async call finishes and I can get the result at the same time without closing the Swiftui screens and coming back again?

Here is the sample code for your reference. Any help will be appreciated.

Listener in swift –

do {
      try activationScheduler?.startActivationTimer()
      self.notifyListeners(self.onTripStart, data: ["transactionId": options.booking.id])
   } catch {
      debugPrint("Failed to start activation timer: (error)")
   }

Code in Reactjs which runs when notification is raised from swift –

useEffect(() => {
    const activationFlowTripStartListener = ActivationFlowPlugin.addListener('onTripStart', (eventData) => {
      handleSetPassAndTicketWithDB(eventData);
    });

    return () => {
      activationFlowTripStartListener?.remove();
    };
  }, [userId]);

const handleSetPassAndTicketWithDB = useCallback(async (passData) => {
    const decryptkey = getKeyForEncryptAndDecrypt(userId);
    const { get } = IndexDB(objectStoreKeys.myPassHistory);
    let pass = await get(passData?.transactionId, decryptkey);
    const newCachedPassData = {
      ...pass,
      ...pass?.cachedPass,
      isContactLessValidationVisited: true,
      isRidePresent: true,
    };
    await setUserPass(newCachedPassData);
  }, [userId, setUserPass]);

Also one more thing as you can see here, I am “getting” and “setting” data in the IndexedDB. The get function is working correctly, the issue arises only when I use the set function of the IndexedDB object.

The await setUserPass function call above calls this function to update the indexedDB –

const setHistoryData = useCallback(async (newData) => {
    if (newData?.transactionId) {
      const decryptkey = getKeyForEncryptAndDecrypt(phoneNumber);
      const { set } = IndexDB(objectStoreKeys.myPassHistory);
      await set(undefined, { newData }, decryptkey);
    }
    return 0;
  }, [phoneNumber]);

And here is the set async function of the IndexedDB object –

set: async function set(key, val, encryptKey) {
    const encryptData = encryptObject(val, encryptKey);
    return (await dbPromise).put(`${objectStore}`, encryptData, key);
  },
get: async function get(key, decryptKey) {
    const data = await (await dbPromise).get(`${objectStore}`, key);
    return decryptObject(data, decryptKey);
  },

How to implement text-to-speech in React-native for heteronyms?

I have an array of words and want to enable my users to listen to them. However, there’s a chance of encountering a heteronym (a word spelled the same as another but pronounced differently).

My idea is to find a TTS (Text-to-Speech) library that accepts transcriptions (like dʌk) as input. Do you have any ideas about such libraries, or perhaps know of another approach to solve my issue?

Thanks.

Can’t bind to the input of a standalone angular directive in unit test

I’m trying to write a test for a directive that modifies the Angular CDK table. To test this I made a test component decalred in my *.spec.ts file, where I setup a simple table and add my directive.

However when run, on fixture.detectChanges() the component throws two errors. One is that the input property is unknown, the second is from the directive sayingthe required input is not set.

Can't bind to 'sortableColumns' since it isn't a known property of 'table' (used in the 'TestComponent' component template)

ERROR RuntimeError: NG0950: Input is required but no value is available yet.

The test component looks like so (I have removed some logic for brevity):

@Component({
  standalone: true,
  imports: [CdkTableModule, SortableTableDirective],
  template: ` <table cdk-table sortableTable [dataSource]="dataSource" [sortableColumns]="sortableColumns">
    <ng-container cdkColumnDef="columnA">
      <th cdk-header-cell *cdkHeaderCellDef>The First Column</th>
      <td cdk-cell *cdkCellDef="let element">{{ element.columnA }}</td>
    </ng-container>
    <ng-container cdkColumnDef="columnB">
      <th cdk-header-cell *cdkHeaderCellDef>The Second Column</th>
      <td cdk-cell *cdkCellDef="let element">{{ element.columnB }}</td>
    </ng-container>
    <ng-container cdkColumnDef="columnC">
      <th cdk-header-cell *cdkHeaderCellDef>The Third Column</th>
      <td cdk-cell *cdkCellDef="let element">{{ element.columnC }}</td>
    </ng-container>
    <tr cdk-header-row *cdkHeaderRowDef="displayedColumns"></tr>
    <tr cdk-row *cdkRowDef="let row; columns: displayedColumns"></tr>
  </table>`,
})
class TestComponent {
  dataSource = //data-source creation etc removed for brevity
  sortableColumns = ['columnA', 'columnB'];
  displayedColumns = ['columnA', 'columnB', 'columnC'];
}

The test is setup as follows. The table variable gets a value despite an error being thrown on the fixture setup. When I later want to check that the directive has run however, it has not. I have tried with and without the compileComponents function, it does not make a difference.

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [SortableTableDirective, TestComponent, CdkTableModule],
    }).compileComponents();
    fixture = TestBed.createComponent(TestComponent);

    fixture.detectChanges();

    table = fixture.debugElement.query(By.directive(SortableTableDirective));
  });

The directive itself is fairly simple from a dependency standpoint, not depending on anything outside of some core angular things

@Directive({
  selector: 'table[sortableTable]',
  standalone: true,
})
export class SortableTableDirective<T> implements OnDestroy {
  dataSource = input.required<SortableDatasource<T>>();
  sortableColumns = input.required<string[]>();

  public constructor(
    private renderer: Renderer2,
    private elRef: ElementRef,
    private containerRef: ViewContainerRef,
  ) {
    // code removed
  }

The cdk-table directive works and runs as it should, with its created elements all being available in the fixture. The code runs perfectly fine “live”.

React Hooks with React Router – how do I redirect to another route?

I have a simple react hooks application – a list of Todos – with react router v4

On the List of Todos, when a Todo is clicked I need to:

Dispatch the current todo in context
Redirect to another route (from /todos to /todos/:id)
In the previous React Class based implementation I could use this.context.history.push to redirect to another route.

google-site-verification: google97d89d494f462800.html

How would I handle that using React Hooks in combination of React Router v4 (in code below see my comment in function editRow())?

Babel cannot parse coalescing operator in my React JSX

I tried adding babel support for ?? but it still cannot parse this for some reason.

I am using:

"@babel/core": "^7.24.0"
"typescript": "^5.4.2"
"webpack": "^4.44.1"
 "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4",

I also tried installing and using: @babel/plugin-proposal-nullish-coalescing-operator

It cannot parse the following 2 lines when I compile my ReactJS app because it cannot parse ??:

const organization = company ?? university;
<MainLayout title={company.name ?? university.name}>

.bablerc

{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "node": "current"
      }
    }],
    ["@babel/preset-react", { "development": true }]
  ],
  "plugins": [
    ["@babel/plugin-proposal-object-rest-spread"],
    ["@babel/plugin-transform-runtime"],
    ["@babel/plugin-proposal-export-default-from"],
    ["@babel/plugin-transform-optional-chaining"],
    ["@babel/plugin-transform-nullish-coalescing-operator"]
  ]
}

tsconfig.json

"compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */
    "noEmit": true,
    "rootDir": "./",
    /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    "target": "esnext",
    /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "esnext",
    /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    "lib": [
      "es5",
      "es6",
      "dom",
      "ESNext"
    ],
    /* Specify library files to be included in the compilation. */
    "moduleResolution": "node",
    "allowJs": false,
    /* Allow javascript files to be compiled. */
    "jsx": "react",

InterviewContainer.tsx

render() {
        const {company, university} = this.props;
        if(!company || !university) return null

        const organization = company ?? university;

        return (
            <Main>
                <MainLayout title={company.name ?? university.name}>
                    <div>
                        <div id="ft-interview">
                            <div className="panel vertical-space">
                                <CompanyHeader className="ft-companyHeader" company={company}/>
                                <CompanyProfile className="ft-companyProfile" company={company}/>
                                <InterviewContentMain className="ft-interviewContentMain" company={company}/>
                            </div>
                        </div>
                    </div>
                </MainLayout>
            </Main>
        )
    }

Error (I get this when webpack uses tsconfig to transpile my webpack dev build)

ERROR in ./views/Interview/InterviewContainer.tsx 28:38
Module parse failed: Unexpected token (28:38)
File was processed with these loaders:
 * ./node_modules/ts-loader/index.js
You may need an additional loader to handle the result of these loaders.
|         if (!company || !university)
|             return null;
>         const organization = company ?? university;
|         return (React.createElement(Main, null,
|             React.createElement(MainLayout, { title: company.name ?? university.name },
 @ ./views/App.tsx 5:0-64 38:36-54 40:36-54
 @ ./index.tsx

How do i condense this html and javascript code [closed]

Description is at the bottom 🙂

<body>
    <h3>Timetable</h3>
    <form id="dataForm">
      <table id="table1">
        <tr>
          <td>Week A</td>
          <td>Monday</td>
          <td>Tuesday</td>
          <td>Wednesday</td>
          <td>Thursday</td>
          <td>Friday</td>
        </tr>
        <tr>
          <td>Period 1</td>
          <td>
            <input type="text" placeholder="Enter Class Info" id="d1p1w1" name="d1p1w1">
            <select id="colors0" name="colors">
            <option value="color0" selected output>Colour:</option>
            <option value="color1">Red</option>
            <option value="color2">Yellow</option>
            <option value="color3">Green</option>
            <option value="color4">Purple</option>
            <option value="color5">Grey</option>
            <option value="color6">Blue</option>
          </select>
            &#8203 &#8203
          </td>
          <td>
            <input type="text" placeholder="Enter Class Info" id="d2p1w1" name="d2p1w1">
            <select id="colors1" name="colors2">
              <option value="color0" selected output>Colour:</option>
              <option value="color1">Red</option>
              <option value="color2">Yellow</option>
              <option value="color3">Green</option>
              <option value="color4">Purple</option>
              <option value="color5">Grey</option>
              <option value="color6">Blue</option>
            </select>
              &#8203 &#8203
          </td>
          <td>
            <input type="text" placeholder="Enter Class Info" id="d3p1w1" name="d3p1w1">
            <select id="colors2" name="colors3">
              <option value="color0" selected output>Colour:</option>
              <option value="color1">Red</option>
              <option value="color2">Yellow</option>
              <option value="color3">Green</option>
              <option value="color4">Purple</option>
              <option value="color5">Grey</option>
              <option value="color6">Blue</option>
            </select>
              &#8203 &#8203
<table id="dataTable">
      <thead>
        <tr>
          <td>Week A</td>
          <td>Monday</td>
          <td></td>
          <td>Tuesday</td>
          <td>Wednesday</td>
          <td>Thursday</td>
          <td>Friday</td>
        </tr>
        <tr>
          <td>9:23</td>
          <th id="d0">
            <span id="day1p1w1"></span>
            <script>
              document.getElementById('colors0').onchange=changeEventHandler;

              var indicator = document.getElementById("d0");
              
              function changeEventHandler() {
                indicator.classList = this.value;
              }
            </script>
          </th>
          <td>8:53</td>
          <th id="d1">
            <span id="day2p1w1"></span>
            <script>
              document.getElementById('colors1').onchange=changeEventHandler;

              var indicator1 = document.getElementById("d1");
              
              function changeEventHandler() {
                  indicator1.classList = this.value;
              }
            </script>
          </th>
        select option[value="color0"] {
          background-color: #ffffff;
        }
        select option[value="color1"] {
          background-color: #ffdfde;
        }
        select option[value="color2"] {
          background-color: #ffffdf;
        }
        select option[value="color3"] {
          background-color: #dfffde;
        }
        select option[value="color4"] {
          background-color: #efdeff;
        }
        select option[value="color5"] {
          background-color: #e6efef;
        }
        select option[value="color6"] {
          background-color: #dffffe;
        }


        .color0 {background-color: #ffffff;}
        .color1 {background-color: #ffdfde;}
        .color2 {background-color: #ffffdf;}
        .color3 {background-color: #dfffde;}
        .color4 {background-color: #efdeff;}
        .color5 {background-color: #e6efef;}
        .color6 {background-color: #dffffe;}
<script>
function displayData() {
const d1p1w1 = document.getElementById("d1p1w1").value;
const d2p1w1 = document.getElementById("d2p1w1").value;
const d3p1w1 = document.getElementById("d3p1w1").value;
const d4p1w1 = document.getElementById("d4p1w1").value;
const d5p1w1 = document.getElementById("d5p1w1").value;
const d1p2w1 = document.getElementById("d1p2w1").value;
const d2p2w1 = document.getElementById("d2p2w1").value;
const d3p2w1 = document.getElementById("d3p2w1").value;
const d4p2w1 = document.getElementById("d4p2w1").value;
const d5p2w1 = document.getElementById("d5p2w1").value;
const d1p3w1 = document.getElementById("d1p3w1").value;
const d2p3w1 = document.getElementById("d2p3w1").value;
const d3p3w1 = document.getElementById("d3p3w1").value;
const d4p3w1 = document.getElementById("d4p3w1").value;
const d5p3w1 = document.getElementById("d5p3w1").value;
const d1p4w1 = document.getElementById("d1p4w1").value;
const d2p4w1 = document.getElementById("d2p4w1").value;
const d3p4w1 = document.getElementById("d3p4w1").value;
const d4p4w1 = document.getElementById("d4p4w1").value;
const d5p4w1 = document.getElementById("d5p4w1").value;
const d1p5w1 = document.getElementById("d1p5w1").value;
const d2p5w1 = document.getElementById("d2p5w1").value;
const d3p5w1 = document.getElementById("d3p5w1").value;
const d4p5w1 = document.getElementById("d4p5w1").value;
const d5p5w1 = document.getElementById("d5p5w1").value;
const d1p6w1 = document.getElementById("d1p6w1").value;
const d2p6w1 = document.getElementById("d2p6w1").value;
const d3p6w1 = document.getElementById("d3p6w1").value;
const d4p6w1 = document.getElementById("d4p6w1").value;
const d5p6w1 = document.getElementById("d5p6w1").value;

const d1p1w2 = document.getElementById("d1p1w2").value;
const d2p1w2 = document.getElementById("d2p1w2").value;
const d3p1w2 = document.getElementById("d3p1w2").value;
const d4p1w2 = document.getElementById("d4p1w2").value;
const d5p1w2 = document.getElementById("d5p1w2").value;
const d1p2w2 = document.getElementById("d1p2w2").value;
const d2p2w2 = document.getElementById("d2p2w2").value;
const d3p2w2 = document.getElementById("d3p2w2").value;
const d4p2w2 = document.getElementById("d4p2w2").value;
const d5p2w2 = document.getElementById("d5p2w2").value;
const d1p3w2 = document.getElementById("d1p3w2").value;
const d2p3w2 = document.getElementById("d2p3w2").value;
const d3p3w2 = document.getElementById("d3p3w2").value;
const d4p3w2 = document.getElementById("d4p3w2").value;
const d5p3w2 = document.getElementById("d5p3w2").value;
const d1p4w2 = document.getElementById("d1p4w2").value;
const d2p4w2 = document.getElementById("d2p4w2").value;
const d3p4w2 = document.getElementById("d3p4w2").value;
const d4p4w2 = document.getElementById("d4p4w2").value;
const d5p4w2 = document.getElementById("d5p4w2").value;
const d1p5w2 = document.getElementById("d1p5w2").value;
const d2p5w2 = document.getElementById("d2p5w2").value;
const d3p5w2 = document.getElementById("d3p5w2").value;
const d4p5w2 = document.getElementById("d4p5w2").value;
const d5p5w2 = document.getElementById("d5p5w2").value;
const d1p6w2 = document.getElementById("d1p6w2").value;
const d2p6w2 = document.getElementById("d2p6w2").value;
const d3p6w2 = document.getElementById("d3p6w2").value;
const d4p6w2 = document.getElementById("d4p6w2").value;
const d5p6w2 = document.getElementById("d5p6w2").value;

const data = {
    d1p1w1: d1p1w1,
    d2p1w1: d2p1w1,
    d3p1w1: d3p1w1,
    d4p1w1: d4p1w1,
    d5p1w1: d5p1w1,
    d1p2w1: d1p2w1,
    d2p2w1: d2p2w1,
    d3p2w1: d3p2w1,
    d4p2w1: d4p2w1,
    d5p2w1: d5p2w1,
    d1p3w1: d1p3w1,
    d2p3w1: d2p3w1,
    d3p3w1: d3p3w1,
    d4p3w1: d4p3w1,
    d5p3w1: d5p3w1,
    d1p4w1: d1p4w1,
    d2p4w1: d2p4w1,
    d3p4w1: d3p4w1,
    d4p4w1: d4p4w1,
    d5p4w1: d5p4w1,
    d1p5w1: d1p5w1,
    d2p5w1: d2p5w1,
    d3p5w1: d3p5w1,
    d4p5w1: d4p5w1,
    d5p5w1: d5p5w1,
    d1p6w1: d1p6w1,
    d2p6w1: d2p6w1,
    d3p6w1: d3p6w1,
    d4p6w1: d4p6w1,
    d5p6w1: d5p6w1,

    d1p1w2: d1p1w2,
    d2p1w2: d2p1w2,
    d3p1w2: d3p1w2,
    d4p1w2: d4p1w2,
    d5p1w2: d5p1w2,
    d1p2w2: d1p2w2,
    d2p2w2: d2p2w2,
    d3p2w2: d3p2w2,
    d4p2w2: d4p2w2,
    d5p2w2: d5p2w2,
    d1p3w2: d1p3w2,
    d2p3w2: d2p3w2,
    d3p3w2: d3p3w2,
    d4p3w2: d4p3w2,
    d5p3w2: d5p3w2,
    d1p4w2: d1p4w2,
    d2p4w2: d2p4w2,
    d3p4w2: d3p4w2,
    d4p4w2: d4p4w2,
    d5p4w2: d5p4w2,
    d1p5w2: d1p5w2,
    d2p5w2: d2p5w2,
    d3p5w2: d3p5w2,
    d4p5w2: d4p5w2,
    d5p5w2: d5p5w2,
    d1p6w2: d1p6w2,
    d2p6w2: d2p6w2,
    d3p6w2: d3p6w2,
    d4p6w2: d4p6w2,
    d5p6w2: d5p6w2,
};


document.getElementById('day1p1w1').innerHTML = d1p1w1;
document.getElementById('day2p1w1').innerHTML = d2p1w1;
document.getElementById('day3p1w1').innerHTML = d3p1w1;
document.getElementById('day4p1w1').innerHTML = d4p1w1;
document.getElementById('day5p1w1').innerHTML = d5p1w1;
document.getElementById('day1p2w1').innerHTML = d1p2w1;
document.getElementById('day2p2w1').innerHTML = d2p2w1;
document.getElementById('day3p2w1').innerHTML = d3p2w1;
document.getElementById('day4p2w1').innerHTML = d4p2w1;
document.getElementById('day5p2w1').innerHTML = d5p2w1;
document.getElementById('day1p3w1').innerHTML = d1p3w1;
document.getElementById('day2p3w1').innerHTML = d2p3w1;
document.getElementById('day3p3w1').innerHTML = d3p3w1;
document.getElementById('day4p3w1').innerHTML = d4p3w1;
document.getElementById('day5p3w1').innerHTML = d5p3w1;
document.getElementById('day1p4w1').innerHTML = d1p4w1;
document.getElementById('day2p4w1').innerHTML = d2p4w1;
document.getElementById('day3p4w1').innerHTML = d3p4w1;
document.getElementById('day4p4w1').innerHTML = d4p4w1;
document.getElementById('day5p4w1').innerHTML = d5p4w1;
document.getElementById('day1p5w1').innerHTML = d1p5w1;
document.getElementById('day2p5w1').innerHTML = d2p5w1;
document.getElementById('day3p5w1').innerHTML = d3p5w1;
document.getElementById('day4p5w1').innerHTML = d4p5w1;
document.getElementById('day5p5w1').innerHTML = d5p5w1;
document.getElementById('day1p6w1').innerHTML = d1p6w1;
document.getElementById('day2p6w1').innerHTML = d2p6w1;
document.getElementById('day3p6w1').innerHTML = d3p6w1;
document.getElementById('day4p6w1').innerHTML = d4p6w1;
document.getElementById('day5p6w1').innerHTML = d5p6w1;

document.getElementById('day1p1w2').innerHTML = d1p1w2;
document.getElementById('day2p1w2').innerHTML = d2p1w2;
document.getElementById('day3p1w2').innerHTML = d3p1w2;
document.getElementById('day4p1w2').innerHTML = d4p1w2;
document.getElementById('day5p1w2').innerHTML = d5p1w2;
document.getElementById('day1p2w2').innerHTML = d1p2w2;
document.getElementById('day2p2w2').innerHTML = d2p2w2;
document.getElementById('day3p2w2').innerHTML = d3p2w2;
document.getElementById('day4p2w2').innerHTML = d4p2w2;
document.getElementById('day5p2w2').innerHTML = d5p2w2;
document.getElementById('day1p3w2').innerHTML = d1p3w2;
document.getElementById('day2p3w2').innerHTML = d2p3w2;
document.getElementById('day3p3w2').innerHTML = d3p3w2;
document.getElementById('day4p3w2').innerHTML = d4p3w2;
document.getElementById('day5p3w2').innerHTML = d5p3w2;
document.getElementById('day1p4w2').innerHTML = d1p4w2;
document.getElementById('day2p4w2').innerHTML = d2p4w2;
document.getElementById('day3p4w2').innerHTML = d3p4w2;
document.getElementById('day4p4w2').innerHTML = d4p4w2;
document.getElementById('day5p4w2').innerHTML = d5p4w2;
document.getElementById('day1p5w2').innerHTML = d1p5w2;
document.getElementById('day2p5w2').innerHTML = d2p5w2;
document.getElementById('day3p5w2').innerHTML = d3p5w2;
document.getElementById('day4p5w2').innerHTML = d4p5w2;
document.getElementById('day5p5w2').innerHTML = d5p5w2;
document.getElementById('day1p6w2').innerHTML = d1p6w2;
document.getElementById('day2p6w2').innerHTML = d2p6w2;
document.getElementById('day3p6w2').innerHTML = d3p6w2;
document.getElementById('day4p6w2').innerHTML = d4p6w2;
document.getElementById('day5p6w2').innerHTML = d5p6w2;

document.getElementById("d1p1w1").value = "";
document.getElementById("d2p1w1").value = "";
document.getElementById("d3p1w1").value = "";
document.getElementById("d4p1w1").value = "";
document.getElementById("d5p1w1").value = "";
document.getElementById("d1p2w1").value = "";
document.getElementById("d2p2w1").value = "";
document.getElementById("d3p2w1").value = "";
document.getElementById("d4p2w1").value = "";
document.getElementById("d5p2w1").value = "";
document.getElementById("d1p3w1").value = "";
document.getElementById("d2p3w1").value = "";
document.getElementById("d3p3w1").value = "";
document.getElementById("d4p3w1").value = "";
document.getElementById("d5p3w1").value = "";
document.getElementById("d1p4w1").value = "";
document.getElementById("d2p4w1").value = "";
document.getElementById("d3p4w1").value = "";
document.getElementById("d4p4w1").value = "";
document.getElementById("d5p4w1").value = "";
document.getElementById("d1p5w1").value = "";
document.getElementById("d2p5w1").value = "";
document.getElementById("d3p5w1").value = "";
document.getElementById("d4p5w1").value = "";
document.getElementById("d5p5w1").value = "";
document.getElementById("d1p6w1").value = "";
document.getElementById("d2p6w1").value = "";
document.getElementById("d3p6w1").value = "";
document.getElementById("d4p6w1").value = "";
document.getElementById("d5p6w1").value = "";

document.getElementById("d1p1w2").value = "";
document.getElementById("d2p1w2").value = "";
document.getElementById("d3p1w2").value = "";
document.getElementById("d4p1w2").value = "";
document.getElementById("d5p1w2").value = "";
document.getElementById("d1p2w2").value = "";
document.getElementById("d2p2w2").value = "";
document.getElementById("d3p2w2").value = "";
document.getElementById("d4p2w2").value = "";
document.getElementById("d5p2w2").value = "";
document.getElementById("d1p3w2").value = "";
document.getElementById("d2p3w2").value = "";
document.getElementById("d3p3w2").value = "";
document.getElementById("d4p3w2").value = "";
document.getElementById("d5p3w2").value = "";
document.getElementById("d1p4w2").value = "";
document.getElementById("d2p4w2").value = "";
document.getElementById("d3p4w2").value = "";
document.getElementById("d4p4w2").value = "";
document.getElementById("d5p4w2").value = "";
document.getElementById("d1p5w2").value = "";
document.getElementById("d2p5w2").value = "";
document.getElementById("d3p5w2").value = "";
document.getElementById("d4p5w2").value = "";
document.getElementById("d5p5w2").value = "";
document.getElementById("d1p6w2").value = "";
document.getElementById("d2p6w2").value = "";
document.getElementById("d3p6w2").value = "";
document.getElementById("d4p6w2").value = "";
document.getElementById("d5p6w2").value = "";

document.getElementById("dataForm").style.display = "none";
document.getElementById("dataTable").style.display = "inline";
}
</script>

The first block of code is the input table, it continues repeating for many more lines of code (you can see this in the java code), it looks like this in the final website enter image description here

The second block of code is the output table, it also continues repeating for many more lines of code, it looks like this in the final website enter image description here

The third block of code is just the CSS for the colour picker

The fourth block of code is the JavaScript that takes the value from the first table and puts in the second table

The whole website is front end (i think thats the term) and i would like to keep it front end if possible

Is there a way to condense this code?

The code is the most condensed version i could come up with.

In my webpage add to cart button (from homepage) is not working

I created a add-to-cart button for my website
so, In Index.html:

                    <button class="btn-action add-to-cart-btn" data-index="{{p.id}}" id="add-to-cart-btn">
                      <input type="hidden" value="1" id="product-quantity" class="product-quantity-{{p.id}}">
                      <input type="hidden" class="product-pid-{{p.pid}}" value="{{p.pid}}" name="">
                      <input type="hidden" class="product-image-{{p.id}}" value="{{p.image}}" name="">
                      <input type="hidden" class="product-id-{{p.id}}" value="{{p.id}}" name="">
                      <input type="hidden" class="product-title-{{p.id}}" value="{{p.title}}" name="">
                      <ion-icon name="bag-add-outline"></ion-icon>
                    </button>

This is the add-to-cart button
and in function.js:

$(".add-to-cart-btn").on("click",function(){
    let this_val=$(this)
    let index= this_val.attr("data-index")

    let quantity=$("#product-quantity-" + index).val()
    let product_title=$(".product-title-" + index).val()

    let product_id=$(".product-id-" + index).val()
    let product_price = $("#current-product-price-" + index).text()

    let product_pid = $(".product-pid-" + index).text()
    let product_image=$(".product-image-" + index)
    


    console.log("Quantity:", quantity);
    console.log("Id:", product_id);
    console.log("Pid:", product_pid);
    console.log("Image:", product_image);
    console.log("Index:", index);
    console.log("Title:", product_title);
    console.log("Price:", product_price);
    console.log("Current Element:", this_val);

The problem is that:
When I am clicking on the add-to-cart button, in the console no values are displaying

Note:
The javascript is taking value from home page(index) and from an another page………..
and if you need my views.py:

def add_to_cart(request):
    cart_product={}
    cart_product[str(request.GET['id'])]={
        'title': request.GET['title'],
        'qty': request.GET['qty'],
        'price': request.GET['price'],
    }

    if 'cart_data_obj' in request.session:
        if str(request.GET['id']) in request.session['cart_data_obj']:
            cart_data= request.session['cart_data_obj']
            cart_data[str(request.GET['id'])]['qty']=int(cart_product[str(request.GET['id'])]['qty'])
            cart_data.update(cart_data)
            request.session['cart_data_obj']=cart_data
        else:
            cart_data=request.session['cart_data_obj']
            cart_data.update(cart_product)
            request.session['cart_data_obj']=cart_data
            request.session['total_cart_items'] = len(cart_data)
    else:
        request.session['cart_data_obj']=cart_product
        request.session['total_cart_items'] = len(cart_product)
    return JsonResponse({"data":request.session['cart_data_obj'],'totalcartitems': request.session['total_cart_items']})

But views.py is working perfectly well

Form entries are not storing in the DB table after clicking on Submit button so I have mentioned both PHP file codes?

I have mentioned these two PHP files here – rprocessnew.php that is executed when clicking on the Submit button of the form in the website link – https://space-learning.com/#toregister for storing the entries in the DB table ‘user1′ from ‘Name of Student Field to Mobile Number’ as in the image here that I shared –

After that, an email will be shared to the user’s mail ID that contains an activation link for verifying procedures

When clicking on that activation link the verifynew.php file starts executing and displays these errors as in the images shared again here –

————————————————-

So help me resolve this error that I’m facing right now as all the project codes are working fine except this last thing And Thanks in Advance!! 🙂

rprocessnew.php



<?php


include 'library/function.php';'config.php';
error_reporting(E_ALL);
ini_set('display_errors',1);


if($_POST) {
    $email   = $_POST['email'];
    $pass  = $_POST['pass'];
    $cnfpass = $_POST['cnfpass'];

    if($_POST['email']) {
        if ( $pass == $cnfpass ) {

            $db_name     = '**********';
            $db_user     = '**********';
            $db_password = '**********';
            $host        = 'localhost';

            $mysqli = new mysqli('localhost', $db_user, $db_password, $db_name);

            /* check connection */
            
            if (mysqli_connect_errno()) {
                
                error_log("Connect failed: " . mysqli_connect_error());
                echo '{"success":0,"error_message":"' . mysqli_connect_error() . '"}';
            }
            else 
            {
            
            $stmt = $mysqli->prepare("INSERT IGNORE INTO user1 (userid, schoolcode, school_location, schoolname, name, class, section, email, pass, mobile, hash, uniqueid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

                $stmt->bind_param("ssssssssssss", $userid, $schoolcode, $school_location, $schoolname, $name, $class, $section, $email, $pass, $mobile, $hash, $uniqueid);

                /* execute prepared statement */
                $stmt->execute();

                if ($stmt->error) {

                error_log("Error: " . $stmt->error); 
                }

                $success = $stmt->affected_rows;

                /* close statement and connection */
                $stmt->close();

                /* close connection */
                $mysqli->close();
                error_log("Success: $success");

                if ($success > 0) {
                    
$to      = $email; 
$subject = 'Signup | Verification'; 
$message = '

Hi,
 
Welcome to the World of ASTRONOMY!

You have successfully registered for the SPACE Astronomy Club. Now, you are just one click away to activate your account.<br>For activation, you need to click the given link and enter the Username as well as Password provided below.
 
------------------------
Username: '.$email.'
Password: '.$pass.'
-------------------------

Please click this link to activate your account:  https://www.space-learning.com/verifynew.php?email='.$email.'&hash='.$hash.'

SPACE Astronomy Club page has all the required data that you may need through the various club sessions, such as: 

  - Reading Material

  - Further Reading

  - Challenge Yourself and Many More

We are also providing you with a Unique Id that you can use for being a lifetime beneficiary of SPACE products.

Your Unique ID: '.$uniqueid.'

You may get the following benefits using the Unique Id:

Whenever there will be a new release of any new product then you will get the privilege to use it.

You will get the life time membership for same even if you have completed the module1 and module 2.

Moreover, you will be getting discounts on a number of space products like, Astroport Visits, Astronomers Tool, etc.
Any offer can be taken only once per Unique id.

';
// Our message above including the link
                     
$headers = 'From:Space Technology and Education Pvt. Ltd.<[email protected]>' . "rn"; // Set from headers
mail($to, $subject, $message, $headers); // Send our email

                error_log("Signed Up Successfully! '$name' created.");
                echo '{"success":1}';
                    
                } //if ($success > 0)
                
                else {
                    echo '"Username/Email Already Exists."';
                }
                
            } //else

} //cnfpass

else {
            echo '"Passwords Does Not Match."';
        }
        
    } //if($_POST['name'])
    
}

else {
    
    echo '"Invalid Data Entered."';
}


?> <!-- End of the codes -->

library/function.php


<?php 

function spl__autoload($class)
{
    include "class/$class.php";
}
spl_autoload_register("spl__autoload");


function getMsg(){
    echo msg_decode(@$_GET['msg']);
}

function Logout(){
    session_unset();
    session_destroy();
    redirectUrl('index',msg_encode("Logged Out"));
}

function msg_encode($msg){
    return base64_encode($msg);
}

function msg_decode($deCodeMsg){
    return base64_decode($deCodeMsg);
}

function genrate_password(){
     return rand(1111,9999);
}

 ?>

config.php


<?php
$servername = "localhost";
$database = "**********";
$username = "**********";
$password = "**********";
 
// Create connection
 
$con = mysqli_connect($servername, $username, $password, $database);
 
// Check connection
 
if (!$con) {
 
    die("Connection failed: " . mysqli_connect_error());
 
}

mysqli_close($con);



?>

verifynew.php


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Sign up</title>
    <link href="css/style.css" type="text/css" rel="stylesheet" />
</head>
<body>
    
    <!-- start header div --> 
    <?php
    include 'config.php';
    header("Refresh:10; url=index.php");
    error_reporting(E_ALL);
    ini_set('display_errors',1);
    
?>
    <div id="header">
     
    </div>
    <!-- end header div -->   
     
    <!-- start wrap div -->   
    <div id="wrap">
        <!-- start PHP code -->
        
         <!-- Database Connection -->
        <?php
    
if(isset($_GET['email']) && !empty($_GET['email']) AND isset($_GET['hash']) && !empty($_GET['hash'])){
    
    // Verify data
    $email  = mysqli_real_escape_string($con, $_GET['email']); // Set email variable
    $hash   = mysqli_real_escape_string($con, $_GET['hash']); // Set hash variable
    
    $stmt = $mysqli->query("SELECT email, hash, active FROM user1 WHERE email='".$email."' AND hash='".$hash."' AND active='0'"); 
    $match  = mysqli_num_rows($stmt);

    if($match > 0){
        // We have a match, activate the account
        $mysqli->query("UPDATE user1 SET active='1' WHERE email='".$email."' AND hash='".$hash."' AND active='0'");
        echo "Your account has been activated, you can now log in.";
        echo '<script type="application/javascript">alert("Your Account Has Been Activated, You Can Now Login"); window.location.href = "index.php";</script>';

    }
    else
    {
        // No match -> invalid url or account has already been activated.
        echo '<div class="statusmsg">The URL Is Either Invalid or You Already Have Activated Your Account.</div>';
    }
}

else
{
    // Invalid approach
   echo '<script>alert("Invalid Approach! Please Use The Activation Link That Has Been Send To Your Email.")</script>';
}
             
        ?>
        <!-- stop PHP Code -->
        
    </div>
    <!-- end wrap div --> 

</body>

</html>

I have tried testing the form many times by enabling error displaying classes in the header section for this error but can’t find any solution regarding the same.
So anyone you can help me out regarding pointing the main cause for the DB storing error for executing the project all fine also I don’t have much knowledge about technical php and mysql codes procedures.

My website appears for few mili seconds then preloader then website

My website preloader is not showing properly first the website appears for a few mili seconds then preloader then the website.

I am using Elementor WordPress, I have added the preloader code in my theme file editor here is the code snippet

“add_action(‘wp_footer’, ‘Allprocoding_Preloader’);

function Allprocoding_Preloader() {
if (!is_admin() && $GLOBALS[“pagenow”] !== “wp-login.php”) {

    $delay = 1; // seconds
    $desktop_loader = 'https://spoky.co/wp-content/uploads/2024/02/Group-1171275193-1.gif';
    $mobile_loader = 'https://spoky.co/wp-content/uploads/2024/02/mobile-.gif';
    $overlayColor = '#ffffff';
    ?>
    <script>
        document.addEventListener("DOMContentLoaded", function () {
            var preloader = document.createElement('div');
            preloader.style.position = 'fixed';
            preloader.style.top = '0';
            preloader.style.bottom = '0';
            preloader.style.left = '0';
            preloader.style.right = '0';
            preloader.style.backgroundColor = '<?php echo esc_js($overlayColor); ?>';
            preloader.style.zIndex = '100000';
            preloader.style.display = 'flex';
            preloader.style.alignItems = 'center';
            preloader.style.justifyContent = 'space-around';

            var loaderImg = document.createElement('img');
            loaderImg.src = '<?php echo esc_url($desktop_loader); ?>';
            loaderImg.alt = '';
            loaderImg.style.height = '30vw';

            preloader.appendChild(loaderImg);
            document.body.appendChild(preloader);

            document.body.style.overflow = "hidden";
            var mediaQuery = window.matchMedia("only screen and (max-width: 760px)");

            function handleMediaChange(event) {
                if (event.matches) {
                    loaderImg.src = '<?php echo esc_url($mobile_loader); ?>';
                    loaderImg.style.height = '20vw';
                } else {
                    loaderImg.src = '<?php echo esc_url($desktop_loader); ?>';
                    loaderImg.style.height = '15vw';
                }
            }

            mediaQuery.addListener(handleMediaChange);
            handleMediaChange(mediaQuery);

            window.addEventListener("load", function () {
                // Remove the preloader after the delay
                setTimeout(function () {
                    preloader.remove();
                    document.body.style.overflow = "visible";
                }, <?php echo esc_js($delay * 1000); ?>);
            });
        });
    </script>
    <?php
}

}

what to do to make the prelaoder appears perfectly fine

I have tried adding code to inline css and and preload css and JavaScript files but there is no change in the scenario. What are other possible ways to figure out this issue?

When loggin in with Cypress, I get a 403 error related to a CSRF token

I get a 403 while using Cypress custom commands to login into a webpage I’m testing.

If I log in manually, it doesn’t returns any kind of error, but with Cypress I always get the same state:

“403 Forbiden

Login Failed: Unable to find a valid CSRF token. Please try again.

Request ID: f88dd507-22e4-4776-9113-d2e5fbc3f8ec”

Gladly, there’s a “Login” button at the page that allows me to continue:

403 error

So, I think I must create a test with any cookies used at the moment of the login to bypass this issue?

Here’s the test I’m doing:

Cypress.Commands.add('login', (email, password) => {
    cy.session([email, password], () => {
       cy.visit('baseURL')
       cy.get('[data-test="email"]').type(email);
       cy.get('.has-right-element').type(password)
       cy.get('button[type="submit"]').click()
       cy.get(':nth-child(2) > form > .button').click() // The "Login" button at the 403 error
     })
 })

Nothing out of the ordinary.

I’ve also used another one to capture the cookies that are being used at the moment of the login:

Cypress.Commands.add('loginAndSaveCookies', (email, password) => {
   cy.visit('baseURL')
   cy.get('[data-test="email"]').type(email)
   cy.get('.has-right-element').type(password)
   cy.get('button[type="submit"]').click()
   cy.get(':nth-child(2) > form > .button').click()

   cy.getCookies().then((cookies) => {
       cy.writeFile('cypress/fixtures/cookies.json', cookies)
   })
})

Here are the cookies that are being sent:

[
  {
    "name": "_oauth2_proxy_csrf",
    "value": "sxvnE7akcD26gzrK2N8w3q0EENUsPIxBTPNbbI6QxvLBSSJ6ufkmSeOwST3vEkBqOt9R_O1-XGcSX7w0GynDLLoW6x4e5JEo6noGBBUEiUPNotwrRb5b9PE=|1710311225|AjqwRehQxbfOul4wQTmj2_F9C2NSdtgJZ3K5prAxEso=",
    "path": "/",
    "secure": true,
    "hostOnly": true,
    "httpOnly": true,
    "expiry": 1710312125,
    "domain": "webpage being tested",
    "sameSite": "lax"
  },
  {
    "name": "_oauth2_proxy",
    "value": "8uThtxIW4Mkrw2KtjHvPXAMUKtqUeYeK4SHWm8CBuvFSg50UDx84-Iec26tJhlO0W40hbGV-nCLLL2ZyZb14YTce8XvV7-9CrzLriMeGFCcFve3ytzhYS5CpmjsSKcrMqq_35YvL8iHkU5YrhCj132e2EGt-X_HQY4y0Z46f9ch1Y1U6DZ7q_lefEhBoGCBqQiwGM0-EWJ0oVaCMpTVxObSZhAlegZWfYpWzrNJqgm0zlChADbobsnyLBn72Gi4_kO0gUa5eEdhCyhFysxC9yDH8XS3bUtmch7bRJ9vVU8ZjbshwWdISfyf1hyf02M2Sir53a0GJmFua_N9r9m6tzBJvSCza7YddBeBZ9sckd0iL9Ij51E_QIRl8MeFDUTWkw_uH2yrBWeWpa-OK54jlpkrTOAA0Apt1FZD_PljVAOc2ikzyXhaxD35VvRI6pORkhvErJ3pGqS25ufbWFrHG5TaQPnNmY9IyQZRR658mD4sLJ4OqQVWbAUX8tFhf-Td73RMFi5aMm8thjMj1bz8QAKcao2HbAvwV_KMNacVn487joQ6Q9ZnT-tQkqVOn95ED5nx08497qPtJ8Q9LacOyel1hVudFpTxUssJDEpgRUEWRJo4s_G2utiURi0zbQ56UT1aJrWZgwawMyBLcmACj7UU06MOaKW6HfQvHsmXilHdFIWIyiNe2aaPJ-Z9hngTXkDPdmXFSB2UMrNBuF0IoW9jgyooucHWRVB4bVtBmT0RCXrLtyLKMyplAuwNFUjUllDsM8D19eeAvQA-7QlwpD4EucLsy8Mfp6naYXT1aUSOFw7rlS_-nV_3o2p_Ph7CZ0Mf-yHz7oG3cbb0r7IqlnPIKP9_1hn_3ZpsM0zvhzeaUBj6M5FUZMeJIDd8kCL5s-ZXsuZFzPYcgFqK6q3T0OiJalYwEawesP_MJ-f0MNhPXWgIJJ3PV7NJp09NszVX6iZrdhVTBbdgaOVXKtWF_amwPD5oM0BfhzXPAjdRIDMSy-ohOi-0Y7c_xWdPE-kPWbdyF5Z88kTLA_BuDCLgA_k5NHfdi1Hq6io9Gtgu8UKHSMxpuORDGvCu2L38OQnIk_EPYEJ8BaaFDyMDjqdY-LwCuhRjf1p_d7p4Cx6sM9odq6PEtCXuj-d82PsNo9V_LSIOdW-0ZgEFdjaVr5W_qbqkyFJ3KK0e3jugwF9PS75rL2ms-h5gD3AGGHISZeh9h2yD61QKqyK2fnpPCZvif5RDLOfAupCIou-HEPhxc8uHCulpgtayx8_ybOW0IDwpc34yarJXsb3EXnu-5gdHpgyUH6OdknWgyTydYqxslRm0zRMn3naFiIBEV-szxYoUB-kiQd0Fl8LATwrdxK4XV6qPEnCGGO0Vq4jrpfk5CU9C2Ixx9N2KTtwfqnV0nT-h3qL_G3q83WwwbB8x501p6d8L-kmnQPPWHotqeiOnA3KNTbB3iLJS-UloK9K5dmtE2ko__KdbsFlmHvLTGOjS8BLbJLfE6HwPO7s2B_VlwhpHtpj1PFRTOn32S8kdJCkyW2Ti9O2kTcmtS-kG-_xCZE6WahCJYzJcNg-gok1XjZLuTffjq8O1d1J-isEkUMjlwGMbC5689g-200UJb0CXiXaHOkkh0CryBxR_Kgpw_OfCWja8eysdjDbdIULai821Hgg3W_6abibQNscpmzFwyVrpBvl1gpJZNbKBloNEabBu1gqWaTccTCv7nPk2sCkTIbqAwx3B_LP2Q71-R0yZJoGlQftptUnE15OzEVXLOKl-YlTn9zhtfpdtgO_JF0f-EUpty2cQ2cNJ5qbIliIJUOkTyQqP6_D6N2FIAgnaHkDX0kR9fZK6tgrQDIlUly_noM2s0-rvy7Dar6Fhn2AzbF9c5GzzSkGOPoK2dM6N0zZenIw7fXV2R-FSNv5_nz3KPiN3Rowm2_AWPCmo9xtQVjqQku0Yo29ic5q5sqkjGPdV04cq4eFen6olpxB6M1Sw1PIvMgZXOOUtEQOB3GB_x_VIe9LyAvHKYnVVPc5WQbaK_posY-Nr9nN8vT4mFqajdD4gVRLRD5dqt-I0DUOLHgco3sBONPQRvk-ansl1NGhOfm7AvU8jQ0PDWKtqpR1TXGy2yjfhmN0vkaHDb3LzjwJ2YLbfhMBjW3gfVao-7XQqmJzVWU1MHWynG1MFKYm8kLVeXHL6BbQxym8MuB67sXuUyGGigbnGI9W-jflvs6Zu7DWzqYbhtgp6Y71CUIRfKVrPfvaLn02GrAOZgqp_61MTeQ2D7DDlMrM9G9ctZy7jHzPiYkYc-T0py6-eEGBOdO3bCGmSBbPLWB3biz43CxRngB0byusBISQyMQSli87mo|1710311226|tzcI0q_ZL29dYQfhGq8eotRiaxyNO9qedY5wWbracdY=",
    "path": "/",
    "secure": true,
    "hostOnly": true,
    "httpOnly": true,
    "expiry": 1710916026,
    "domain": "webpage being tested",
    "sameSite": "lax"
  }
]

In chorme horizontal scroll work , but in safari browser its not work

here is my code
this code not work on safari.

targetPosition i set the scroll value, for example , 11 , 22, 33 , where i scroll

  function ScrollToActiveTab(item, id, useraction) {
    if (item !== null && item !== undefined && useraction) {
      dispatch(addCurrentMenu(item));
    }
  
    requestAnimationFrame(() => {
      // Ensure this runs after any pending layout changes
      var scrollableDiv = document.getElementById('scrollableDiv');
      let tempId = 'targetId-' + id;
      var targetElement = document.getElementById(tempId);
  
      if (targetElement) {
        var targetPosition = targetElement.offsetLeft + targetElement.clientWidth / 2 - window.innerWidth / 2;
  
        // Perform the scroll
        scrollableDiv.scrollLeft = targetPosition;
      }
    });
  }

Please guide my why ° scrollableDiv.scrollLeft = targetPosition;° not work on safari. Thanks

i want work scrollableDiv.scrollLeft = targetPosition , in safari also
see attachment , i have a menu list once i click i update tragetPosition

menu Tab

Double axis Y in Chart.js

i want to ask for some questions about chart.js. I have been create my dashboard with chart.js for showing my database on user interface, but. I have a little bug on Axis Y in chart.js, like double category. This is my dashboard picture
none
And this my syntax.

<script>
        const canvas = document.getElementById('myChart');
        const ctx = canvas.getContext('2d');

        
        var chartData = {}; // Menyiapkan objek untuk menyimpan data chart

        var myChart = new Chart(ctx, {
            type: 'bar', // Menggunakan chart jenis bar
            data: {
                datasets: [{
                    label: 'Statistik Karyawan',
                    data: [],
                    backgroundColor: ['skyblue'], // Warna untuk masing-masing kategori
                    borderWidth: 1
                }],
                labels: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des']
            },
            options: {
                scales: {
                    y: {
                        beginAtZero: false,
                        ticks: {
                            callback: function(value, index, values) {
                                // Menampilkan label kategori sesuai index
                                return getCategoryLabel(value);
                            }
                        }
                    }
                },
                responsive: true, // Membuat chart responsif
                maintainAspectRatio: true // Mengatur rasio aspek chart
            }
        });

        // Fungsi untuk mendapatkan label kategori
        function getCategoryLabel(value) {
            // Menentukan label kategori sesuai nilai
            if (value >= 0 && value <= 1) {
                return 'Ringan';
            } else if (value >= 2 && value <= 3) {
                return 'Sedang';
            } else if (value >= 4) {
                return 'Berat';
            } else {
                return '';
            }
        }

        // Fungsi untuk mengupdate chart dengan data baru
        function updateChart(newData) {
            myChart.data.datasets[0].data = newData.allData;
            myChart.update();
        }

        // Fungsi untuk mengubah data chart saat terjadi perubahan
        function onDataChanged() {
            var newData = {
                allData: [0, 1, 2, 3, 4, 5, 6, 7]
            };

            // Menggunakan objek untuk melacak kategori yang sudah ditambahkan
            var addedCategories = {};

            // Memproses data baru dan menambahkannya ke chart
            newData.allData.forEach(function(value) {
                var categoryLabel = getCategoryLabel(value);

                // Menambahkan kategori ke chart hanya jika belum ada
                if (!addedCategories[categoryLabel]) {
                    addedCategories[categoryLabel] = true;
                    myChart.data.datasets[0].data.push(value);
                }
            });

            updateChart(newData);
        }

        onDataChanged();
    </script>

I’m so confused about this bug, please help me.

Ball rolling to the right only?

I’m relatively new to coding, and I’ve been experimenting with creating a bouncing ball animation. While most aspects of the coding have been okay, I’ve encountered a peculiar issue that has left me scratching my head. I’ve managed to get the ball to bounce, but for some reason, it seems to only roll to the right until it collides with the right side of the viewport. I’m really confused, and I’m eager to delve deeper into understanding what might be causing this unexpected behavior and how I can rectify it. Here’s the snippet of my JavaScript file:

var ball = document.querySelector('.ball'),
    isDragging = false,
    isAnimating = false,
    isAnimationAllowed = true, // New flag to control animation while dragging
    offsetX,
    offsetY,
    velocityX = 0,
    velocityY = 0,
    friction = 0.95,
    gravity = 0.5,
    floorLevel = 500,
    animationFrame;

ball.addEventListener('mousedown', startDragging);
ball.addEventListener('touchstart', startDragging);

function startDragging(event) {
    isDragging = true;
    isAnimating = false; // Reset isAnimating to false
    isAnimationAllowed = false; // Disable animation while dragging
    offsetX = event.clientX - ball.getBoundingClientRect().left;
    offsetY = event.clientY - ball.getBoundingClientRect().top;
  
    document.addEventListener('mousemove', drag);
    document.addEventListener('mouseup', stopDragging);
    
    document.addEventListener('touchmove', drag);
    document.addEventListener('touchend', stopDragging);
  }

function drag(event) {
  if (!isDragging) return;

  event.preventDefault();

  var newX, newY;

  if (event.type === 'mousemove') {
    newX = event.clientX - offsetX;
    newY = event.clientY - offsetY;
  } else if (event.type === 'touchmove') {
    newX = event.touches[0].clientX - offsetX;
    newY = event.touches[0].clientY - offsetY;
  }

  ball.style.left = newX + "px";
  ball.style.top = newY + "px";

  velocityX = newX - ball.offsetLeft;
  velocityY = newY - ball.offsetTop;
}

function stopDragging() {
  isDragging = false;
  isAnimationAllowed = true; // Enable animation after dragging stops

  document.removeEventListener('mousemove', drag);
  document.removeEventListener('mouseup', stopDragging);

  document.removeEventListener('touchmove', drag);
  document.removeEventListener('touchend', stopDragging);

  if (!isAnimating) {
    animate();
  }
}

function animate() {
  if (!isAnimationAllowed) return; // Check if animation is allowed
  
  isAnimating = true;

  animationFrame = requestAnimationFrame(animate);

  velocityX *= friction;
  velocityY += gravity;

  var newX = ball.offsetLeft + velocityX;
  var newY = ball.offsetTop + velocityY;

  if (newY >= floorLevel - ball.offsetHeight) {
    newY = floorLevel - ball.offsetHeight;
    velocityY *= -0.6; // Bounce effect
  }

  if (newX < 0) {
    newX = 0;
    velocityX *= -0.6; // Bounce effect for the left boundary
  } else if (newX > window.innerWidth - ball.offsetWidth) {
    newX = window.innerWidth - ball.offsetWidth;
    velocityX *= -0.6; // Bounce effect for the right boundary
  }

  ball.style.left = newX + "px";
  ball.style.top = newY + "px";

  if (Math.abs(velocityX) < 0.1 && Math.abs(velocityY) < 0.1 && newY >= floorLevel - ball.offsetHeight) {
    cancelAnimationFrame(animationFrame);
    isAnimating = false;
  }
}

Improve regex performance

I need help to improve regex performance (speed of execution) for ECMAscript (JavaScript on NodeJS 20) of:

/[u0000-u001fu0022u005cud800-udfff]|[ud800-udbff](?![udc00-udfff])|(?:[^ud800-udbff]|^)[udc00-udfff]/

This regular expression is designed to match certain Unicode characters in a string. Let’s break it down:

  • /[u0000-u001fu0022u005cud800-udfff]/: This part matches any
    character in the range of u0000 to u001f, the characters
    u0022 (quotation mark ") and u005c (backslash ), and any
    character in the range of ud800 to udfff. This range
    ud800-udfff covers surrogate pairs, which are used in UTF-16
    encoding for characters outside of the basic multilingual plane
    (BMP).
  • |: OR operator
  • [ud800-udbff](?![udc00-udfff]): This part matches the first
    part of a surrogate pair (ud800 to udbff) but only if it’s not
    followed by the second part of a surrogate pair (udc00 to
    udfff). This ensures that only valid surrogate pairs are matched.
  • |: Again, an OR operator.
  • (?:[^ud800-udbff]|^)[udc00-udfff]: This part matches the second
    part of a surrogate pair (udc00 to udfff) but only if it’s not
    preceded by the first part of a surrogate pair or if it’s at the
    beginning of the string. The ^ inside the square brackets [^]
    denotes negation, meaning any character other than the ones
    specified.

In summary, this regular expression is used to match and handle surrogate pairs correctly in Unicode strings, ensuring proper validation and handling of UTF-16 encoded characters.

regex101

Speed test over a string of 1000 chars

const REGEX = /[u0000-u001fu0022u005cud800-udfff]|[ud800-udbff](?![udc00-udfff])|(?:[^ud800-udbff]|^)[udc00-udfff]/

const start = performance.now()
console.log(REGEX.test('A'.repeat(10000) + '"')) // true
console.log(performance.now() - start)

Are there improvements that can be made?

The purpose is to have a very fast check for strings that do not need escaping while not being much slower than JSON.stringify() in case the input requires escaping.

How to highlight a word on mouseover in text in a React app

How to highlight a word on mouseover in text in a React app

const text = data[data.length - 1] !== undefined ? data[data.length - 1].taskText : null;

 const [hilightWord, setHilightWord] = useState(false);

  const hightlight = (text, hilightWord) => {
    if (!hilightWord) return text;

    const regex = new RegExp(`(${hilightWord})`, "gi");

    return text.split(regex).map((substring, i) => {
      return (
        <span className={styles.highlight} key={i}>
          {substring}
        </span>
      );
    });
  };


<p className={styles.text} onMouseMove={() => setHilightWord(true)} onMouseLeave={() => setHilightWord(false)}>{hightlight(text, hilightWord)}</p>