Forráskód Böngészése

Fix mobile dropzone infinite-recursion on tap-to-upload — v1.5.10 -> v1.5.11

The <input type="file"> lives inside .studiou-fpp-upload-area, so
$fileInput.trigger('click') dispatched a bubbling jQuery event that
re-entered the dropzone's own click handler. Mobile browsers synthesize
an extra click when the picker closes, which tipped this into infinite
recursion: "Maximum call stack size exceeded" → picker never opened.

Fix: open the picker via native $fileInput[0].click() (no bubbling
jQuery event), and bail out of the dropzone handler when the click
originates on the input itself. Defensive stopPropagation on the input
as a second layer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dalibor Votruba 2 hónapja
szülő
commit
7d303370f9

+ 2 - 2
studiou-wc-free-photo-product/CLAUDE.md

@@ -2,7 +2,7 @@
 
 ## Project Overview
 
-WordPress/WooCommerce plugin called **studiou-wc-free-photo-product** (QDR - Studiou WC Free Photo Product) v1.5.10.
+WordPress/WooCommerce plugin called **studiou-wc-free-photo-product** (QDR - Studiou WC Free Photo Product) v1.5.11.
 Allows publishing special variable products where customers upload custom raw images to be printed for a price.
 
 ## Initial Requirements
@@ -52,7 +52,7 @@ Allows publishing special variable products where customers upload custom raw im
 1. `maybe_suppress_pvtfw()` detaches pvtfw's `print_table` and `available_options_btn` hooks on `wp` priority 5.
 2. `render_upload_area()` on `woocommerce_single_product_summary` priority 35 passes variants + max uploads + existing batch files + hero preview URL to JS via `wp_localize_script('studiou-wcfpp-frontend', 'studiouFppCardData', ...)`.
 3. Browser renders:
-   - **Dropzone** (multi-file `<input type="file" multiple>`) — accepts drag-drop + click-to-browse.
+   - **Dropzone** (multi-file `<input type="file" multiple>`) — accepts drag-drop + click-to-browse. Click-to-browse opens the native file picker via `$fileInput[0].click()` (NOT `$fileInput.trigger('click')`), because the `<input>` lives inside the dropzone element and a bubbling jQuery trigger re-entered the dropzone's own click handler, causing `Maximum call stack size exceeded` on mobile where the browser synthesizes an extra click when the picker closes (fixed in 1.5.11).
    - **Cards stack** — one card per upload, all built client-side by `buildCard()` from `studiouFppCardData`.
    - **Order overview panel** — rendered server-side initially from `WC()->cart` filtered to the current product; re-rendered in-place after each cart change.
 4. Customer drops photos → `enqueueFiles()` creates a "uploading" card per file, queue processes sequentially via chunked AJAX.

+ 13 - 2
studiou-wc-free-photo-product/assets/js/frontend.js

@@ -247,9 +247,20 @@
                 var files = e.originalEvent.dataTransfer.files;
                 enqueueFiles(files);
             });
-            $dropzone.on('click', function () {
+            $dropzone.on('click', function (e) {
                 if ($dropzone.hasClass('studiou-fpp-dropzone-disabled')) return;
-                $fileInput.trigger('click');
+                // File input lives INSIDE the dropzone, so a click on it bubbles up and
+                // re-enters this handler. On mobile the synthetic .trigger('click') also
+                // bubbles, producing infinite recursion ("Maximum call stack size exceeded").
+                // Ignore clicks that originate on (or bubble from) the input itself.
+                if (e.target === $fileInput[0]) return;
+                // Use the native .click() on the DOM element — it opens the file picker
+                // without dispatching a bubbling jQuery event that would re-trigger us.
+                $fileInput[0].click();
+            });
+            $fileInput.on('click', function (e) {
+                // Defense in depth: stop the click from bubbling back to the dropzone.
+                e.stopPropagation();
             });
             $fileInput.on('change', function () {
                 enqueueFiles(this.files);

+ 1 - 1
studiou-wc-free-photo-product/languages/studiou-wc-free-photo-product-cs_CZ.po

@@ -3,7 +3,7 @@
 # This file is distributed under the GPL v2 or later.
 msgid ""
 msgstr ""
-"Project-Id-Version: QDR - Studiou WC Free Photo Product 1.5.10\n"
+"Project-Id-Version: QDR - Studiou WC Free Photo Product 1.5.11\n"
 "Report-Msgid-Bugs-To: https://www.quadarax.com\n"
 "POT-Creation-Date: 2026-04-02 00:00+0000\n"
 "PO-Revision-Date: 2026-04-02 00:00+0000\n"

+ 1 - 1
studiou-wc-free-photo-product/languages/studiou-wc-free-photo-product.pot

@@ -2,7 +2,7 @@
 # This file is distributed under the GPL v2 or later.
 msgid ""
 msgstr ""
-"Project-Id-Version: QDR - Studiou WC Free Photo Product 1.5.10\n"
+"Project-Id-Version: QDR - Studiou WC Free Photo Product 1.5.11\n"
 "Report-Msgid-Bugs-To: https://www.quadarax.com\n"
 "POT-Creation-Date: 2026-04-02 00:00+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"

+ 12 - 0
studiou-wc-free-photo-product/readme.md

@@ -2,6 +2,18 @@
 
 WordPress (6.9.4+) / WooCommerce (10.6.2+) plugin that allows publishing special variable products with custom raw image upload for photo printing. Customers upload one or more photos on the product page and compose an order where each uploaded photo can be printed in a different variant at its own quantity. Uploaded files are stored in the WordPress media library under a configurable media category.
 
+## What's new in 1.5.11
+
+- **Mobile upload fix.** Tapping the dropzone on mobile raised `Maximum call stack size exceeded` and prevented the file picker from opening. The `<input type="file">` lives inside the dropzone, so `$fileInput.trigger('click')` dispatched a bubbling jQuery event that re-entered the dropzone's own click handler in an infinite loop (mobile surfaces it because the browser synthesizes an extra click when the picker closes). Fix: open the picker via native `$fileInput[0].click()` (no bubbling jQuery event) and bail out of the dropzone handler when the click originates on the input itself.
+
+## What's new in 1.5.10
+
+- **Clean currency rendering in the variant combobox.** WooCommerce's `get_woocommerce_currency_symbol()` returns `Kč` as `&#75;&#269;` and the Czech `get_woocommerce_price_format()` as `%2$s&nbsp;%1$s`. Both values flowed into `formatPricePlain()`, whose result is assigned via jQuery `.text()`, so entities rendered verbatim as `10,00&nbsp;&#75;&#269;` in `<option>` labels. Decoded at the PHP localize step with `html_entity_decode(..., ENT_QUOTES | ENT_HTML5, 'UTF-8')` before handing to JS.
+
+## What's new in 1.5.9
+
+- **HTML entities in variant attribute labels.** Term names or non-taxonomy attribute values stored in the WP database sometimes carry entities (`&nbsp;`, `&#75;`, `&aacute;`, …) pasted in from rich editors. Since `<option>` text is literal, they leaked into the variant combobox as-is. `build_variant_list()` (JS combobox data) and the order-overview template now decode entities (and urldecode non-taxonomy values) before building the label.
+
 ## What's new in 1.5.8
 
 - **Explicit "Enlarge" button** on every upload card (in the price-row next to Add-to-Cart) and every order-overview line. Opens the lightbox with the `woocommerce_single`-size preview so customers can check image detail before committing. The button sits clear of the × remove button and is wired via direct `element.onclick` + jQuery delegation to survive any theme-level click interceptors. If the overlay DOM fails to initialize for any reason, the button falls back to opening the preview in a new browser tab instead of being a no-op. Thumbnail clicks remain as a secondary opener.

+ 2 - 2
studiou-wc-free-photo-product/studiou-wc-free-photo-product.php

@@ -3,7 +3,7 @@
  * Plugin Name: QDR - Studiou WC Free Photo Product
  * Plugin URI: https://www.quadarax.com/plugins/studiou-wc-free-photo-product
  * Description: Allows publishing special WooCommerce products with variants and custom raw image upload for photo printing
- * Version: 1.5.10
+ * Version: 1.5.11
  * Requires at least: 6.9.4
  * Requires PHP: 8.2
  * Requires Plugins: woocommerce, product-variant-table-for-woocommerce
@@ -22,7 +22,7 @@ if (!defined('WPINC')) {
     die;
 }
 
-if (!defined('STUDIOU_WCFPP_VERSION')) define('STUDIOU_WCFPP_VERSION', '1.5.10');
+if (!defined('STUDIOU_WCFPP_VERSION')) define('STUDIOU_WCFPP_VERSION', '1.5.11');
 if (!defined('STUDIOU_WCFPP_PLUGIN_DIR')) define('STUDIOU_WCFPP_PLUGIN_DIR', plugin_dir_path(__FILE__));
 if (!defined('STUDIOU_WCFPP_PLUGIN_URL')) define('STUDIOU_WCFPP_PLUGIN_URL', plugin_dir_url(__FILE__));
 if (!defined('STUDIOU_WCFPP_PLUGIN_BASENAME')) define('STUDIOU_WCFPP_PLUGIN_BASENAME', plugin_basename(__FILE__));