I'm trying to create an upload preview for the image the user is uploading. I've gotten most of what I want done (thanks to stackoverflow... a lot of copying pasting and some tweaking) but since I don't know JavaScript, I can't get it to work exactly.
function uploadPreview(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
if (e.target.result.trim().length == 0) {
$('#serviceImage').attr('src', 'http://catawbabrewing.com/wp-content/themes/catawba/images/placeholder.png');
} else {
$('#serviceImage').attr('src', e.target.result);
}
}
reader.readAsDataURL(input.files[0]);
}
}
function uploadPreviewExt(input) {
if (input.trim().length == 0) {
var previewSrc = '{{CSS_URL}}/images/placeholder.jpg';
} else {
var previewSrc = input;
}
$('#serviceImage').attr('src', previewSrc);
}
function resetUploadPreview() {
if (!$('#previousImage').val()) {
$('#serviceImage').attr('src', 'http://catawbabrewing.com/wp-content/themes/catawba/images/placeholder.png');
} else {
$('#serviceImage').attr('src', '{{PROD_IMG}}/'.$('#previousImage').val());
}
}
$("#mainImage").change(function() {
uploadPreview(this);
});
$('[name="mainImgExt"]').on('change', function() {
uploadPreviewExt(this.value);
});
$('#clearUpload').on('click', function() {
$('#mainImage').val('');
if ($('#imgExt').val().trim().length == 0) {
resetUploadPreview();
} else {
uploadPreviewExt($('#imgExt').val());
}
});
$('#clearUploadExt').on('click', function() {
$('#imgExt').val('');
if (!$('#mainImage').val()) {
resetUploadPreview();
} else {
uploadPreview($('#mainImage'));
}
});
pointer {
cursor: pointer;
}
img.placeholder {
width: 100px;
height: 100px;
}
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="//unpkg.com/popper.js@1.12.9/dist/umd/popper.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<div class="form-group p-3 border p-2 rounded m-3">
<div class="row">
<div class="col-sm-3 text-center pt-2 border-right">
<label for="mainImage"><img src="http://catawbabrewing.com/wp-content/themes/catawba/images/placeholder.png" alt="Placeholder" id="serviceImage" class="placeholder img-thumbnail" aria-describedby="imagePreviewHelp" /></label>
<small id="imagePreviewHelp" class="form-text text-muted">Preview could appear stretched</small>
</div>
<div class="col">
<label for="mainImage">Image</label>
<div class="input-group mb-3">
<input type="file" class="form-control border p-1" id="mainImage" name="mainImage" />
<div class="input-group-append">
<span class="input-group-text bg-warning text-danger pointer" id="clearUpload">X</span>
</div>
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" id="imgExt" name="mainImgExt" placeholder="Externel Image" aria-describedby="imageHelp" />
<div class="input-group-append">
<span class="input-group-text bg-warning text-danger pointer" id="clearUploadExt">X</span>
</div>
</div>
<small id="imageHelp" class="form-text text-muted">Upload a local image <strong>or</strong> link to an external image.</small>
</div>
</div>
</div>
There is a lot of JavaScript involved (more then my comfort zone since I don't know it at all).
There are two versions of HTML that the JavaScript could come across. It depends whether the user is adding a service, or editing one. The form is generated dynamically with the help of TWIG.
In JSFiddle, there is one version of the image uploading part of the form (if it's adding a service) below is the version for editing a service. (The hidden input field "previousImage" is added and the preview is the current image rather then the placeholder)
<div class="form-group p-3 border p-2 rounded">
<div class="row">
<div class="col-sm-3 text-center pt-2 border-right">
<label for="mainImage"><img src="https://logismarketmx.cdnwm.com/ip/eve-maquinaria-mantenimiento-para-gruas-mantenimiento-de-gruas-987423-FGR.jpg" alt="Vinyl" id="serviceImage" class="placeholder img-thumbnail" aria-describedby="imagePreviewHelp" /></label>
<input type="hidden" name="previousImage" id="previousImage" value="eve-maquinaria-mantenimiento-para-gruas-mantenimiento-de-gruas-987423-FGR.jpg" />
<small id="imagePreviewHelp" class="form-text text-muted">Preview could appear stretched</small>
</div>
<div class="col">
<label for="mainImage">Image</label>
<div class="input-group mb-3">
<input type="file" class="form-control border p-1" id="mainImage" name="mainImage" />
<div class="input-group-append">
<span class="input-group-text bg-warning text-danger pointer" id="clearUpload">X</span>
</div>
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" id="imgExt" name="mainImgExt" placeholder="Externel Image" aria-describedby="imageHelp" />
<div class="input-group-append">
<span class="input-group-text bg-warning text-danger pointer" id="clearUploadExt">X</span>
</div>
</div>
<small id="imageHelp" class="form-text text-muted">Upload a local image <strong>or</strong> link to an external image.</small>
</div>
</div>
</div>
That's the backstory of the problem. Here is what I'm struggling with.
I want it when the user clicks on the red 'X' to clear the field to it's immediate left. It clears the field, but I also want to reset the upload preview image.
The reason the second version of the form matters is because if the user resets and is adding, then the image changes to the placeholder (which is what happens for the local upload but not the external URL); but if the user is editing a service then the upload preview would reset to the previous image that was set to the service.
I have the javascript to what I think should be working, but it doesn't.
function resetUploadPreview()
{
if(!$('#previousImage').val())
{
$('#serviceImage').attr('src', '{{CSS_URL}}/images/placeholder.jpg');
}
else
{
$('#serviceImage').attr('src', '{{PROD_IMG}}/' . $('#previousImage').val());
}
}
The logic behind that is if input with the ID 'previousImage' is empty (or nonexistent) it would display the placeholder but if it does have a value than we use it's value (the filename) to display this image.
But it doesn't do that, clearing the local file upload resets the image to the placeholder no matter if previousImage is filled or not, and the external url doesn't clear at all.
Another feature I'd like implemented is if both fields are filled in (local and external) then clearing one would display the other image in the preview.
Sorry if this seems simple, the logic seems simple to me but I can't seem to get it to work and I have no idea what I am missing... seems to me like everything is where it should work, but it just doesn't.
When editing it doesn't reset to the previous image... it doesn't reset at all. Console is giving me the following error
TypeError: "../design/variant/productImages/".$ is not a function
The line of code that it leads to is:
function resetUploadPreview()
{
if(!$('#previousImage').val())
{
$('#serviceImage').attr('src', '{{CSS_URL}}/images/placeholder.jpg');
}
else
{
// This is the line that makes that error
$('#serviceImage').attr('src', '{{PROD_IMG}}/' . $('#previousImage').val());
}
}
When adding a new service if you add a local image first and then an external image it shows the external image preview just like it should. But once you clear the external image it should display the local image (since it is filled in) but it doesn't change the preview at all. And console isn't showing any warnings/errors.
What am I doing wrong?
Nice work!
I made two adjustments:
In JavaScript, string concatenation is performed by using the +
sign, as opposed to the .
sign. (Hence the TypeError
message you referenced.) I changed the code in resetUploadPreview()
accordingly.
The uploadPreview()
function does not expect a jQuery object, but a jQuery object is passed to restore the main image when the external image field is cleared. I changed it to pass the DOM element instead: $('#mainImage')[0]
instead of $('#mainImage')
. For more info, see What does $(selector)[0] mean in jQuery?
function uploadPreview(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
if (e.target.result.trim().length == 0) {
$('#serviceImage').attr('src', '//catawbabrewing.com/wp-content/themes/catawba/images/placeholder.png');
} else {
$('#serviceImage').attr('src', e.target.result);
}
}
reader.readAsDataURL(input.files[0]);
}
}
function uploadPreviewExt(input) {
if (input.trim().length == 0) {
var previewSrc = '{{CSS_URL}}/images/placeholder.jpg';
} else {
var previewSrc = input;
}
$('#serviceImage').attr('src', previewSrc);
}
function resetUploadPreview() {
if (!$('#previousImage').val()) {
$('#serviceImage').attr('src', 'http://catawbabrewing.com/wp-content/themes/catawba/images/placeholder.png');
} else {
$('#serviceImage').attr('src', '{{PROD_IMG}}/' + $('#previousImage').val());
}
}
$("#mainImage").change(function() {
uploadPreview(this);
});
$('[name="mainImgExt"]').on('change', function() {
uploadPreviewExt(this.value);
});
$('#clearUpload').on('click', function() {
$('#mainImage').val('');
if ($('#imgExt').val().trim().length == 0) {
resetUploadPreview();
} else {
uploadPreviewExt($('#imgExt').val());
}
});
$('#clearUploadExt').on('click', function() {
$('#imgExt').val('');
if (!$('#mainImage').val()) {
resetUploadPreview();
} else {
uploadPreview($('#mainImage')[0]);
}
});
pointer {
cursor: pointer;
}
img.placeholder {
width: 100px;
height: 100px;
}
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="//unpkg.com/popper.js@1.12.9/dist/umd/popper.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<div class="form-group p-3 border p-2 rounded m-3">
<div class="row">
<div class="col-sm-3 text-center pt-2 border-right">
<label for="mainImage"><img src="http://catawbabrewing.com/wp-content/themes/catawba/images/placeholder.png" alt="Placeholder" id="serviceImage" class="placeholder img-thumbnail" aria-describedby="imagePreviewHelp" /></label>
<small id="imagePreviewHelp" class="form-text text-muted">Preview could appear stretched</small>
</div>
<div class="col">
<label for="mainImage">Image</label>
<div class="input-group mb-3">
<input type="file" class="form-control border p-1" id="mainImage" name="mainImage" />
<div class="input-group-append">
<span class="input-group-text bg-warning text-danger pointer" id="clearUpload">X</span>
</div>
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" id="imgExt" name="mainImgExt" placeholder="Externel Image" aria-describedby="imageHelp" />
<div class="input-group-append">
<span class="input-group-text bg-warning text-danger pointer" id="clearUploadExt">X</span>
</div>
</div>
<small id="imageHelp" class="form-text text-muted">Upload a local image <strong>or</strong> link to an external image.</small>
</div>
</div>
</div>