Jquery deferred : How to use promise without Deferred for sync calls in JS

I need to make a sync get rest call and i dont want to deffer it, i want to get result and act upon the value for next processing.

Based on input to a external api call i get a result and with the response i do some processing so i cant deffer the call.

I tried a call back function :

$scope.getRxHccValue = function (diagDesc) {
                     problemsModel.getRxHccValue(diagDesc, function () {
                        return problemsModel.rxHccValue;
                    });
                }

but while fetching call deffered.promise doesnt not return value synchronously

var deffered = this.$q.defer();
            this.$http.get(this.baseUrl + '/getRxHcc', { params: { diagDesc: diagDesc } })
                .success(function (data) {
                        deffered.resolve(data);
                });
            return deffered.promise;

CircularProgress TypeError: Cannot read properties of undefined (reading ‘main’)

I am new to React and Next.js, whilst upgrading from Node V16 to Node V18. One of the changes was to MUI from v4 to v5, currently using the packages

"@emotion/babel-plugin": "^11.11.0",
"@emotion/core": "^10.1.1",
"@emotion/react": "^11.11.4",
"@emotion/server": "^11.11.0",
"@emotion/styled": "^11.11.5",
"@mui/icons-material": "^5.15.13",
"@mui/lab": "^5.0.0-alpha.168",
"@mui/material": "^5.15.13".
"next": "14.1.3"

I ran all the codemods that were suggested on the official MUI documentation found here https://mui.com/material-ui/migration/v5-style-changes/. Unfortunately the solution did not find certain packages. So I Googled a bit and found this post: https://github.com/styled-components/styled-components/issues/2502. I copied his implementation then ran into this problem after some basic debugging. TypeError: Cannot read properties of undefined (reading ‘main’)

the _document.js code

import Document, { Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheet } from 'styled-components';
import { renderToString } from 'react-dom/server';
import { extractCritical } from '@emotion/server';

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);

      // Extract critical CSS
      const emotionStyles = extractCritical(<Main />);
      const emotionCss = emotionStyles.css;

      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            <style dangerouslySetInnerHTML={{ __html: emotionCss }} />
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }

  render() {
    return (
      <Html lang="en">
        <Head>
          <meta name="description" content="" />
          <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
        </Head>
        <body>
          <noscript>You need JavaScript to use this web application</noscript>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

Loading.js code (the only place where it calls CircularProgress package

import * as React from 'react';
import CircularProgress from '@mui/material/CircularProgress';
import styled from '@emotion/styled'

import { createTheme, ThemeProvider } from '@mui/system';


const theme = createTheme();
const Container = styled.div`
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
`;

function Loading() {
  const [progress, setProgress] = React.useState(0);

  React.useEffect(() => {
    function tick() {
      // reset when reaching 100%
      setProgress((oldProgress) => (oldProgress >= 100 ? 0 : oldProgress + 1));
    }

    const timer = setInterval(tick, 20);
    return () => {
      clearInterval(timer);
    };
  }, []);

  return (
    <ThemeProvider theme={theme}>
    <Container>
      <CircularProgress variant="determinate" value={progress} />
    </Container>
    </ThemeProvider>
  );
}

export default Loading;

and the error that is giving me:

TypeError: Cannot read properties of undefined (reading 'main')
    at CircularProgressRoot.ownerState.ownerState (PATHnode_modules@muimaterialnodeCircularProgressCircularProgress.js:82:58)
    at processStyleArg ([email protected]:66:67)
    at [email protected]:172:25
    at handleInterpolation (PATHnode_modules@emotionserializedistemotion-serialize.cjs.dev.js:149:24)
    at Object.serializeStyles (PATHnode_modules@emotionserializedistemotion-serialize.cjs.dev.js:274:15)
    at PATHnode_modules@emotionstyledbasedistemotion-styled-base.cjs.dev.js:167:34
    at PATHnode_modules@emotionreactdistemotion-element-f93e57b0.cjs.dev.js:85:16
    at renderWithHooks (PATHnode_modulesreact-domcjsreact-dom-server.browser.development.js:5658:16)
    at renderIndeterminateComponent (PATHnode_modulesreact-domcjsreact-dom-server.browser.development.js:5731:15)
    at renderElement (PATHnode_modulesreact-domcjsreact-dom-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (PATHnode_modulesreact-domcjsreact-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (PATHnode_modulesreact-domcjsreact-dom-server.browser.development.js:6076:14)
    at renderForwardRef (PATHnode_modulesreact-domcjsreact-dom-server.browser.development.js:5859:5)
    at renderElement (PATHnode_modulesreact-domcjsreact-dom-server.browser.development.js:6005:11)
    at renderNodeDestructiveImpl (PATHnode_modulesreact-domcjsreact-dom-server.browser.development.js:6104:11) {
  page: '/'
}

I have tried reading Stack Overflow comments, asking Chatgpt, Perplexity AI, Youtube and CircularProgress documentation for guidance yet I still feel lost.

How to fix my js built table whenever I add an extra column to be placed as its first column?

I have a table made with js based on data from 2 arrays of objects that I have.

One of the arrays contains all the subzones and the second array contains microzones, microzones can be children of the same subzone.

I made a function that builds a table so that the data will be placed like this in the table(take into consideration that the row-span in this example for SI-N1 is 3 while microzone column has 3 rows for microzone 1,2 and 3 since they are children of subzone SI-N1)

Sub-zone Micro-Zone
SI-N4 CONCEPCION
SI-N1 microzone 1
microzone 2
microzone 3

My code works when I’m just displaying the data like this

const subZones = [
    {
        "creationUserId": 1913,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "SI-N4",
        "id": 65,
        "creationDate": "2022-12-08 13:04:23"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateDate": "2019-12-18 10:39:27",
        "lastUpdateUserId": 2,
        "active": true,
        "description": "SI-N1",
        "id": 1,
        "controlId": "9",
        "creationDate": "2019-11-15 15:03:09"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "OF-N3",
        "id": 49,
        "creationDate": "2020-11-26 16:44:41"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "PU-N2",
        "id": 28,
        "controlId": "18",
        "creationDate": "2019-12-18 11:39:44"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "PU-N1",
        "id": 29,
        "controlId": "19",
        "creationDate": "2019-12-18 11:39:44"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "PU-N4",
        "id": 39,
        "controlId": "20",
        "creationDate": "2020-11-24 16:24:21"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "OF-N2",
        "id": 48,
        "controlId": "22",
        "creationDate": "2020-11-26 16:44:41"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "OF-N1",
        "id": 47,
        "controlId": "23",
        "creationDate": "2020-11-26 16:44:41"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateDate": "2019-12-18 10:39:19",
        "lastUpdateUserId": 2,
        "active": true,
        "description": "SI-N2",
        "id": 2,
        "creationDate": "2019-11-15 15:03:09"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateDate": "2023-12-15 16:26:38",
        "lastUpdateUserId": 2,
        "active": false,
        "description": "SI-N3",
        "id": 3,
        "creationDate": "2019-11-15 15:03:09"
    }
];

const microZones = [
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "COLONIA NUEVA DURANGO",
        "id": 37,
        "creationDate": "2022-12-08 00:58:56"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "GUAJAYVI",
        "id": 39,
        "creationDate": "2022-12-08 00:59:48"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "NUEVA CONQUISTA",
        "id": 40,
        "creationDate": "2022-12-08 00:59:54"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "SANTANI",
        "id": 41,
        "creationDate": "2022-12-08 13:00:00"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "VILLA DEL ROSARIO",
        "id": 42,
        "creationDate": "2022-12-08 13:00:06"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "VILLA YGATIMI",
        "id": 43,
        "creationDate": "2022-12-08 13:00:38"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 2,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "ANTEQUERA",
        "id": 44,
        "creationDate": "2022-12-08 13:01:05"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 2,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "LIBERACION",
        "id": 45,
        "creationDate": "2022-12-08 13:01:11"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 2,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "SANTA ROSA DEL AGUARAY",
        "id": 46,
        "creationDate": "2022-12-08 13:01:48"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 2,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "TACUATI",
        "id": 47,
        "creationDate": "2022-12-08 13:01:55"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 3,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "CAPITAN BADO",
        "id": 48,
        "creationDate": "2022-12-08 13:02:59"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 3,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "PEDRO JUAN CABALLERO",
        "id": 49,
        "creationDate": "2022-12-08 13:03:06"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 65,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "CONCEPCION",
        "id": 50,
        "creationDate": "2022-12-08 13:04:39"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateDate": "2023-01-25 11:55:19",
        "lastUpdateUserId": 1913,
        "active": true,
        "description": "CURUGUATY",
        "id": 38,
        "creationDate": "2022-12-08 00:59:03"
    }
];

function generateZoneTable(subzones, microzones, isEdition) {
    const tableBody = document.getElementById('tBodyContainerLocationSubZone');

    subzones.forEach((subzone) => {
        const subzoneMicrozones = microzones.filter((microzone) => microzone.locationSubZoneId === subzone.id);
        const subzoneRowCount = subzoneMicrozones.length;

        subzoneMicrozones.forEach((microzone, index) => {
            const subzoneRow = document.createElement('tr');

            if (isEdition){
                if (index === 0) {
                    //columna para desasociar
                    const unBind = document.createElement('td');
                    unBind.innerHTML = '<i class="mdi mdi-link-off"></i>'; // Insert icon or content
                    unBind.setAttribute('rowspan', subzoneRowCount);
                    subzoneRow.appendChild(unBind);
                }

                //columna para subzona
                const subzoneCell = document.createElement('td');
                subzoneCell.textContent = subzone.description;
                subzoneCell.setAttribute('rowspan', subzoneRowCount);

                //icono de ojo para la subzona
                const subzoneIcon = document.createElement('i');
                subzoneIcon.classList.add('mdi', 'mdi-eye', 'ml-1');
                subzoneIcon.style.cursor = 'pointer';
                subzoneIcon.addEventListener('click', () => {
                    showLocationSubZone(subzone.id, "zoneView", false);
                });
                subzoneCell.appendChild(subzoneIcon);
                subzoneRow.appendChild(subzoneCell);
            } else {
                if (index === 0) {
                    //columna para subzona
                    const subzoneCell = document.createElement('td');
                    subzoneCell.textContent = subzone.description;
                    subzoneCell.setAttribute('rowspan', subzoneRowCount);

                    //icono de ojo para la subzona
                    const subzoneIcon = document.createElement('i');
                    subzoneIcon.classList.add('mdi', 'mdi-eye', 'ml-1');
                    subzoneIcon.style.cursor = 'pointer';
                    subzoneIcon.addEventListener('click', () => {
                        showLocationSubZone(subzone.id, "zoneView", false);
                    });
                    subzoneCell.appendChild(subzoneIcon);
                    subzoneRow.appendChild(subzoneCell);
                }
            }
            //columna para microzona
            const microzoneCell = document.createElement('td');
            microzoneCell.textContent = microzone.description;

            // icono de ojo para la microzona
            const microzoneIcon = document.createElement('i');
            microzoneIcon.classList.add('mdi', 'mdi-eye', 'ml-1');
            microzoneIcon.style.cursor = 'pointer'; // Cambiar el cursor al puntero
            microzoneIcon.addEventListener('click', () => {
                showLocationSubZone(microzone.id, "zoneView", true);
            });
            microzoneCell.appendChild(microzoneIcon);

            subzoneRow.appendChild(microzoneCell);
            tableBody.appendChild(subzoneRow);
        });
    });
}

generateZoneTable(subZones, microZones, false);
/* Add border to table and cells */
.table-bordered {
    border: 1px solid #dee2e6;
}

.table-bordered th,
.table-bordered td {
    border: 1px solid #dee2e6;
}

/* Add padding to table cells */
.table th,
.table td {
    padding: 0.75rem;
}

/* Center the content of table cells */
.table td,
.table th {
    text-align: center;
}

/* Add margin to the table */
#zoneGeographicAssociation {
    margin-top: 10px; /* Adjust as needed */
}

/* Style the button */
.btn-secondary {
    color: #fff;
    background-color: #6c757d;
    border-color: #6c757d;
}

.btn-secondary:hover {
    color: #fff;
    background-color: #5a6268;
    border-color: #545b62;
}

.btn-secondary:focus, .btn-secondary.focus {
    box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);
}

.btn-secondary.disabled, .btn-secondary:disabled {
    color: #fff;
    background-color: #6c757d;
    border-color: #6c757d;
}

/* Adjust spacing between elements */
.input-group {
    margin-bottom: 10px;
}

/* Optional: Add hover effect to table rows */
.table-hover tbody tr:hover {
    background-color: #f8f9fa;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font/css/materialdesignicons.min.css">
<div class="col-md-12 col-sm-12 mt-3">
    <div class="row">
        <div class="input-group">
            <h4>Asociación Geográfica</h4>
            <button type="button" class="btn btn-secondary btn-sm ml-1 " onclick="createLocationSubZone(true)">Agregar</button>
        </div>
        <table class="table table-bordered table-centered mb-0 mt-3" id="zoneGeographicAssociation" style="width:100%;">
            <thead>
                <tr>
                    <th class="w-50">Sub-Zonas</th>
                    <th class="w-50">Micro-Zonas</th>
                </tr>
            </thead>
            <tbody id="tBodyContainerLocationSubZone">
            </tbody>
        </table>
    </div>
</div>

However whenever I need to edit the data then my HTML transforms to add an extra column before subzone with the header “desasociar” and the value of the isEdition parameter becomes true and that’s when my table gets all messed up and it looks like this

const subZones = [
    {
        "creationUserId": 1913,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "SI-N4",
        "id": 65,
        "creationDate": "2022-12-08 13:04:23"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateDate": "2019-12-18 10:39:27",
        "lastUpdateUserId": 2,
        "active": true,
        "description": "SI-N1",
        "id": 1,
        "controlId": "9",
        "creationDate": "2019-11-15 15:03:09"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "OF-N3",
        "id": 49,
        "creationDate": "2020-11-26 16:44:41"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "PU-N2",
        "id": 28,
        "controlId": "18",
        "creationDate": "2019-12-18 11:39:44"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "PU-N1",
        "id": 29,
        "controlId": "19",
        "creationDate": "2019-12-18 11:39:44"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "PU-N4",
        "id": 39,
        "controlId": "20",
        "creationDate": "2020-11-24 16:24:21"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "OF-N2",
        "id": 48,
        "controlId": "22",
        "creationDate": "2020-11-26 16:44:41"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "OF-N1",
        "id": 47,
        "controlId": "23",
        "creationDate": "2020-11-26 16:44:41"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateDate": "2019-12-18 10:39:19",
        "lastUpdateUserId": 2,
        "active": true,
        "description": "SI-N2",
        "id": 2,
        "creationDate": "2019-11-15 15:03:09"
    },
    {
        "creationUserId": 2,
        "locationZoneId": 1,
        "lastUpdateDate": "2023-12-15 16:26:38",
        "lastUpdateUserId": 2,
        "active": false,
        "description": "SI-N3",
        "id": 3,
        "creationDate": "2019-11-15 15:03:09"
    }
];

const microZones = [
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "COLONIA NUEVA DURANGO",
        "id": 37,
        "creationDate": "2022-12-08 00:58:56"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "GUAJAYVI",
        "id": 39,
        "creationDate": "2022-12-08 00:59:48"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "NUEVA CONQUISTA",
        "id": 40,
        "creationDate": "2022-12-08 00:59:54"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "SANTANI",
        "id": 41,
        "creationDate": "2022-12-08 13:00:00"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "VILLA DEL ROSARIO",
        "id": 42,
        "creationDate": "2022-12-08 13:00:06"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "VILLA YGATIMI",
        "id": 43,
        "creationDate": "2022-12-08 13:00:38"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 2,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "ANTEQUERA",
        "id": 44,
        "creationDate": "2022-12-08 13:01:05"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 2,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "LIBERACION",
        "id": 45,
        "creationDate": "2022-12-08 13:01:11"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 2,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "SANTA ROSA DEL AGUARAY",
        "id": 46,
        "creationDate": "2022-12-08 13:01:48"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 2,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "TACUATI",
        "id": 47,
        "creationDate": "2022-12-08 13:01:55"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 3,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "CAPITAN BADO",
        "id": 48,
        "creationDate": "2022-12-08 13:02:59"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 3,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "PEDRO JUAN CABALLERO",
        "id": 49,
        "creationDate": "2022-12-08 13:03:06"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 65,
        "lastUpdateUserId": 0,
        "active": true,
        "description": "CONCEPCION",
        "id": 50,
        "creationDate": "2022-12-08 13:04:39"
    },
    {
        "creationUserId": 1913,
        "locationSubZoneId": 1,
        "lastUpdateDate": "2023-01-25 11:55:19",
        "lastUpdateUserId": 1913,
        "active": true,
        "description": "CURUGUATY",
        "id": 38,
        "creationDate": "2022-12-08 00:59:03"
    }
];

function generateZoneTable(subzones, microzones, isEdition) {
    const tableBody = document.getElementById('tBodyContainerLocationSubZone');

    subzones.forEach((subzone) => {
        const subzoneMicrozones = microzones.filter((microzone) => microzone.locationSubZoneId === subzone.id);
        const subzoneRowCount = subzoneMicrozones.length;

        subzoneMicrozones.forEach((microzone, index) => {
            const subzoneRow = document.createElement('tr');

            if (isEdition){
                if (index === 0) {
                    //columna para desasociar
                    const unBind = document.createElement('td');
                    unBind.innerHTML = '<i class="mdi mdi-link-off"></i>'; // Insert icon or content
                    unBind.setAttribute('rowspan', subzoneRowCount);
                    subzoneRow.appendChild(unBind);
                }

                //columna para subzona
                const subzoneCell = document.createElement('td');
                subzoneCell.textContent = subzone.description;
                subzoneCell.setAttribute('rowspan', subzoneRowCount);

                //icono de ojo para la subzona
                const subzoneIcon = document.createElement('i');
                subzoneIcon.classList.add('mdi', 'mdi-eye', 'ml-1');
                subzoneIcon.style.cursor = 'pointer';
                subzoneIcon.addEventListener('click', () => {
                    showLocationSubZone(subzone.id, "zoneView", false);
                });
                subzoneCell.appendChild(subzoneIcon);
                subzoneRow.appendChild(subzoneCell);
            } else {
                if (index === 0) {
                    //columna para subzona
                    const subzoneCell = document.createElement('td');
                    subzoneCell.textContent = subzone.description;
                    subzoneCell.setAttribute('rowspan', subzoneRowCount);

                    //icono de ojo para la subzona
                    const subzoneIcon = document.createElement('i');
                    subzoneIcon.classList.add('mdi', 'mdi-eye', 'ml-1');
                    subzoneIcon.style.cursor = 'pointer';
                    subzoneIcon.addEventListener('click', () => {
                        showLocationSubZone(subzone.id, "zoneView", false);
                    });
                    subzoneCell.appendChild(subzoneIcon);
                    subzoneRow.appendChild(subzoneCell);
                }
            }
            //columna para microzona
            const microzoneCell = document.createElement('td');
            microzoneCell.textContent = microzone.description;

            // icono de ojo para la microzona
            const microzoneIcon = document.createElement('i');
            microzoneIcon.classList.add('mdi', 'mdi-eye', 'ml-1');
            microzoneIcon.style.cursor = 'pointer'; // Cambiar el cursor al puntero
            microzoneIcon.addEventListener('click', () => {
                showLocationSubZone(microzone.id, "zoneView", true);
            });
            microzoneCell.appendChild(microzoneIcon);

            subzoneRow.appendChild(microzoneCell);
            tableBody.appendChild(subzoneRow);
        });
    });
}

generateZoneTable(subZones, microZones, true);
/* Add border to table and cells */
.table-bordered {
    border: 1px solid #dee2e6;
}

.table-bordered th,
.table-bordered td {
    border: 1px solid #dee2e6;
}

/* Add padding to table cells */
.table th,
.table td {
    padding: 0.75rem;
}

/* Center the content of table cells */
.table td,
.table th {
    text-align: center;
}

/* Add margin to the table */
#zoneGeographicAssociation {
    margin-top: 10px; /* Adjust as needed */
}

/* Style the button */
.btn-secondary {
    color: #fff;
    background-color: #6c757d;
    border-color: #6c757d;
}

.btn-secondary:hover {
    color: #fff;
    background-color: #5a6268;
    border-color: #545b62;
}

.btn-secondary:focus, .btn-secondary.focus {
    box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);
}

.btn-secondary.disabled, .btn-secondary:disabled {
    color: #fff;
    background-color: #6c757d;
    border-color: #6c757d;
}

/* Adjust spacing between elements */
.input-group {
    margin-bottom: 10px;
}

/* Optional: Add hover effect to table rows */
.table-hover tbody tr:hover {
    background-color: #f8f9fa;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font/css/materialdesignicons.min.css">
<div class="col-md-12 col-sm-12 mt-3">
    <div class="row">
        <div class="input-group">
            <h4>Asociación Geográfica</h4>
            <button type="button" class="btn btn-secondary btn-sm ml-1 " onclick="createLocationSubZone(true)">Agregar</button>
        </div>
        <table class="table table-bordered table-centered mb-0 mt-3" id="zoneGeographicAssociation" style="width:100%;">
            <thead>
                <tr>
                    <th class="w-10">Desasociar</th>
                    <th class="w-40">Sub-Zonas</th>
                    <th class="w-50">Micro-Zonas</th>
                </tr>
            </thead>
            <tbody id="tBodyContainerLocationSubZone">
            </tbody>
        </table>
    </div>
</div>

The behaviour I’m expecting to get is just an extra column at the beggining of the table with an icon that will have a function later(this part not important now) the extra column with the icon is supposed to share the same rowspan as the subzone, the rest needs to look the same but my table is all messed up.

Any help is appreciated

How to make the series text responsive in highcharts?

I am using highcharts. Everything seems fine but I am not sure how to make the series text (LLLL! LLLL! LLLL!, XYZM XYZM XYZM XYZM) responsive/ wrap text depending upon the screen size? Right now, if I minimize the screen, the text overlaps on each other. Is there a way to make the text wrap instead of overlapping? Here is my code.

// container7
var chartOptions = {
  chart: {
    type: 'column',
    inverted: true,
    height: 200


  },
  title: {
    text: ''
  },
  xAxis: {
    lineColor: 'white',
    categories: ['ABCD'],
    labels: {
      padding: 40, // Add padding of 40 to the x-axis labels
      style: {
        fontSize: '12px' // Adjust the font size as needed
      }
    }
  },
  yAxis: {
    allowDecimals: false,
    max: 100,
    title: {
      text: ''
    },
    labels: {
      enabled: false // Hide y-axis labels
    },
    gridLineWidth: 0 // Remove grid lines
  },
  plotOptions: {
    column: {
      stacking: 'normal', // this will be our default
      dataLabels: {
        enabled: true,
        style: {
          color: 'black', // Set font color to black
          fontSize: '13px', // Set font size to 12px
          textShadow: 'none' // Remove text shadow
        },
        backgroundColor: 'rgba(0, 0, 0, 0)', // Set background color to transparent
        formatter: function() {
          return this.series.name + ': ' + Highcharts.numberFormat(this.y, 0) + '%';
        }
      }
    }
  },


  colors: ['#d37295', '#fabfd2'],
  series: [{
    name: 'LLLL!LLLL!LLLL!LLLL!LLLL!LLLL!LLLL!',
    data: [57]
  }, {
    name: 'XYZM XYZMXYZMXYZMXYZM XYZMXYZM XYZM XYZM',
    data: [43]
  }],
  legend: {
    enabled: false // Hide the legend
  },
  credits: {
    enabled: false // Hide the credits
  }
};

// Render the chart using Highcharts
Highcharts.chart('container7', chartOptions);
<script src="https://code.highcharts.com/highcharts.js"></script>
<h2>... look like this:</h2>
<div id="container7" style=" border: 1px solid lightgray;"></div>

Time Calculation (PHP, JS, MYSQL) [closed]

I have the following script ready for calculating the attendance of staff

index.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dynamic Table</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css">
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="container mt-5">
        <h1 class="text-center mb-5">Dynamic Table</h1>
        <form id="myForm">
            <table class="table">
                <thead>
                    <tr>
                        <th>Description</th>
                        <th>Start Time</th>
                        <th>End Time</th>
                        <th>Time Taken</th>
                        <th>Total Time Taken</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>
                            <input type="text" name="description[]" class="form-control">
                        </td>
                        <td>
                            <input type="datetime-local" name="start_time[]" class="form-control start_time" required>
                        </td>
                        <td>
                            <input type="datetime-local" name="end_time[]" class="form-control end_time" required>
                        </td>
                        <td>
                            <input type="text" name="time_taken[]" class="form-control time_taken" readonly>
                        </td>
                        <td>
                            <input type="text" name="total_time_taken[]" class="form-control total_time_taken" readonly>
                        </td>
                        <td>
                            <i class="fas fa-trash delete-row" style="display: none;"></i>
                        </td>
                    </tr>
                </tbody>
            </table>
            <button type="button" class="btn btn-primary" id="addRow">Add Row</button>
            <button type="button" class="btn btn-primary" id="validate" style="display: none;">Validate</button>
            <button type="submit" class="btn btn-primary" id="submit" style="display: none;">Submit</button>
            <p class="error-message"></p>
        </form>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="script.js"></script>
</body>
</html>

script.js

$(document).ready(function() {
    let rowCounter = 1;
    let totalTimeTaken = 0;

    // Function to calculate time difference
    function calculateTimeDifference(start, end) {
        const startDate = new Date(start);
        const endDate = new Date(end);

        const diffInMilliseconds = Math.abs(endDate - startDate);
        const days = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24));
        const hours = Math.floor((diffInMilliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
        const minutes = Math.floor((diffInMilliseconds % (1000 * 60 * 60)) / (1000 * 60));

        return `${days} days ${hours} hrs ${minutes} mins`;
    }

    // Function to calculate total time taken
    function calculateTotalTimeTaken(timeTakenArray) {
        let totalTimeTaken = 0;

        timeTakenArray.forEach(timeTaken => {
            totalTimeTaken += timeTaken;
        });

        return totalTimeTaken;
    }

    // Function to create a new row
    function createNewRow() {
        if (rowCounter > 1) {
            $('input[name="start_time[]"]:last').attr('readonly', true);
            $('.delete-row:last').show();
        }

        const rowHtml = `<tr>
                <td>
                    <textarea name="description[]" class="form-control" rows="1"></textarea>
                </td>
                <td>
                    <input type="datetime-local" name="start_time[]" class="form-control start_time" required>
                </td>
                <td>
                    <input type="datetime-local" name="end_time[]" class="form-control end_time" required>
                </td>
                <td>
                    <input type="text" name="time_taken[]" class="form-control time_taken" readonly>
                </td>
                <td>
                    <input type="text" name="total_time_taken[]" class="form-control total_time_taken" readonly>
                </td>
                <td>
                    <i class="fas fa-trash delete-row"></i>
                </td>
            </tr>
        `;

        $('#myForm table tbody').append(rowHtml);
        rowCounter++;
    }

    // Function to remove the last row
    function removeLastRow() {
        if (rowCounter > 1) {
            $('table tbody tr:last-child').remove();
            rowCounter--;
        }
    }

    // Event listener for adding a new row
    $('#addRow').click(function() {
        createNewRow();
    });

    // Event listener for removing the last row
    $(document).on('click', '.delete-row', function() {
        removeLastRow();
    });

    // Event listener for datetime input
    $(document).on('change', '.start_time, .end_time', function() {
        const row = $(this).closest('tr');
        const startTime = row.find('.start_time').val();
        const endTime = row.find('.end_time').val();

        if (endTime < startTime) {
            row.find('.end_time').addClass('is-invalid');
            row.find('.start_time').addClass('is-invalid');
            $('.error-message').text('End time cannot be less than start time.');
        } else {
            row.find('.end_time').removeClass('is-invalid');
            row.find('.start_time').removeClass('is-invalid');
            $('.error-message').text('');

            const timeTaken = calculateTimeDifference(startTime, endTime);
            row.find('.time_taken').val(timeTaken);

            const timeTakenArray = $('input[name="time_taken[]"]').map(function() {
                return $(this).val();
            }).get();

            let currentRowTotalTimeTaken = calculateTotalTimeTaken(timeTakenArray);

            if (rowCounter > 1) {
                currentRowTotalTimeTaken += timeTaken;
            } else {
                currentRowTotalTimeTaken = timeTaken;
            }

            row.find('.total_time_taken').val(currentRowTotalTimeTaken);
            totalTimeTaken = currentRowTotalTimeTaken;
        }
    });

    // Event listener for form submission
    $('#myForm').on('submit', function(e) {
        e.preventDefault();

        if ($('.is-invalid').length > 0) {
            return;
        }

        $.ajax({
            url: 'submit.php',
            method: 'post',
            data: $(this).serialize(),
            success: function(response) {
                console.log(response);
                alert('Data submitted successfully!');
            },
            error: function(jqXHR, textStatus, errorThrown) {
                console.error(textStatus, errorThrown);
                alert('Error occurred while submitting data.');
            }
        });
    });

    // Show/hide buttons
    $('#addRow').click(function() {
        $('#validate').show();
    });

    $('button[type="button"]').click(function() {
        if ($(this).attr('id') === 'validate') {
            $('#submit').show();
            $(this).hide();
        }

        if ($(this).attr('id') === 'submit') {
            $(this).hide();
        }
    });
});

submit.php

<?php
// Database connection
$servername = "localhost";
$username = "your_username";
$password = "your_password";
$dbname = "your_database";

$conn = new mysqli($servername, $username, $password, $dbname);

if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// Get data from the form
$description = $_POST['description'];
$start_time = $_POST['start_time'];
$end_time = $_POST['end_time'];
$time_taken = $_POST['time_taken'];
$total_time_taken = $_POST['total_time_taken'];

// Insert into the database
for ($i = 0; $i < count($description); $i++) {
    $sql= "INSERT INTO your_table (description, start_time, end_time, time_taken, total_time_taken)
            VALUES ('{$description[$i]}', '{$start_time[$i]}', '{$end_time[$i]}', '{$time_taken[$i]}', '{$total_time_taken[$i]}')";

    if ($conn->query($sql) === FALSE) {
        echo "Error: " . $sql . "<br>" . $conn->error;
    }
}

// Close the connection
$conn->close();
?>

I need the value as below,
First row time taken = 1 days 16 hrs 32 mins | Total time taken = 1 days 16 hrs 32 mins
Second row time taken = 8 mins | Total time taken = 1 days 16 hrs 40 mins

The total time taken should be the sum of all time taken upto the current row. But when i run the code, the total time taken just add the text values like below

First row time taken = 1 days 16 hrs 32 mins | Total time taken = 1 days 16 hrs 32 mins
Second row time taken = 8 mins | Total time taken = 1 days 16 hrs 32 mins 0 days 0 hrs 8 mins

I tried changing the type of input from text to date-time with no luck.

Secondly
I would like to validate if the end time of the first/previous row is equal to the start time of the current row if not to throw an error.

I’m not able to retrieve the live value of the fields since js is run when the documents is loaded.

Google map API zoom plus, minus, tilt map and full screen icons are broken

I have implemented google-map in my Angular project with below settings:

this.options = {
      center: { lat: this.filters.locationLat, lng: this.filters.locationLong },
      zoom: 8,
      zoomControl: true,
      fullscreenControl: true,
      disableDefaultUI: false,
      clickableIcons: true,
      draggable: false,
      mapTypeControl: false,
      streetViewControl: false,
      tilt: 0,
      keyboardShortcuts: false,
      maxZoom: 18,
    };

<google-map (mapInitialized)="onMapReady($event)" [options]="options">
  <map-marker-clusterer> </map-marker-clusterer>
</google-map>

But somehow it is breaking the zoom plus, minus, tilt map and full screen icons as below:

Google-map

Note: I am not getting any error on my console regarding Google map.

I have an issue with excel js property – protection{locked:true}

I am creating and downloading an excel sheet using excel.js. I have a task like making certain columns and rows uneditable. I searched for it, I got a way like giving protected{locked: true} should protect the cells and should be uneditable, but when i download the excel, iam still able to edit the cells.

mergedWorkbook.eachSheet((worksheet) => {
    const lastColumnIndex = worksheet.columns.length;

    const protectedColumns = [0, 1, 2, lastColumnIndex];

    // Protect specified columns
    worksheet.columns.forEach((column, columnIndex) => {
      if (protectedColumns.includes(columnIndex)) {
        column.eachCell((cell) => {
          cell.protection = {
            locked: true,
          };
        });
      }
    });

    // Protect header row
    worksheet.getRow(1).eachCell((cell) => {
      cell.protection = {
        locked: true,
      };
    });
  });

How to get (#document (url)) in

I don’t know how to get (#document (url)) under <object>.

I want get that URL at variable, then use .

Is it possible at jQuery and console ?

I try this, but I think it’s not what I want.

ex)

<object id="ext_obj_1" type="text/html" data="https://en.wikipedia.org/wiki/">Not loading</object>

If I action this code in browser, devTool(F12) monitor is that.

<object id="ext_obj_1" type="text/html" data="https://en.wikipedia.org/wiki/">
    #document (https://en.wikipedia.org/wiki/Main_Page)
        <!DOCTYPE html>
        ~ ~ ~
</object>

Then if I click any keyword in wiki(embeded screen by <object>), monitor change that.

<object id="ext_obj_1" type="text/html" data="https://en.wikipedia.org/wiki/">
    #document (https://en.wikipedia.org/wiki/Encyclopedia)
        <!DOCTYPE html>
        ~ ~ ~
</object>

So I want how to get (#document (url)) under <object>.

Is it possible at jQuery and console ?

jQueru Ui autocomlete remote with image

This jQuery Ui Autocomplete code with image works perfectly well, but the image appears on top of the text, I would like the image to appear on the left and text on the right, like the photo below. Any suggestions?

$(function() {
var cache = {};
$("#myAutocomplete").autocomplete({
 minLength: 1,     
 source: function(request, response) {
  var term = request.term;
  if (term in cache) {
   response(cache[term]);
   return;
  }
  $.getJSON("services/test_ima_JAutocomplete1.asp", request, function(data, status, xhr) {
   status, xhr ) {
   cache[term] = data;
   response(data);
  });
 }
}).data("ui-autocomplete")._renderItem = function (ul, item) {
     return $("<li></li>")
         .data("item.autocomplete", item)
         .append("<img src="+ item.image + ">" + "<a>" + item.label + "</a>" )
          .appendTo(ul);
  }
});

Can we display the local datetime to the User in MVC using Javascript? [closed]

I need to display the datetime received in CET to the local time of user by using javascript in a .NET MVC application. How can this be done?

<table>
    <thead>
        <tr>
            <th>Date</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td data-utc-time="@item.ScheduledTime?.ToUniversalTime().ToString("o")">@item.ScheduledTime.HasValue ? item.ScheduledTime.Value.ToUniversalTime() : "N/A"</td>
        </tr>
    </tbody>
</table>
function convertUtcToLocal() {
    document.querySelectorAll('[data-utc-time]').forEach(function (element) {
        const utcTime = element.getAttribute('data-utc-time');
        if (utcTime) {
            const localTime = new Date(utcTime).toLocaleString('en-GB', {
                year: 'numeric',
                month: '2-digit',
                day: '2-digit',
                hour: '2-digit',
                minute: '2-digit',
                hour12: false
            });
            element.textContent = localTime;
        }
    });
}

This is the code I tried I added a class for each datetime and got the utc time using ToUniversalTime() and then used ToLocaleString() to convert the UTC time to local time of user but this does not work

Retrieving firstName from a Firebase Realtime Database where UserId matches the uid of the person logged in

I have tried to figure this out using tutorials and videos and can’t get it to work. My Firebase Realtime database has a table called “users”. In the users table are two fields – UserId and firstName.

I want to retrieve the firstName field value of the record where UserId = uid of currently logged in user. Here is my code:

//monitoring authchanges 
onAuthStateChanged(auth, async (user) => {
    if (user) {
        const uid = user.uid;
        const firstname = await getFirstnameOfLoggedInUser();
        if (firstname) {
            welcomeTxt.textContent = "Welcome back, " + firstname + "!";
        } else {
            // Handle case where firstname retrieval fails (optional)
        }
    } else {
        console.log("user is logged out");
        welcomeTxt.textContent = "Welcome! Please sign in or create an account.";
    }
});

//get FirstName of person logged in
async function getFirstnameOfLoggedInUser() {
    const user = auth.currentUser;
    console.log(user);
    if (user) {
        const uid = user.uid;
        console.log(uid);
        const userRef = ref(database, "users/" + uid);
        console.log(userRef);
        get(userRef, (snapshot) => {
            const userdata = snapshot.val().firstName;

            console.log(userdata);
        });
    }
}

This code logs the current uid correctly but does not retrieve the correct record in the users table even though I see that the UserId and uid match. Please help!

how to paginate using html and javascript dynamically

I am trying get my javascaript pagination right on pure html table. Despite the number of records I get back my pagination keeps showing me
one button.

<ul>
     <li class="nav-item">
        <a class="nav-link" id="addtocatalog-tab" data-toggle="tab" href="#addtocatalog" role="tab" aria-controls="account-details" aria-selected="false">Add Catalog</a>
    </li>
    <li class="nav-item">
        <a class="nav-link" id="updateCatalog-tab" data-toggle="tab" href="#updateCatalog" onclick="InitiateTable()" role="tab" aria-controls="account-details" aria-selected="false">Update Catalog</a>
    </li>
 </ul>




function InitiateTable(id) {
         GetAllData();
      //})
 }




function GetAllData() {
     var orderData = [];
     const pageSize = 10;
     let curPage = 1;
     debugger
     $.ajax({
         url: "@Url.Action("GetallCat", "Home")",
         type: "Post",
     processData: false,
     contentType: false,
         success: function (result) {
             orderData = result.result;
             var tableData = "";
             console.log(result);
             console.log(orderData);
             orderData.filter((row, index) => {
                 let start = (curPage - 1) * pageSize;
                 let end = curPage * pageSize;
                 if (index >= start && index < end) return true;
             }).forEach(orderIndex => {
                 tableData += "<tr onClick ='getRow("+orderIndex.id +")'>";
                 tableData += `<td> ${parseFloat(orderIndex.id)} </td>`;
                 tableData += `<td> ${orderIndex.OEM}</td>`;
                 tableData += `<td> ${orderIndex.PCB} </td>`;
                 tableData += `<td> ${orderIndex.HFR} </td>`;
                 tableData += `<td> ${orderIndex.LUK}</td>`;
                 tableData += `<td> $${orderIndex.TractorModel}</td>`;
                 tableData += `<td> $${0}</td>`; "<tr>";
               /*  tableData += `<td> $${orderIndex.AvailableStock}</td>`;"<tr>";*/
                 //tableData += `<td> ${orderIndex.OEM}</td>`; "<tr>";
             });
             document.getElementById("data").innerHTML = tableData;

             var $table = document.getElementById("tblCatalogueUpdateList"),
                 // number of rows per page
                 $n = 10,
                 // number of rows of the table
                 $rowCount = $table.rows.length,
                 // get the first cell's tag name (in the first row)
                 $firstRow = $table.rows[0].firstElementChild.tagName,
                 // boolean var to check if table has a head row
                 $hasHead = ($firstRow === "TH"),
                 // an array to hold each row
                 $tr = [],
                 // loop counters, to start count from rows[1] (2nd row) if the first row has a head tag
                 $i, $ii, $j = ($hasHead) ? 1 : 0,
                 // holds the first row if it has a (<TH>) & nothing if (<TD>)
                 $th = ($hasHead ? $table.rows[(0)].outerHTML : "");
             // count the number of pages
             var $pageCount = Math.ceil($rowCount / $n);
             // if we had one page only, then we have nothing to do ..
             if ($pageCount > 1) {
                 // assign each row outHTML (tag name & innerHTML) to the array
                 for ($i = $j, $ii = 0; $i < $rowCount; $i++, $ii++)
                     $tr[$ii] = $table.rows[$i].outerHTML;
                 // create a div block to hold the buttons
                 $table.insertAdjacentHTML("afterend", "<div id='buttons'></div");
                 // the first sort, default page is the first one
                 sortDataRows(1, $th, $n, $tr, $table, $pageCount);
                 //function sortDataRows($p, $th, $n, $s)
             }
    

             // ($p) is the selected page number. it will be generated when a user clicks a button
             
         //}
       

     },
     error: function (er) {
         //code after Failure
     }

 });

 }



  function sortDataRows($p, $th, $n, $tr, $table, $pageCount) {
     /* create ($rows) a variable to hold the group of rows
     ** to be displayed on the selected page,
     ** ($s) the start point .. the first row in each page, Do The Math
     */
     var $rows = $th, $s = (($n * $p) - $n);
     for ($i = $s; $i < ($s + $n) && $i < $tr.length; $i++)
         $rows += $tr[$i];

     // now the table has a processed group of rows ..
     $table.innerHTML = $rows;
     // create the pagination buttons
     document.getElementById("buttons").innerHTML = pageButtons($p, $th, $n, $tr, $table,$pageCount);
     //sortDataRows(1, $th, $tn, $n, $s);
     // CSS Stuff
     document.getElementById("id" + $p).setAttribute("class", "active");
 }





 function pageButtons($pCount, $cur, $th, $tn, $n, $tr, $table, $pageCount) {
      /* this variables will disable the "Prev" button on 1st page
         and "next" button on the last one */
      var $prevDis = ($cur == 1) ? "disabled" : "",
          $nextDis = ($cur == $pCount) ? "disabled" : "",
          /* this ($buttons) will hold every single button needed
          ** it will creates each button and sets the onclick attribute
          ** to the "sort" function with a special ($p) number..
          */
          $buttons = "<input type='button' value='&lt;&lt; Prev' onclick='sortDataRows(" + ($cur - 1, $th, $n, $tr, $table, $pageCount) + ")' " + $prevDis + ">";
      for ($i = 1; $i <= $pCount; $i++)
          $buttons += "<input type='button' id='id" + $i + "'value='" + $i + "' onclick='sortDataRows(" +$i, $th, $n, $tr, $table, $pageCount + ")'>";
      $buttons += "<input type='button' value='Next &gt;&gt;' onclick='sortDataRows(" + ($cur + 1, $th, $n, $tr, $table, $pageCount) + ")' " + $nextDis + ">";
      return $buttons;
  }

How to dynamically make text’s color to be in contrast to its parent’s background color?

There are div having background color, containing text :

enter image description here

callAPI("/activites/prestationsFromGroupes", "POST", JSON.stringify(groupes)).then(prestationsGroupes => {
     let htmlPrestations = "";
     for(let i = 0 ; i < groupes.length ; i++) {
         let groupe = groupes[i];
         let prestations = prestationsGroupes[groupe['id']];
         let active = (i == onglet ? 'active' : '');
         htmlPrestations += '<div class="tab-pane min-h100 fade show '+active+'" id="pills-activites'+i+'" role="tabpanel" aria-labelledby="pills-activites'+i+'-tab">';
         htmlPrestations += '   <div class="group-menu-form">';
         for(let j = 0 ; j < prestations.length ; j++) {
             let prestation = prestations[j];
             let autoriseVae = prestation['autoriseVae'];
             if (autoriseVae == null) {
                 autoriseVae = 0;
             }
             let cuissonApplicable = prestation['cuissonApplicable'];
             if (cuissonApplicable == null) {
                 cuissonApplicable = 0;
             }
             let cdeCuisine = prestation['cdeCuisine'];
             if (cdeCuisine == null) {
                 cdeCuisine = 0;
             }
             let CSSbgcolor = prestation['couleur'] == "" ? "" : 'style="background-color: '+prestation['couleur']+';"';
             htmlPrestations += '   <a href="javascript:void(0);" data-id="'+prestation['id']+'" data-libelle="'+prestation['libelle']+'" data-prix="'+nvl(prestation['prix'], 0)+'" data-prix-emporter="'+nvl(prestation['prixEmporter'], 0)+'" data-tva="'+nvl(prestation['tva'], 0)+'" data-autorisevae="'+autoriseVae+'" data-cuissonapplicable="'+cuissonApplicable+'" data-cdeCuisine="'+cdeCuisine+'" title="'+prestation['libelle']+'">';
             htmlPrestations += '       <div class="menu-card" '+CSSbgcolor+'>';
             htmlPrestations += '           <div class="name-menu">'+prestation['libelle']+'</div>';
             htmlPrestations += '           <div class="group-menu">';
             htmlPrestations += '               <div class="price-menu">';
             htmlPrestations += '                   '+prestation['prix']+" &euro;";
             htmlPrestations += '               </div>';
             htmlPrestations += '           </div>';
             htmlPrestations += '       </div>';
             htmlPrestations += '   </a>';
         }
         htmlPrestations += '   </div>';
         htmlPrestations += '</div>';
     }
     $("#pills-tabContent").html(htmlPrestations);
     ...

The css of the text :

.menu-card .name-menu {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    max-width: 110px;
    font-weight: bold;
    color: #727272;
    font-size: 18px;
}
.menu-card .group-menu .price-menu {
    font-size: 30px;
    font-weight: bold;
    color: #4B4A4A;
    padding-left: 5px;
}

The problem is that sometimes when the div background color is dark then the text is not very clear. So how to dynamically make the text to be in contrast with the div’s background-color ?

Need to see the track changes and comments of word document in view.officeapps.live.com/

I have a scenario where I want to preview the MS Word document in the web browser. Yes, I am able to do that. However, the problem here is that I am not able to view the track changes or the comments inside the Word document.
Here, view.officeapps.live.com is used to preview the document as shown below.

https://view.officeapps.live.com/op/view.aspx?src=FILE_URL

example :

https://view.officeapps.live.com/op/view.aspx?src=https://calibre-ebook.com/downloads/demos/demo.docx

Can anyone tell me how to enable the ‘Track Changes’ / ‘Comments’ view, or if it is not possible, an alternative view would be appreciated.