Short summary
- Users can upload an image to a Cropper field and see a Croppie preview. But when they select a different crop size from the dropdown the preview sometimes becomes blank/white and the image appears to disappear.
Why this matters
- This breaks the UX for customers configuring print photos or other image-based options—users expect to be able to change the target size and re-position/zoom the same uploaded image.
Reproduction
- Use the attached meta group (ppom-meta-1782149192.csv) or any Cropper field with multiple size options.
- Upload an image.
- Change the crop size via the dropdown.
- See the preview area become blank/white (image disappears).
Observed
- Croppie boundary renders, but the uploaded image disappears from the viewport.
Expected
- Croppie should re-initialize with the selected size while preserving the uploaded image so the user can continue adjusting the crop.
Technical root cause
There are two client-side issues that combine to cause this:
- Shared options object is mutated on size change (JS)
- File: js/file-upload.js
- Function: ppom_set_croppie_options
- Problem: code mutates the shared
ppom_file_vars.croppie_options object (it writes option.url and option.viewport = viewport). Because the same option object is reused for subsequent re-inits, a one-time change persists and breaks responsive calculations.
- Code reference: js/file-upload.js around where ppom_set_croppie_options is defined (search for
function ppom_set_croppie_options in file-upload.js).
- Fragile read/write of image URL from Croppie DOM
- File: js/file-upload.js
- Code location: Croppie size-change handler (the
change listener on .ppom-cropping-size) — the handler reads jQuery(croppie_dom).find('img').attr('src') and writes it back into file_list_preview_containers[data_name].image_url before reinitialization.
- Problem: Croppie's internal
<img> can be a blob/data URL or be removed by destroy(), so reading it back is unreliable and can produce an invalid URL which then causes Croppie to initialize without an image.
- Code reference: js/file-upload.js around the Croppie size-change handler (search for
'.ppom-croppie-preview' ).on('change', '.ppom-cropping-size').
Server-side context
- File: src/Files/Handler.php
- Function: get_croppie_options (builds viewport / boundary values passed to the frontend). The PHP options are fine, but combined with the client-side mutation they surface inconsistent behavior for complex meta groups (e.g. boundary string
"480,300").
- Code reference: src/Files/Handler.php → get_croppie_options
Suggested fixes (concrete, copy/paste friendly)
- Do not mutate the shared options object — use a deep copy before modifying:
// inside ppom_set_croppie_options
const workingOption = jQuery.extend(true, {}, option);
workingOption.url = file_list_preview_containers[file_name].image_url;
if (viewport !== undefined) {
viewport.type = workingOption.viewport.type;
workingOption.viewport = viewport;
}
// Use `workingOption` when calling `.croppie()` instead of mutating `option`.
- Stop reading/writing the image src from Croppie's DOM during size changes. The canonical upload URL is already stored during upload in
file_list_preview_containers[file_name].image_url (set in ppom_show_cropped_preview). Remove the find('img').attr('src') read and do not overwrite file_list_preview_containers[file_name].image_url in the size-change handler.
Short summary
Why this matters
Reproduction
Observed
Expected
Technical root cause
There are two client-side issues that combine to cause this:
ppom_file_vars.croppie_optionsobject (it writesoption.urlandoption.viewport = viewport). Because the sameoptionobject is reused for subsequent re-inits, a one-time change persists and breaks responsive calculations.function ppom_set_croppie_optionsin file-upload.js).changelistener on.ppom-cropping-size) — the handler readsjQuery(croppie_dom).find('img').attr('src')and writes it back intofile_list_preview_containers[data_name].image_urlbefore reinitialization.<img>can be a blob/data URL or be removed bydestroy(), so reading it back is unreliable and can produce an invalid URL which then causes Croppie to initialize without an image.'.ppom-croppie-preview' ).on('change', '.ppom-cropping-size').Server-side context
"480,300").Suggested fixes (concrete, copy/paste friendly)
file_list_preview_containers[file_name].image_url(set inppom_show_cropped_preview). Remove thefind('img').attr('src')read and do not overwritefile_list_preview_containers[file_name].image_urlin the size-change handler.