Obtain reference to SignaturePad instance after creation

I have code that generates multiple signature pads on a page, giving them a unique ID along the way. I would like to be able to do individual signaturePad.toDataURL() calls as I process a button click, by looping through the canvas elements. I would also like to do single signaturePad.clear() functions as required.

I haven’t been able to figure out how to refer to the signature-pad instance that is attached to a given canvas element.

For clearing the signature, I’ve tried

$jq("body").on("click", ".signature-clear", function() {
 var canvas = document.getElementById($jq(this).closest('.canvas-wrap').find('canvas').attr('id'));
 var signaturePad = canvas.signaturePad();
});

But despite the canvas element being correctly targeted, I get the canvas.signaturePad is not a function error.

I’m sure it will be simple

Why does my nextToken work unless a filter is added to my graphql call?

Some context is needed for my question at the bottom of the post. There are two tables in the DynamoDB with the following schema.

type Post @model {
  id: ID!
  author: String!
  comments: [Comment] @hasMany
}

type Comment @model {
  id: ID!
  description: String!
  post: Post! @belongsTo
}

The Post table has 125 posts. The Comment table has 3000+ comments. Fetching all 125 Posts takes less than 5 seconds. Fetching all 3000+ comments with a limit of 1000 and paginating takes more than 10 seconds.

In each Post object, it contains a limit of 100 comments. Assuming each Post has 100+ comments, when we fetch all 125 posts, we have 1,250 of 3000+ comments within 5 seconds versus waiting greater than 10 seconds when we fetch all comments from the Comment table.

Code for fetching from Comment Table where it takes greater than 10 seconds.

    do {
      const result = await API.graphql(graphqlOperation(listComments, { limit: 1000, nextToken }));
      const tokens = result.data.listComments.items;
      allEvents.push(...tokens);
      nextToken = result.data.listComments.nextToken;
    } while (nextToken);

In order to speed up the time it takes for our app to get all the comments (the goal), I tried extracting all comment data from the Post objects since we get all Post objects much faster. The thinking was if we get 1250 comments from the Posts that quickly, we could just take the nextToken from the Post.comments.nextToken. (array of 100 comments is at Post.comments.items), and hit that same graphql function above. However when doing that, it returns the following pagination error.

 error in fetchAllCommentsAPI: {"data":{"listComments":null},"errors":[{"path":["listComments"],"data":null,"errorType":"IllegalArgument","errorInfo":null,"locations":[{"line":2,"column":3,"sourceName":null}],"message":"Invalid pagination token given."}]}

I thought it might be because we need to add a filter for the specific Post we are fetching for but that gave the same error.

Adding a filter to my nextToken graphql call causes an error:

const result = await API.graphql(graphqlOperation(listComments, { filter: { commentPostId: { eq: postId } }, nextToken })); // where commentPostId is the id of the Post.

I dont understand why I am getting that error, I would think the nextToken would take you to that filtered page.

Questions

  1. How can I use nextToken when fetching comments while filtering for a specific post?

  2. Is there a better way to get all comment data efficiently / is extracting is from Post objects bad practice?

Ensuring thin instanced meshes are always visible in Three.js

I am creating a heatmap with Three.js that has 19 rows and ~6,000 columns. Since there are so many columns, each cell is very thin. Out of the >110,000 cells in my current dataset, 47 are colored red, which are especially of interest. Most of these cells are visible, but there are 3 that are completely invisible until you zoom in or apply some animation that makes them larger (they disappear again when zooming out or return them to their original size).

The cells are generated using 3 instanced meshes,

const cellWidth = width / nCols;
const apparentCellWidth = cellWidth*1.01;
const cellHeight = height / nRows;

const cellGeometry = new THREE.PlaneGeometry(apparentCellWidth, cellHeight);

const redMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const greyMaterial = new THREE.MeshBasicMaterial({ color: 0xc7c8c9 });
const whiteMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });

let redMesh = new THREE.InstancedMesh(cellGeometry, redMaterial, redCount);
let greyMesh = new THREE.InstancedMesh(cellGeometry, greyMaterial, greyCount);
let whiteMesh = new THREE.InstancedMesh(cellGeometry, whiteMaterial, whiteCount);



const heatmapGroup = new THREE.Group();
heatmapGroup.add(redMesh);
heatmapGroup.add(greyMesh);
heatmapGroup.add(whiteMesh);

scene.add(heatmapGroup);

Is there a way to give the redMesh preferential treatment such that it will always be shown?

I have already tried the following to no avail

redMesh.renderOrder = 999;
redMesh.material.depthTest = false;
redMesh.material.depthWrite = false;
redMesh.onBeforeRender = function (renderer) { renderer.clearDepth(); };

Previously I had an issue where there were vertical gaps in between some columns. My solution to this was to calculate the positions of the cells using cellWidth, but to draw them with a width that is 1% wider apparentCellWidth. I suspect these issues could be related to one another.

fetch call render update lit webcomponent

I tried below to make fetch call and render data , I can see fetch call happening and data coming back in network tab , but never see dom updated.

import { html, unsafeCSS, nothing, css } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { AllEtfs } from './queries/all-etfs.js';
import { DsIvsApiBaseComponent } from '../ds-base/ds-base.api.js';
/**
 * @tag ds-etf-listing-table
 *
 */
@customElement('ds-etf-listing-table')
export class DsEtfListingTable extends DsIvsApiBaseComponent {
  static get styles() {
    return css`
          :host {
            display: inline-flex;
            align-items: center;
            background: blue;
          }
        `;
  }

  /**
   * @internal
   */
  query = AllEtfs.ALL_ETFS_QUERY;


  constructor() {
    super();
  }

  protected processResponse(_response): void {
    this.componentObject = _response.data;
    this.requestUpdate();
  }

  renderDataGrid() {
   if (this.componentObject?.allExchangeTradedFunds) {
      const allETFs = this.componentObject.allExchangeTradedFunds;
      return html`
        ${allETFs.forEach((etf) =>
          html`
            <div class="etf-listing">
              <div class="etf-listing__ticker">${etf.ticker}</div>
            </div>
          `,
        )}
      `;
    }

    return html``;
  }

  updated(changedProperties : Map<string, any>) {
    console.log('updated', changedProperties);
    console.log('componentObject', this.componentObject);
    super.updated(changedProperties);
  }

  render() {
    return this.renderComponent(html`
      <section class="content">
      <div>${this.renderDataGrid()}</div>
      </section>
    `);
  }
}


import { property, customElement } from 'lit/decorators.js';
import { DsBase } from './ds-base';

/**
 * Base class for components that fetch data from the IVS API.
 */
@customElement('ds-ivs-api-base-component')
export class DsIvsApiBaseComponent extends DsBase {

  private static readonly IVS_SERVICE_ENDPOINT = "https://api.dev.awstrp.net/investment-vehicle-svc/service/graphql";
  /**
   * The fragment used to fetch the data for the component.
   */
  @property({
    attribute: false,
  })
  protected query!: string;
  /**
   * The request query variables.
   */
  @property({ attribute: 'data-query-variables', type: String})
  protected variables?: string;



  constructor() {
    super();
  }

  connectedCallback() {
    super.connectedCallback();

    this.fetchData().then((response) => {
      console.log("IVS response" + response.data);
      this.processResponse(response);
    }).catch((error) => {
       console.error('Error fetching IVS data:', error);
    });
  }


  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  protected processResponse(_response) {
    // Component must override
    console.warn('processResponse must be overridden');
  }

  protected getQueryVariables(): Record<string, unknown> {
    try {
      return JSON.parse(this.variables || '{}');
    } catch (e) {
      console.warn('Invalid or No query variables', e);
      return {};
    }
 }

  protected getQuery(): string {
    return this.query;
  }

  /** write code to make a fetch request to the IVS API using the getApiUrl, getQuery, and getQueryVariables methods. **/
    protected async fetchData(): Promise<any> {
      const response = await fetch(DsIvsApiBaseComponent.IVS_SERVICE_ENDPOINT, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-TRP-Requested-With': 'XMLHttpRequest',
          'apikey': 'pJex4NUuoEVkZ6ohvw5nR8Yfa27vcXI2'
        },
        body: JSON.stringify({
          query: this.getQuery(),
          variables: this.getQueryVariables(),
        }),
      });
      return response.json();
    }



}


import { LitElement, html, unsafeCSS } from 'lit';
import { property, customElement, state } from 'lit/decorators.js';
import { ComponentLoaderMixin } from '@trp-dms-digital-shared/ds-ui-library-components/src/lib/component-loader/component-loader.js';
import { DigitalSharedAnalytics } from '@trp-dms-digital-shared/ds-ui-library-common/src/utils/analytics/analytics.js';
import mixin from '@trp-dms-digital-shared/ds-ui-library-common/src/lib/mixin.js';

import { Constants } from './ds-base.constants';

type TTrackingHTMLElement = HTMLElement &
  Record<string, (originalEvent: Event) => void>;

/**
 * Base class for components that includes Beacon
 * @tag ds-base
 */
@customElement(Constants.TAG_NAME)
export class DsBase extends mixin(LitElement, ComponentLoaderMixin) {
  /**
   * @internal
   */
  static styles = [unsafeCSS(`/// styles imported via <link>n`)];

  /**
   * @internal
   */
  @state()
  tagName = '';

  /**
   * The current version of the pop component, used for version specific scoping
   * @internal
   */
  @property({ attribute: Constants.DS_VERSION, reflect: true })
  version = Constants.VERSION;

  /**
   * The current version of the pop component, used for version specific scoping
   * @internal
   */
  @property({ attribute: Constants.DS_VERSION, reflect: true })
  stylesheetUrl = Constants.VERSION;

  @property({
    type: Object,
    attribute: false,
  })
  componentObject?: unknown;

  constructor() {
    super();
  }

  connectedCallback() {
    super.connectedCallback();
    DigitalSharedAnalytics.unsetHostEventHandlerForAnalytics(
      this as unknown as TTrackingHTMLElement,
    );

    DigitalSharedAnalytics.setHostEventHandlerForAnalytics(
      this as unknown as TTrackingHTMLElement,
      Constants.DS_VERSION,
      this.version,
    );
  }

  /**
   * If the component is disconnected from the DOM, remove the analytics event listeners.
   */
  disconnectedCallback() {
    DigitalSharedAnalytics.unsetHostEventHandlerForAnalytics(
      this as unknown as TTrackingHTMLElement,
    );
    super.disconnectedCallback();
  }

  /*
   * This method is called from the Component Loader Mixin once any Defer conditions are met.
   * No need to override this method when extending the Base Component.
   * Wrapper to be used inside of the `render()` method
   * @example
   * render() {
   *  return this.renderComponent(html`<p>meow</p>`)
   * }
   */
  protected renderComponent(
    content: unknown,
    classes = 'beacon-theme-modern-outlook',
  ) {
    return !this.initialized
      ? html`<!--- Not Initialized --->`
      : html`
          <div data-base-container class="b-reset ${classes}">${content}</div>
        `;
  }

  render() {
    return this.renderComponent(html`<!--- Base Render Content --->`);
  }
}

As you can see, I have ds-base.ts, ds-base.api.ts and , etf-listing-table.ts . I have fetch call inside connectedCallBack and processResponse method setting componentObject.

What I don’t see , rederDataGrid html not appearing on the page, even though when I debug , I see all the code getting called.

Why does my chartData output [Object], [Object] instead of { label: ‘Lukáš’, value: 8 } in JavaScript?

I’m working on a JavaScript project where I generate a list of employees and their respective work hours. I want to create a chart data object with the names and values of employees, but when I log the chartData, it outputs something like this:

chartData: {
  all: [
    [Object], [Object],
    [Object], [Object],
    [Object], [Object],
    [Object], [Object],
    [Object], [Object]
  ]
}

Instead of the expected output, which should look like this:

chartData: {
  all: [
    { label: 'Lukáš', value: 8 },
    { label: 'Eva', value: 8 },
    { label: 'Tomáš', value: 7 },
    { label: 'Anna', value: 6 },
    { label: 'Lucie', value: 5 },
    { label: 'Jan', value: 4 },
    { label: 'Petr', value: 4 },
    { label: 'Tereza', value: 3 },
    { label: 'Michal', value: 3 },
    { label: 'Jana', value: 2 }
  ]
}

I checked the nameCounter function, and it seems to be counting the names correctly.

I used Object.entries and .map to convert the counts to the required format.

I logged the result, but the output is still in the [Object], [Object] format, which makes me think that the issue might be with how I’m logging the result or how the data is being returned.

heres my code:

// Array of male names
const maleNames = [
    "Peter", "John", "Michael", "Luke", "Thomas"]
// Array of female names
const femaleNames = [
    "Anna", "Jane", "Eva", "Lucy", "Teresa"]
// Array of male last names
const maleLastname = [
    "Smith", "Johnson", "Brown", "Taylor", "Anderson"]
// Array of female last names
const femaleLastname = [
    "Smith", "Johnson", "Brown", "Taylor", "Anderson"
]

/**
 * Main function to generate a list of employees based on input parameters.
 * @param {object} dtoIn - Input object with parameters.
 * @param {number} dtoIn.count - The number of employees to generate.
 * @param {object} dtoIn.age - The age range of the employees.
 * @param {number} dtoIn.age.min - Minimum age of employees.
 * @param {number} dtoIn.age.max - Maximum age of employees.
 * @returns {Array<object>} - An array of objects representing the employees.
 */
function generateEmployeeData(dtoIn) {
    const dtoOut = [];
    for (let i = 0; i < dtoIn.count; i++) {
        let gender = getGender();  // Randomly select gender
        let employee = {
            gender: gender,
            birthdate: getBirthdate(dtoIn.age.min, dtoIn.age.max),
            name: getName(gender, maleNames, femaleNames),  // Get the name based on gender
            surname: getName(gender, maleLastname, femaleLastname),  // Get the surname based on gender
            workload: getWorkload()  // Randomly select workload
        }
        dtoOut.push(employee);
    }

    // Sort employees by their workload in ascending order
    return dtoOut.sort((a, b) => a.workload - b.workload);
}

/**
 * Randomly generates a number within the given range.
 * @param {number} min - The minimum value.
 * @param {number} max - The maximum value.
 * @returns {number} - A random number between min and max (inclusive).
 */
function getRandom(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

/**
 * Randomly determines the gender.
 * @returns {string} - "male" or "female".
 */
function getGender() {
    return getRandom(0, 1) === 0 ? 'male' : 'female';
}

/**
 * Generates a random birthdate based on the given age range.
 * @param {number} ageMin - Minimum age.
 * @param {number} ageMax - Maximum age.
 * @returns {string} - Birthdate in ISO 8601 format.
 */
function getBirthdate(ageMin, ageMax) {
    const currentDay = new Date().getTime();
    const yearInMil = 365.25 * 24 * 60 * 60 * 1000;

    const minRange = currentDay - (new Date(ageMax * yearInMil));
    const maxRange = currentDay - (new Date(ageMin * yearInMil));
    const birthDate = getRandom(minRange, maxRange);

    return new Date(birthDate).toISOString();
}

/**
 * Returns a random name based on gender.
 * @param {string} gender - Gender ("male" or "female").
 * @param {Array<string>} male - Array of male names.
 * @param {Array<string>} female - Array of female names.
 * @returns {string} - A random name corresponding to the gender.
 */
function getName(gender, male, female) {
    return gender === 'male' ? male[getRandom(0, male.length - 1)] : female[getRandom(0, female.length - 1)];
}

/**
 * Generates a random workload (work hours) from a list of possible values.
 * @returns {number} - Random workload (e.g., 10, 20, 30, 40).
 */
function getWorkload() {
    const workloads = [10, 20, 30, 40];
    const index = getRandom(0, workloads.length - 1);
    return workloads[index];
}

/**
 * Extracts all names from a list of employees.
 * @param {Array<object>} list - List of employees.
 * @returns {Array<string>} - Array of employee names.
 */
function getAllNames(list) {
    return list.map(e => e.name);
}

/**
 * Filters the list by gender and returns only employees of the specified gender.
 * @param {Array<object>} list - List of employees.
 * @param {string} gender - The gender to filter by ("male" or "female").
 * @returns {Array<object>} - Filtered list of employees by gender.
 */
function getNameByGender(list, gender) {
    return list.filter(e => e.gender === `${gender}`);
}

/**
 * Filters the list by gender and workload (full-time or part-time).
 * @param {Array<object>} list - List of employees.
 * @param {number} [workload] - If provided, filters by a specific workload.
 * @returns {Array<string>} - List of names that match the criteria.
 */
function genderWorkload(list, workload) {
    if (workload === undefined) {
        let femaleList = getNameByGender(list, "female");
        femaleList = femaleList.filter(e => e.workload !== 40);  // Part-time female employees
        return getAllNames(femaleList);
    }
    else {
        let maleList = getNameByGender(list, "male");
        maleList = maleList.filter(e => e.workload === 40);  // Full-time male employees
        return getAllNames(maleList);
    }
}

/**
 * Counts the occurrences of names in a list.
 * @param {Array<string>} list - List of names.
 * @returns {object} - An object with the name counts.
 */
function nameCounter(list) {
    return list.reduce((acc, name) => {
        acc[name] = (acc[name] || 0) + 1;
        return acc;
    }, {});
}

/**
 * Converts the name counts into the required format { label, value } and sorts by value.
 * @param {Array<string>} list - List of names.
 * @returns {Array<object>} - Array of objects with the format { label: name, value: count }.
 */
function charOutput(list) {
    const countedNames = nameCounter(list);
    return Object.entries(countedNames).map(([label, value]) => ({
        label: label,
        value: value
    })).sort((a, b) => b.value - a.value);  // Sort by value descending
}

/**
 * Creates chart data with name counts for all employees, male, and female.
 * @param {Array<object>} list - List of employees.
 * @returns {object} - Object containing chart data for all employees, male and female.
 */
function getEmployeeChartContent(list) {
    const dtoOut = {
        names: {
            all: nameCounter(getAllNames(list)),  // Dynamic creation for 'all'
            male: nameCounter(getAllNames(getNameByGender(list, "male"))),
            female: nameCounter(getAllNames(getNameByGender(list, "female"))),
            femalePartTime: nameCounter(genderWorkload(list)),
            maleFullTime: nameCounter(genderWorkload(list, 40)),
        },
        chartData: {
            all: charOutput(getAllNames(list)),
            male: charOutput(getAllNames(getNameByGender(list, "male"))),
        }
    };
    return dtoOut;
}

/**
 * The main function to generate employee data and chart content.
 * @param {object} dtoIn - Input parameters.
 * @returns {void}
 */
function main(dtoIn) {
    let data = generateEmployeeData(dtoIn);
    const dtoOut = getEmployeeChartContent(data);
}

// Example input data for employee generation
const dtoIn = {
    count: 50,
    age: {
        min: 19,
        max: 35
    }
}

// Generate employee data and display the chart content
let data = generateEmployeeData(dtoIn);
console.log(getEmployeeChartContent(data));

// Output the name count in the required chart format
console.log(charOutput(getAllNames(data)));

Having trouble with centering a div in my Vue project with CSS

My code for some reason doesn’t center containers/text properly but instead centers them vertically, but not horizontally.

Instead of horizontally centered text will take up space on the left of the center (image attached)

Would appreciate any help and if I am making some dumb mistake please do let me know

the problem

Here is the code attached
(Dashboard)

<!-- src/views/Dashboard.vue -->

<script setup>
import Navbar from '@/components/TheNavbar.vue';
</script>

<template>
  <div>
    <Navbar />
    <div class="container">
      <div class="title">Welcome to the Dashboard!</div>
    </div>
  </div>
</template>

<style scoped>

.title {
  font-size: 40px;
  font-weight: 600;
}

.container {
  display: flex;
  justify-content: center;
  align-items: center;
}

</style>

(index.js for router)

import { createRouter, createWebHistory } from 'vue-router'
import LandingPage from '../views/LandingPage.vue'
import LoginSignup from '../views/LoginSignup.vue'
import DashboardPage from '../views/DashboardPage.vue'
import BudgetPage from '../views/BudgetPage.vue'
import AnalyticsPage from '../views/AnalyticsPage.vue'
import AccountPage from '../views/AccountPage.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'Landing',
      component: LandingPage,
    },

    {
      path: '/loginsignup',
      name: 'LoginSignup',
      component: LoginSignup,
    },

    {
      path: '/dashboard',
      name: 'Dashboard',
      component: DashboardPage,
    },

    {
      path: '/budget',
      name: 'Budget',
      component: BudgetPage,
    },

    {
      path: '/analytics',
      name: 'Analytics',
      component: AnalyticsPage,
    },

    {
      path: '/account',
      name: 'Account',
      component: AccountPage,
    }
  ],
})

export default router

(App.vue)

<!-- src/App.vue -->

<script setup>
import { RouterLink, RouterView } from 'vue-router'
</script>

<template>
  <main>
      <RouterView />
  </main>
</template>


<style scoped>



</style>

(main.js)

import './assets/main.css'

import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'

const app = createApp(App)

app.use(createPinia())
app.use(router)

app.mount('#app')

(index.html)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>EZ Budget</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@iconscout/[email protected]/css/line.css">
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
  </body>
</html>

(main.css)

@import './base.css';

#app {
  max-width: 1280px;
  margin: 0 auto;
  padding: 2rem;
  font-weight: normal;
}

a,
.green {
  text-decoration: none;
  color: hsla(160, 100%, 37%, 1);
  transition: 0.4s;
  padding: 3px;
}

@media (hover: hover) {
  a:hover {
    background-color: hsla(160, 100%, 37%, 0.2);
  }
}

@media (min-width: 1024px) {
  body {
    display: flex;
    place-items: center;
  }

  #app {
    display: grid;
    grid-template-columns: 1fr 1fr;
    padding: 0 2rem;
  }
}

Here is what my project structure looks like

files

Thanks in advance for any help 🙂

Qualtrics custom JS Custom works in question preview but not actual survey

I believe this is a somewhat common issue however I was unable to find a solution. I made a freeform drag-and-drop question on Qualtrics using the custom JS, which works just fine when I preview the question but does not work if I preview the block, preview the block, or take the survey. The JS portion of the code and some log statements are below, and I would appreciate it if anyone has any insight on how I could make it work!

Qualtrics.SurveyEngine.addOnload(function () {
    const draggableIcons = document.querySelectorAll('#breakfast, #dinner');


        draggableIcons.forEach(icon => {
            let isDragging = false;
            let offsetX, offsetY;

            icon.style.position = 'absolute';
            icon.style.zIndex = '1000';

            // Start dragging
            icon.addEventListener("mousedown", (event) => {
                isDragging = true;
                offsetX = event.clientX - icon.getBoundingClientRect().left;
                offsetY = event.clientY - icon.getBoundingClientRect().top;
                icon.style.cursor = "grabbing";  // Change cursor on drag
                event.preventDefault();

                document.addEventListener("mousemove", onMouseMove);
                document.addEventListener("mouseup", onMouseUp);
            });

            // Handle dragging
            function onMouseMove(event) {
                if (isDragging) {
                    icon.style.left = `${event.clientX - offsetX}px`;
                    icon.style.top = `${event.clientY - offsetY}px`;
                }
            }

            // Stop dragging and reset cursor
            function onMouseUp() {
                isDragging = false;
                icon.style.cursor = "grab";  // Reset cursor
                document.removeEventListener("mousemove", onMouseMove);
                document.removeEventListener("mouseup", onMouseUp);
            }
        });

});

I tried out some console.log statements, and when I am on ‘question preview’ I get the correct logs (e.g., “breakfast is being dragged to: (248.333px, 244.333px), Stop dragging breakfast at final position: (248.333px, 244.333px)”). So I can both drag, and see that the items are being loaded/the correct names and positions are being logged. When I am taking the survey or using ‘preview block’, the logs are suggesting that the items and the coordinates aren’t loading (e.g., “ is being dragged to: (, ), Stop dragging at final position: (, )”). Using addOnload or addOnready didn’t make a difference and I cannot seem to figure out what is causing the issue here!

I tried to create a freeform drag and drop question, I was expecting it to work as it does when I preview the question, but it stops working during the actual survey.

Javascript class to sort HTML tables. Unsort method not working [closed]

My class sorts a table alphabetically by the name of the name of the employees and also by the time worked. The problem that I have is that I can make it to “unsort” the table (sort it to the original state) after clicking the name or worked time headings. I thought it would be simple but no I can’t figure it out.

Sorry if it is bad code. I am learning and I basically wrote the class without knowing too much JS.

Thank you!

export { SortingTable };

class SortingTable {
    #data = null;
    #sortedData = null;
    #sortedTimeData = null;
    #originalData = null;

    constructor(table, selector) {
        this.table = table;
        this.selector = selector;
    }


    #getBodyData() {
        const body = this.table;
        const rows = body.getElementsByTagName('tr');
        const data = [];
        const originalData = [];
        
        for (let i = 0; i < rows.length; i++) {
            data.push(rows[i]); // Push the actual row
            originalData.push(rows[i].cloneNode(true)); // Push a deep copy of the row
        }
        
        this.data = data;
        this.originalData = originalData;
    }
    

    #removeBody(){
        const body = this.table.getElementsByTagName('tbody')[0]
        while (body.childElementCount){
            body.removeChild(body.firstElementChild)
        }
    }

    #sortAlphaData() {
        this.data.sort((a, b) => {
            const elementA = a.querySelector(this.selector);
            const elementB = b.querySelector(this.selector);
    
            const nameA = elementA ? elementA.innerText : '';
            const nameB = elementB ? elementB.innerText : '';
    
            return nameA.localeCompare(nameB);
        });
        this.sortedData = this.data;
    }
    
    #sortTimeData(){
        const data = this.data
        const seconds = []
        const newData = []
        for (let i = 0; i < data.length; i++){
            let wholeTime = data[i].querySelector('#workedTime')?.innerText ?? '';
            // console.log(wholeTime)
            const splitTime = wholeTime.split(':')
            const totalSeconds = (parseFloat(splitTime[0]) * 3600) + 
                           (parseFloat(splitTime[1]) * 60) + 
                           (parseFloat(splitTime[2]))
            seconds.push(totalSeconds)
            const objectData = {
                totalSeconds: totalSeconds,
                originalData: data[i]
            }
            newData.push(objectData)
        }
        newData.sort((a, b) => a.totalSeconds - b.totalSeconds)
        this.sortedTimeData = newData
    }

    #rebuildAlphaBody() {
        const body = this.table.getElementsByTagName('tbody')[0];
        const data = this.sortedData;
    
        // Append the sorted rows directly to the body
        for (let i = 0; i < data.length; i++) {
            body.appendChild(data[i]); // Reuse the original row elements
        }
    }
    
    #rebuildOriginalBody() {
        const body = this.table.getElementsByTagName('tbody')[0];
        const data = this.originalData;
    
        // Append the sorted rows directly to the body
        for (let i = 0; i < data.length; i++) {
            body.appendChild(data[i]); // Reuse the original row elements
        }
    }

    #rebuildTimeBody(){
        const data = this.sortedTimeData
        const body = this.table.getElementsByTagName('tbody')[0]
        for (let i = 0; i < data.length; i++){
            body.appendChild(data[i]['originalData'])
        }
    }

    sortAlpha(){
        this.#getBodyData()
        this.#sortAlphaData()
        this.#removeBody()
        this.#rebuildAlphaBody()
    }

    sortTime(){
        this.#getBodyData()
        this.#sortTimeData()
        this.#removeBody()
        this.#rebuildTimeBody()
    }

unsort() {
    console.log("Original Data:", this.originalData);

    if (!this.originalData) {
        console.error("Error: originalData is not initialized. Call a sorting method first.");
        return;
    }

    this.#removeBody();
    this.#rebuildOriginalBody();
    }  
}

I tried to create a deep copy of the original data so when the this.data was sorted it wouldn’t affect the original data but this console.log(“Original Data:”, this.originalData); is prints undefined.

I am not sure what to do after this.

Thank you

Using glob with the aspect-build bazel-examples repository typescript build?

I’m trying to figure out how to build typescript with Bazel and I cloned this repository:

git clone https://github.com/aspect-build/bazel-examples

And ran the ts_project_transpiler example.

cd ts_project_transpiler
bazel build //...

And this works. And I want to use a glob pattern so that I can have a directory with more typescript files in it, and it looks like Bazel has functions for this.

So I tried.

ts_project(
    name = "tsc",
    #srcs = ["big.ts"],
    srcs = glob(["*.ts"]),
    declaration = True,
    declaration_dir = "build-tsc",
    out_dir = "build-tsc",
    source_map = True,
)

However this errors out.

ERROR: /Temp/bazel-examples/ts_project_transpiler/BUILD.bazel:25:11: in ts_project_rule rule //:tsc: 
Traceback (most recent call last):
        File "/private/var/tmp/_bazel_oleersoy/e1e034f754cf70db5f987ffb5af7aef0/external/aspect_rules_ts/ts/private/ts_project.bzl", line 186, column 13, in _ts_project_impl
                fail(no_outs_msg + """
Error in fail: ts_project target //:tsc is configured to produce no outputs.

This might be because
- you configured it with `noEmit`
- the `srcs` are empty
- `srcs` has elements producing non-ts outputs

This is an error because Bazel does not run actions unless their outputs are needed for the requested targets to build.
ERROR: /Users/oleersoy/Temp/bazel-examples/ts_project_transpiler/BUILD.bazel:25:11: Analysis of target '//:tsc' failed
WARNING: errors encountered while analyzing target '//:tsc': it will not be built
WARNING: errors encountered while analyzing target '//:tsc_test_0__deps': it will not be built
WARNING: errors encountered while analyzing target '//:tsc_test': it will not be built
INFO: Analysis succeeded for only 43 of 46 top-level targets
INFO: Analyzed 46 targets (0 packages loaded, 0 targets configured).
INFO: Found 43 targets...
ERROR: /Users/oleersoy/Temp/bazel-examples/ts_project_transpiler/BUILD.bazel:86:15: Executing genrule //:tsc_test_1__deps failed: missing input file '//:build-tsc/big.js'
ERROR: /Users/oleersoy/Temp/bazel-examples/ts_project_transpiler/BUILD.bazel:86:15: Executing genrule //:tsc_test_2__deps failed: missing input file '//:build-tsc/big.js.map'
ERROR: /Users/oleersoy/Temp/bazel-examples/ts_project_transpiler/BUILD.bazel:86:15: Executing genrule //:tsc_test_3__deps failed: missing input file '//:build-tsc/big.d.ts'
ERROR: /Users/oleersoy/Temp/bazel-examples/ts_project_transpiler/BUILD.bazel:86:15: Executing genrule //:tsc_test_3__deps failed: 1 input file(s) do not exist
ERROR: /Users/oleersoy/Temp/bazel-examples/ts_project_transpiler/BUILD.bazel:86:15: Executing genrule //:tsc_test_1__deps failed: 1 input file(s) do not exist
ERROR: /Users/oleersoy/Temp/bazel-examples/ts_project_transpiler/BUILD.bazel:86:15: Executing genrule //:tsc_test_2__deps failed: 1 input file(s) do not exist
INFO: Elapsed time: 0.123s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
FAILED: Build did NOT complete successfully

Any ideas?

Why is my tumblr-hosted website showing me a broken layout on Firefox? [closed]

I have a Tumblr Blog that has a custom layout made up of HTML, CSS, and JS. It’s displaying properly on Chrome and Safari web browsers on both PC and mobile, but as soon as I open the same page on Firefox (and Firefox Developer Edition) it magnifies everything on the page to the point that it’s not easily viewable anymore.

I thought the problem was needing a "word-wrap: break-word;" addition in an element to target the specific text post that’s causing the issue, but that doesn’t seem to fix it. Any other debugging I’ve tried so far was in completely removing all the included Javascript to see if anything related to the added scripts was causing this underlying effect to take place in Firefox alone, but to no avail. I also tried targeting and removing + later modifying the @-moz-document url-prefix() {} element since it directly ties the containers to display changes in Firefox, but any changes to the height and width of the container through that element or edits to how text should work didn’t render any fixes.

Any help in narrowing the problem down to target and fix whatever is causing its entire layout to break, so that it displays properly again on Firefox, would be greatly appreciated!

The website | The code

How to display, edit, and save a date in DD / MMM / YYYY format in Laravel?

I am working on a Laravel project where I need to add a date field in the user profile section(a form). The date should:

  • Be displayed in the format DD / MMM / YYYY (e.g., 25 / Jun / 2024).
  • Allow users to edit/select the date.
  • Send the date to the backend in a regular YYYY-MM-DD format when the form is submitted.
  • Fetch the saved date from the backend and display it in the same DD / MMM / YYYY format when the page is visited.

I tried using <input type="date">, but it displays the date as 25/06/2025, which isn’t the desired format. I also tried following approach:

`
{!! Form::select(‘day’, range(1, 31), null, [‘placeholder’ => ‘Day’, ‘class’ => ‘form-control’]) !!}
{!! Form::select(‘month’, [’01’ => ‘Jan’, ’02’ => ‘Feb’, ’03’ => ‘Mar’, …, ’12’ => ‘Dec’], null, [‘placeholder’ => ‘Month’, ‘class’ => ‘form-control’]) !!}
{!! Form::select(‘year’, range(date(‘Y’), 1900), null, [‘placeholder’ => ‘Year’, ‘class’ => ‘form-control’]) !!}

`

The JavaScript code for aligning the number of days with the selected month and year, feels overly complex for such a simple requirement.

**Is there an easier way to:
**
Display the date in DD / MMM / YYYY format.
Allow users to edit/select the date.
Fetch and display the saved date(dd-mm-yyyy) in the correct format(dd-mmm-yyyy or 16-05-2025) when the page is visited.

Data to be displayed on webapp based on condition selected from the input from google sheets

I have make a webapp for data capturing. If they select a option on webapp then one data value to be auto displayed on webapp from google sheets. I tried with some codes but not succeeds. Example if i select A or B or C or D then a value will insert inside the plan box which data stored in google sheets. Please suggest.

 .heading {
    margin-top: 20px;
    margin-bottom: 10px;
    text-align:center;
    color: black;
    font-size: 60%;
    height: 85px;
  }
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <base target="_top">
  </head>
  <body>
      <div class="heading">
        <h1><b>Data Monitoring</b></h1>
      </div>
  

      <div class="catg">
        <select id="Category">
        <option>A</option>
        <option>B</option>
        <option>C</option>
        <option>D</option>   
        </select>
      </div>


        <div class="mplan">
        <input id="mdata" type="number" value="0" min="0" oninput="validity.valid||(value='');">
        <label>Data Plan</label>
           
        </div>    
 
     <div class="actual">
        <input id="act" type="number">
        <label for="act">actual : </label>
      </div>

     <div class="sub">
        <button id="btn" type="submit" name="action">Submit
        </button>
     </div>
   
      
  </body>
</html>

Ajax calls loop delay or limit [duplicate]

I have a small Ajax function on my site, which makes the same thing for all list elements which are loaded. My problem is, that the list sometimes has 100+ elements and if it makes the Ajax calls I get ERROR 503, so it’s overloading the server. I just want that let’s say 5 calls are fired parallel or at least make some delay between the calls… I’m not a JS expert, I tried with this after Googling but it’s not right, I got “Unexpected identifier: sleep” error…

async function sleep(ms) { 
    return new Promise(resolve => setTimeout(resolve, ms)); 
}

function genContentSecondStep(){
    var list = document.getElementById("mylist").value;
    
    var splitList = list.split(";");
    for(var element of splitList){
        var trimStr = element.trim();
        if(trimStr != ""){
            callApi('gen-content', trimStr);
            await sleep(1000);
        }
    }
}

function callApi(input, element = null) {
    var prm = "";
    var content = document.getElementById("generatedContent").value;

    if (prm.length == 0 && input == 'generate-list') { 
        document.getElementById("generatedContent").innerHTML = "";
        return;
    } else {
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                document.getElementById("generatedContent").innerHTML += this.responseText;
            }
        };

        xmlhttp.open("GET", "api-call.php?func=" + input + "&prm=" + element + "&content=" + content, true);
        
        xmlhttp.send();
    }
}

How to make this? Is it even possible? Thanks.

EDIT.: the api-call.php is working fine and if I limit the list to a few elements or I execute the previous faulty ones after a while it’s also okay, so the amount of Ajax calls is sadly the problem for the server.

EDIT2.: “thanks” for the duplicate, but it’s not even sure, that the await solves the problem, that was ONE of my first ideas only

How to efficiently integrate Blockly for drag-and-drop coding blocks into a React application?

I’m working on a project to integrate Blockly into a React application. The goal is to create an interactive drag-and-drop programming environment to help beginners visualize algorithms and understand programming concepts.

Goals:

  1. Embed a Blockly workspace in a React component.
  2. Dynamically load and save blocks from/to JSON.
  3. Customize the toolbox for algorithm-related blocks.
  4. Ensure smooth performance as the number of blocks grows.

What I’ve Tried:

  • Used @blockly/react for basic embedding.
  • Defined blocks using JSON but faced issues with dynamically reloading them.
  • Customized the toolbox, but UI responsiveness drops with larger datasets.

Questions:

  • What are the best practices for integrating Blockly with React to ensure performance and scalability?
  • How can I dynamically update the workspace without unnecessary re-renders?
  • Are there libraries or patterns for saving/loading blocks efficiently in a React app?

Any guidance, resources, or code examples would be greatly appreciated!