Need to move Variation Description from original location to woocommerce_single_product_summary location in woodmart theme

I want move Variable Product Description from original location to woocommerce_single_product_summary location but I never success still using many methods i got code from the web

add_action( 'woocommerce_single_product_summary', 'variable_product_description_on_selection' );
function variable_product_description_on_selection() {

    global $product;
    
    if ( ! $product->is_type( 'variable' ) ) return;
    
    echo '<div class="variation-description"></div>';
    
    wc_enqueue_js( "
      $(document).on('found_variation', 'form.cart', function( event, variation ) { 
         $('.variation-description').html(variation.variation_description); 
      });

" );

}

but its making copy.
please help me to move variation description woocommerce_single_product_summary

need to move location variation description.

Fedex API – SATURDAY_DELIVERY

Im having some trouble getting my SATURDAY_DELIVERY tag to work.

I can get the Saturday delivery from the rates and quotes api, so I know the addresses I’m using allow Saturday delivery.

Any help will be greatly appreciated.

I keep getting the following error:

[{"code":"ORGORDEST.SPECIALSERVICES.NOTALLOWED","message":"This special service type is not allowed for the origin/destination pair. Please update and try again","parameterList":[{"key":"SPECIAL_SERVICE_TYPE","value":"SATURDAY_DELIVERY"}]}

I’m wondering if someone else has come across this – Am I doing something wrong here? Iv tried mutiple different payloads with different addresses, iv tried sandbox API, Prod API, tried real addresses, different pickupType, different packagingTypes etc..

Here’s my sample payload

$payload = [
    "accountNumber" => [
        "value" => "*******"
    ],
    "labelResponseOptions" => "URL_ONLY",
    "requestedShipment" => [
        "shipDateStamp" => "2025-06-13", // Friday
        "pickupType" => "DROPOFF_AT_FEDEX_LOCATION",
        "serviceType" => "PRIORITY_OVERNIGHT",
        "packagingType" => "FEDEX_BOX", // Required for SATURDAY_DELIVERY in many areas

        "shipper" => [
            "contact" => [
                "personName" => "John Doe",
                "phoneNumber" => "5555555555",
                "companyName" => "Test Sender Inc"
            ],
            "address" => [
                "streetLines" => ["123 Main Street"],
                "city" => "Memphis",
                "stateOrProvinceCode" => "TN",
                "postalCode" => "38116",
                "countryCode" => "US"
            ]
        ],

        "recipients" => [[
            "contact" => [
                "personName" => "Jane Smith",
                "phoneNumber" => "5555551234",
                "companyName" => "Test Receiver LLC"
            ],
            "address" => [
                "streetLines" => ["100 California Street"],
                "city" => "San Francisco",
                "stateOrProvinceCode" => "CA",
                "postalCode" => "94111",
                "countryCode" => "US",
                "residential" => true
            ]
        ]],

        "shippingChargesPayment" => [
            "paymentType" => "SENDER",
            "payor" => [
                "responsibleParty" => [
                    "accountNumber" => [
                        "value" => "*******"
                    ]
                ]
            ]
        ],

        "requestedPackageLineItems" => [[
            "weight" => [
                "units" => "LB",
                "value" => 2
            ]
        ]],

        "shipmentSpecialServices" => [
            "specialServiceTypes" => ["SATURDAY_DELIVERY"]
        ],

        "labelSpecification" => [
            "labelStockType" => "PAPER_4X6",
            "imageType" => "PDF"
        ]
    ]
];

Sending Laravel form with dynamically added fields with AJAX, Undefined parameters

I have a form in Laravel where I use Ajax to dynamically create options in the selects, based on previous filled information. I am very new to Ajax, so maybe I understand the concept wrong.

Below the first select, just based on a “regular” query.

<select id="selectCompany" name="companyId">
  @foreach($companies as $company)
     <option value="{{ $company->id }}">{{ $company->name }}</option>
  @endforeach
</select>

Based on the first selected value, I use Ajax to select options for the next selection field.

$(document).ready(function () {
  $('#step1').on('click', function (fetchLocations) {
    $.ajax({
      type: 'GET',
      url: '/get/info/',
      dataType: 'json',
      data: {
        companyId: $('#selectCompany option:selected').val()
      },
      success: function (response) {
        $('#selectLocations').empty();
        $.each(response.locations, function (key, value) {
          $('#selectLocations').append('<option value=' + key.id + '>' + value.title + '</option>');
        });
      },
      error: function (ts) {
        alert(ts.responseText);
      }
    });
  });

I add the options to the following select

<select id="selectLocations" name="locationId">
</select>

Now I want to submit the form via normal Laravel route, unfortunately the value send from the second select is “Undefined”. How can I fix this?

Laravel Request parameters:

Laravel Request parameters

emonkey integration returning NaN despite nearly identical code

I am currently working on formatting dates to some desired formats, and I am using Emonkey to do this using their integrations and some Javascript.

I’ve made two integrations called “Integration Tools” and “DateToTextDDMMYYYY” that convert dates from the internal Date format that Emonkey provides to strings formatted as DDMMYYYY and YYYYMMDD. “Integration Tools” correctly formats the Date to a string in the YYYYMMDD format, but the “DateToTextDDMMYYYY” integration returns NaNNaNNaN (NaN is short for Not a number).

The only difference between these integrations is the Javascript functions that they use. The only difference between the Javascript functions is that they concatenate the day, month and year variables in a different order, everything else is exactly the same.

function DateConverter1(date) {

  // control flow
  let newDate = new Date(date);

  if (!newDate) {
    throw new Error("the string date is not a formatted date string");
    return;
  }

  let year = newDate.getFullYear().toString();

  // inkrementerer med 1 siden funksjonen defaulter til 0 for januar og søndag
  let month = (newDate.getMonth() + 1).toString();

  if (Number(month) < 10) {
    month = '0' + month;
  }

  let day = (newDate.getDay() + 1).toString();

  if (Number(day) < 10) {
    day = '0' + day;
  }


  let formattedDate = year + month + day;
  return formattedDate;
}

function DateConverter2(date) {

  // control flow
  let newDate = new Date(date);

  if (!newDate) {
    throw new Error("the string date is not a formatted date string");
    return;
  }

  let year = newDate.getFullYear().toString();

  // inkrementerer by 1 since the getMonth() and getDay() functions default to 0 for 
  //sundays and january
  let month = (newDate.getMonth() + 1).toString();

  if (Number(month) < 10) {
    month = '0' + month;
  }

  let day = (newDate.getDay() + 1).toString();

  if (Number(day) < 10) {
    day = '0' + day;
  }


  let formattedDate = year + month + day;
  return formattedDate;
}

console.log(DateConverter1("2025-06-10"))
console.log(DateConverter2("2025-06-10"))

integration implementation

How to disable Electron.js panel window movable area click event on macOS?

In Electron.js, a panel type Browser window has an approximately 28-pixel top area that acts as a moveable area. Clicking in this area focuses the application, bringing the app menu to the top taskbar, while clicking elsewhere does not. I want to prevent this focusing behavior when clicking the top area to create a spotlight-like panel window. Here is my Electron app’s index.ts code.

//index.ts
import { app, BrowserWindow, globalShortcut, ipcMain } from "electron";
// This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Webpack
// plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on
// whether you're running in development or production).
declare const MAIN_WINDOW_WEBPACK_ENTRY: string;
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string;

declare const QUICK_WINDOW_WEBPACK_ENTRY: string;
declare const QUICK_WINDOW_PRELOAD_WEBPACK_ENTRY: string;

// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require("electron-squirrel-startup")) {
  app.quit();
}

let mainWindow: BrowserWindow | null;
let quickWindow: BrowserWindow | null;

const createWindow = (): void => {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    height: 600,
    width: 1000,
    webPreferences: {
      preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
    },
  });

  quickWindow = new BrowserWindow({
    type: "panel",
    frame: false,
    show: false,
    height: 600,
    width: 600,

    movable: false,
    focusable: true,
    skipTaskbar: true,
    maximizable: false,
    vibrancy: 'sidebar',
    

    webPreferences: {
      preload: QUICK_WINDOW_PRELOAD_WEBPACK_ENTRY,
    },
  });

  // and load the index.html of the app.
  mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
  quickWindow.loadURL(QUICK_WINDOW_WEBPACK_ENTRY);

  globalShortcut.register("CmdOrCtrl+Shift+1", () => {
    quickWindow?.show();
  });

  // Open the DevTools.
  // mainWindow.webContents.openDevTools();
};

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", createWindow);

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    app.quit();
    mainWindow = null;
    quickWindow = null;
  }
});

app.on("activate", () => {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.

ipcMain.handle("hideQuickAccess", () => {
  quickWindow && quickWindow.hide();
});

ipcMain.handle("resizeToExtended", () => {
  if (quickWindow) {
    quickWindow.setBounds({ height: 450, width: 500 });
  }
});

ipcMain.handle("resizeToNormal", () => {
  if (quickWindow) {
    quickWindow.setBounds({ height: 400, width: 300 });
  }
});

Illegal Invocation when calling this.spread.savePDF

Framework: VueJs
SpreadJs Version: 16.2.1

I am trying to save a PDF of the workbook but every time it hits this line of code

this.spread.savePDF((data: Blob) => {
          // dowload function
        }, (err: any) => {
          // error handling
        })

It will cause an invocation error below.

Illegal invocation
TypeError: Illegal invocation
at e.nextTick.i [as nextTick] (webpack-internal:///./node_modules/.pnpm/@[email protected]/node_modules/@grapecity/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js:17:22486)
at f (webpack-internal:///./node_modules/.pnpm/@[email protected]/node_modules/@grapecity/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js:17:36290)
at onwrite (webpack-internal:///./node_modules/.pnpm/@[email protected]/node_modules/@grapecity/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js:17:35023)
at c._write (webpack-internal:///./node_modules/.pnpm/@[email protected]/node_modules/@grapecity/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js:17:1979)
at K (webpack-internal:///./node_modules/.pnpm/@[email protected]/node_modules/@grapecity/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js:17:35945)
at P (webpack-internal:///./node_modules/.pnpm/@[email protected]/node_modules/@grapecity/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js:17:35854)
at a.write (webpack-internal:///./node_modules/.pnpm/@[email protected]/node_modules/@grapecity/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js:17:37406)
at o.P (webpack-internal:///./node_modules/.pnpm/@[email protected]/node_modules/@grapecity/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js:17:280659)
at o.n [as emit] (webpack-internal:///./node_modules/.pnpm/@[email protected]/node_modules/@grapecity/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js:17:120991)
at f.read (webpack-internal:///./node_modules/.pnpm/@[email protected]/node_modules/@grapecity/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js:17:279930)

Tried using other functions of this.spread like this.spread.getSheetCount() works. So it’s not about ‘this’ losing its reference/binding.

Why does my populateDropdown function affect the handleSearch functionality?

I am working on a furniture search and filtering system in JavaScript, where I have two main blocks of code:

  1. The populateDropdown function:
    This function is responsible for dynamically populating dropdown menus with filtered options as the user types into an input field.
function populateDropdown(inputId, dropdownId, options) { 
  const input = document.getElementById(inputId);
  const dropdown = document.getElementById(dropdownId);
  let isTextCopied = false;

  input.addEventListener('focus', function () {
    const query = input.value.toLowerCase();
    populateOptions(query, options, dropdown);
    if (!isTextCopied) dropdown.style.display = 'block';
  });

  input.addEventListener('click', function () {
    if (!isTextCopied) {
      const query = input.value.toLowerCase();
      populateOptions(query, options, dropdown);
      dropdown.style.display = 'block';
    }
  });

  input.addEventListener('input', function () {
    const query = this.value.toLowerCase();
    populateOptions(query, options, dropdown);
    if (!isTextCopied) dropdown.style.display = 'block';
  });

  document.addEventListener('mousedown', function (e) {
    if (!input.contains(e.target) && !dropdown.contains(e.target)) {
      dropdown.style.display = 'none';
    }
  });

  dropdown.addEventListener('mousedown', function (e) {
    e.stopPropagation();
  });

  function populateOptions(query, options, dropdown) {
    dropdown.innerHTML = '';
    const groupedOptions = {};

    options.forEach(option => {
      if (option.name.toLowerCase().includes(query)) {
        if (!groupedOptions[option.group]) {
          groupedOptions[option.group] = [];
        }
        groupedOptions[option.group].push(option);
      }
    });

    if (Object.keys(groupedOptions).length > 0) {
      for (const [group, groupOptions] of Object.entries(groupedOptions)) {
        const groupItem = document.createElement('li');
        groupItem.className = 'optgroup';
        groupItem.textContent = group;
        dropdown.appendChild(groupItem);

        groupOptions.forEach(option => {
          const listItem = document.createElement('li');
          let specialtypeKey = (option.name.indexOf('-') > -1) ? parseInt(option.name.split('-')[0].trim(), 10) : option.name;
          listItem.innerHTML = `<img src="${option.img}" alt="${option.name}"><span class="ddlabel">${option.name}</span>`;
          listItem.setAttribute('data-value', specialtypeKey);

          listItem.addEventListener('click', function (e) {
            e.stopPropagation();
            input.value = option.name;
            input.setAttribute('data-selected', specialtypeKey);
            dropdown.style.display = 'none';
            isTextCopied = true;
          });

          dropdown.appendChild(listItem);
        });
      }
    } else {
      dropdown.style.display = 'none';
    }
  }

  input.addEventListener('input', function () {
    if (input.value.length === 0) {
      input.value = '';
      input.removeAttribute('data-selected');
      isTextCopied = false;
    }
  });

  input.addEventListener('click', function () {
    if (isTextCopied) dropdown.style.display = 'none';
  });
}
  1. The handleSearch function and search filters:
    The handleSearch function applies different filters and updates the displayed results based on user input.
function handleSearch() {
    // Obtener los valores de los inputs y filtros con validación
    const query = document.getElementById("query").value.toLowerCase();
    const selectedLine = (document.getElementById("furniLines").value || "").trim();
    const selectedCategory = (document.getElementById("furniCategories").value || "").trim();
    const selectedEnvironment = (document.getElementById("furniEnvironments").value || "").trim();
    let selectedSpecialtype = (document.getElementById("furniSpecialtypes").value || "").trim();

    // Mantener el valor actual de "per_page" directamente desde el input
    per_page = parseInt(document.getElementById("per_page_results").value, 10) || 100;

    // Procesar el valor de selectedSpecialtype
    if (selectedSpecialtype.includes(" - ")) {
        selectedSpecialtype = selectedSpecialtype.split(" - ")[0];
    }
    selectedSpecialtype = selectedSpecialtype ? parseInt(selectedSpecialtype, 10) : "";

    // Obtener valores de filtros de tipo de muebles
    const allClothingChecked = document.getElementById("allclothing").checked;
    const normalClothingChecked = document.getElementById("clothing").checked;
    const rareClothingChecked = document.getElementById("rareclothing").checked;
    const collectibleClothingChecked = document.getElementById("collectibleclothing").checked;
    const collectibleFurniChecked = document.getElementById("furniCollectibles").checked;

    const furniWallInput = document.getElementById("furniWall");
    const furniFloorInput = document.getElementById("furniFloor");

    const selectedFurniType = furniWallInput.checked ? 'wall' : furniFloorInput.checked ? 'floor' : 'none';

    // Filtrar por tipo de colección
    let filteredData = allFurnis.slice(); // Copiar el array de furnis

    // Si "allclothing" está marcado, filtrar solo por "clothingtypes" y sus subcategorías
    if (allClothingChecked) {
        filteredData = furnidata.clothingtypes.clothingitemtypes.furnitype
            .concat(furnidata.clothingtypes.LTDclothingitemtypes.furnitype)
            .concat(furnidata.clothingtypes.rareclothingitemtypes.furnitype)
            .concat(furnidata.clothingtypes.collectibleclothingitemtypes.furnitype);
    } else {
        // Si no está marcado, seguir con el flujo normal de filtros
        if (collectibleFurniChecked) {
            filteredData = furnidata.collectibleitemtypes.furnitype;
        } else {
            filteredData = [];
            if (normalClothingChecked) filteredData = filteredData.concat(furnidata.clothingtypes.clothingitemtypes.furnitype);
            if (rareClothingChecked) filteredData = filteredData.concat(furnidata.clothingtypes.rareclothingitemtypes.furnitype);
            if (collectibleClothingChecked) filteredData = filteredData.concat(furnidata.clothingtypes.collectibleclothingitemtypes.furnitype);
            if (!normalClothingChecked && !rareClothingChecked && !collectibleClothingChecked) filteredData = allFurnis.slice();
        }
    }

    // Filtrar por tipo especial, ambiente, categoría, y colección (si se seleccionaron)
    filteredData = filteredData.filter(furni => {
    return (
        (query === "" || furni.name.toLowerCase().includes(query) || JSON.stringify(furni).toLowerCase().includes(query)) &&
        (selectedCategory === "" || (Array.isArray(furni.category) 
            ? furni.category.some(category => category.toLowerCase() === selectedCategory.toLowerCase())
            : furni.category.toLowerCase() === selectedCategory.toLowerCase())) &&
        (selectedLine === "" || furni.furniline === selectedLine) &&
        (selectedEnvironment === "" || furni.environment === selectedEnvironment) &&
        (selectedSpecialtype === "" || furni.specialtype === selectedSpecialtype) &&
        (!document.getElementById("onShop").checked || furni.offerid !== -1) &&
        (selectedFurniType === 'wall' ? furnidata.wallitemtypes.furnitype.some(item => item.id === furni.id) : true) &&
        (selectedFurniType === 'floor' ? furnidata.roomitemtypes.furnitype.some(item => item.id === furni.id) : true)
    );
});


    // Filtrar por "ltdclothing" si está marcado
    const ltdclothingChecked = document.getElementById("ltdclothing").checked;
    if (ltdclothingChecked) {
        filteredData = filteredData.filter(furni => furnidata.ltdclothingitemtypes.furnitype.some(item => item.id === furni.id));
    }

    // Filtrar específicamente con los inputs de tipo especial, ambiente, categoría, y colección
    // Filtrar por tipo especial solo con el objeto JSON "specialtype"
    const specialtypeInput = document.getElementById("furniSpecialtypesInput").value.toLowerCase();
    if (specialtypeInput) {
        filteredData = filteredData.filter(furni => furni.specialtype.toLowerCase().includes(specialtypeInput));
    }

    // Filtrar por ambiente solo con el objeto JSON "environment"
    const environmentInput = document.getElementById("furniEnvironmentsInput").value.toLowerCase();
    if (environmentInput) {
        filteredData = filteredData.filter(furni => furni.environment.toLowerCase().includes(environmentInput));
    }

    // Filtrar por categoría solo con el objeto JSON "category"
    const categoryInput = document.getElementById("furniCategoriesInput").value.toLowerCase();
if (categoryInput) {
    filteredData = filteredData.filter(furni => furni.category.toLowerCase().includes(categoryInput));
}

    // Filtrar por colección solo con el objeto JSON "furniline"
    const lineInput = document.getElementById("furniLinesInput").value.toLowerCase();
    if (lineInput) {
        filteredData = filteredData.filter(furni => furni.furniline.toLowerCase().includes(lineInput));
    }

    // Actualizar los datos globales con los resultados filtrados
    window.filteredDataGlobal = filteredData;

    // Calcular el número de páginas
    const totalPages = Math.ceil(filteredData.length / per_page);
    if (page > totalPages) {
        page = totalPages || 1;
    }

    // Mostrar los resultados filtrados
    mostrarResultados();
}
});

Before integrating the populateDropdown function, the filters in handleSearch worked as expected. However, after adding the populateDropdown functionality, it seems to be interfering with the search results.

How can I ensure that the populateDropdown function and the handleSearch functionality work together without interfering with each other? Specifically, I need to understand why interactions with the populateDropdown seem to break or overwrite the filters in handleSearch.

How can I extract text from a specific HTML tag using JavaScript? [duplicate]

I’m working on a simple web project where I need to dynamically extract the text from a specific HTML element using JavaScript. For example, I have a with an id, and I want to get the text content from inside that element and use it elsewhere in my script.

I’ve tried using document.getElementById(“quote”) but I’m not sure if I should use .value, .innerHTML, or .textContent to get just the plain text. I also want to make sure this works reliably in most browsers and doesn’t return any extra HTML or quotes — just the clean string.

Also, if there are better ways to access or manipulate text content from the DOM, I’d appreciate a quick explanation or best practices.

This gave me the text, but I read that innerHTML might include HTML tags if there are any, which I don’t want.

Using const instead of let in Javascript

I have seen quite a few cases (Specially in FreecodeCamp) where they use const for defining loop variables:
i.e.-
for(const i =0;i<5;i++) instead of for(let i=0;i<5;i++).
What is the purpose of it? Is there actually any benefit of using const ? Are there any drawbacks if I use let ?

How to add autocomplete suggestions to st.chat_input() in Streamlit (like Google Search)?

I want to show autocomplete suggestions while the user is typing — like Google Search. For example, when a user types “how”, it should suggest things like: how it work, how to do and etc.

# Chat input
    if query1 := st.chat_input("Ask Here", key="chat1"):
        with st.spinner("AI is analyzing ..."):
            try:
                st.chat_message("user").markdown(query1)
                st.session_state.sales_messages.append({"role": "user", "content": query1})
                # (AI response generation logic here)

is there anyway I can add autocomplete to st.chat_input()?

I’m okay using JavaScript or streamlit.components.v1 if needed.