зеркало из https://github.com/mozilla/kitsune.git
Merge pull request #6159 from escattone/fix-broken-image-upload-preview
Fix broken image upload preview
This commit is contained in:
Коммит
464f34d24e
|
@ -28,34 +28,30 @@
|
|||
|
||||
{% macro submit_row(form, type) %}
|
||||
<div class="upload-action sumo-button-wrap reverse-on-desktop align-full">
|
||||
<input type="submit" class="sumo-button primary-button" name="upload" value="{{ _('Upload file') }}">
|
||||
<input type="submit" class="sumo-button primary-button" name="upload" value="{{ _('Upload') }}">
|
||||
<input type="submit" name="cancel" class="sumo-button kbox-cancel {% if form.instance.pk %} draft{% endif %}" data-action="{{ url('gallery.cancel_draft', media_type=type) }}" value="{{ _('Cancel') }}">
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro image_preview(form, type, name) %}
|
||||
{% set classes = 'preview ' + name %}
|
||||
{% if form.instance.pk and type == 'image' %}
|
||||
{% set html =
|
||||
'<div class="preview-{type} {name}">
|
||||
<img src="{thumbnail_url}">
|
||||
</div>
|
||||
<input type="submit" name="cancel" class="sumo-button button-sm draft link-btn"
|
||||
data-name="{name}" data-action="{action}" value="{value}">'|fe(
|
||||
type=type, name=name,
|
||||
thumbnail_url=form.instance.thumbnail_url_if_set(),
|
||||
action=url('gallery.cancel_draft', media_type=type),
|
||||
value=_('Delete this image')) %}
|
||||
{% set classes = classes + ' on' %}
|
||||
{% else %}
|
||||
{% set classes = classes + ' off' %}
|
||||
{% if type == 'image' %}
|
||||
<div class="field preview {{ name }} {% if form.instance.pk %}on{% else %}off{% endif %}">
|
||||
<label>{{ _('Preview') }}</label>
|
||||
<div class="preview-{{ type }} {{ name }}">
|
||||
{% if form.instance.pk %}
|
||||
<img class="preview" src="{{ form.instance.file.url }}" />
|
||||
{% endif %}
|
||||
</div>
|
||||
<input type="submit" name="cancel" class="sumo-button button-sm draft link-btn"
|
||||
data-name="{{ name }}" data-action="{{ url('gallery.cancel_draft', media_type=type) }}"
|
||||
value="{{ _('Delete this image') }}" />
|
||||
</div>
|
||||
{% endif %}
|
||||
{{ raw_row(html, classes, _('Preview')) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro image_fields(form, type, name) %}
|
||||
{{ form_row(form, name, classes='upload-media') }}
|
||||
{{ raw_row('<span></span><a class="{name}" href="{url}">{text}</a>'|fe(
|
||||
{{ raw_row('<div class="progress-message"></div><a class="{name} sumo-button" data-type="{name}" href="{url}">{text}</a>'|fe(
|
||||
name=name, text=_('Cancel'),
|
||||
url=url('gallery.gallery', media_type=media_type)),
|
||||
'progress ' + name, _('Progress')) }}
|
||||
|
@ -79,11 +75,10 @@ TODO: better error messages ("invalid file" means too big, or extension, etc)
|
|||
<div
|
||||
class="gallery-upload-modal hide-until-expanded attachments-upload"
|
||||
id="gallery-upload-modal"
|
||||
title="{% if has_draft %}{{ _('Continue Uploading Media') }}{% else %}{{ _('Upload a New Media File') }}{% endif %}"
|
||||
title="Upload Media File"
|
||||
data-modal="true"
|
||||
data-target="#btn-upload"
|
||||
data-id="upload-kbox"
|
||||
data-position="center"
|
||||
data-max-image-size="{{ settings.IMAGE_MAX_FILESIZE }}">
|
||||
<form id="gallery-upload-image" class="upload-form{{ ' draft' if image_form.instance.pk else '' }}"
|
||||
data-post-url="{{ url('gallery.upload_async', media_type='image') }}"
|
||||
|
|
|
@ -28,8 +28,7 @@ import "sumo/js/kbox";
|
|||
'invalid': gettext('Invalid image. Please select a valid image file.'),
|
||||
'toolarge': gettext('Image too large. Please select a smaller image file.'),
|
||||
'cancelled': gettext('Upload cancelled. Please select an image file.'),
|
||||
'deleted': gettext('File deleted. Please select an image file.'),
|
||||
'del': gettext('Delete this image')
|
||||
'deleted': gettext('File deleted. Please select an image file.')
|
||||
};
|
||||
|
||||
// Save all initial values of input details:
|
||||
|
@ -94,12 +93,13 @@ import "sumo/js/kbox";
|
|||
|
||||
// Bind cancel upload event.
|
||||
$('.progress a', self.$modal).on("click", function cancelUpload(ev) {
|
||||
var type = $(this).attr('class');
|
||||
var type = $(this).data('type');
|
||||
ev.preventDefault();
|
||||
self.cancelUpload($(this));
|
||||
self.setInputError($(this).closest('.upload-form')
|
||||
.find('input[name="' + type + '"]'),
|
||||
'cancelled');
|
||||
self.setInputMessage(
|
||||
$(this).closest('.upload-form').find('input[name="' + type + '"]'),
|
||||
'cancelled'
|
||||
);
|
||||
return false;
|
||||
});
|
||||
|
||||
|
@ -225,8 +225,7 @@ import "sumo/js/kbox";
|
|||
startUpload: function($input) {
|
||||
var $form = $input.closest('.upload-form'),
|
||||
filename = $input.val().split(/[\/\\]/).pop(),
|
||||
$progress = $('.progress', $form)
|
||||
.filter('.' + $input.attr('name'));
|
||||
$progress = $('.progress', $form).filter(`.${$input.attr('name')}`);
|
||||
// truncate filename
|
||||
if (filename.length > CONSTANTS.maxFilenameLength) {
|
||||
filename = filename.substr(0, CONSTANTS.maxFilenameLength) +
|
||||
|
@ -234,7 +233,7 @@ import "sumo/js/kbox";
|
|||
}
|
||||
$form.find('.upload-media.' + $input.attr('name')).hideFade();
|
||||
var message = interpolate(gettext('Uploading "%s"...'), [filename]);
|
||||
$progress.filter('.row-right').find('span').text(message);
|
||||
$progress.find('.progress-message').text(message);
|
||||
$progress.showFade();
|
||||
$form.find('.metadata').show();
|
||||
return {filename: filename};
|
||||
|
@ -273,11 +272,12 @@ import "sumo/js/kbox";
|
|||
uploadSuccess: function($input, iframeJSON, filename) {
|
||||
var type = $input.attr('name'),
|
||||
$form = $input.closest('.upload-form'),
|
||||
$cancel_btn = $('.upload-action input[name="cancel"]', $form),
|
||||
$content, attrs = {},
|
||||
$preview_area,
|
||||
$cancel_btn = $('input[name="cancel"]', $form),
|
||||
$content,
|
||||
$previewArea,
|
||||
$previewImage,
|
||||
$previewImageContainer,
|
||||
upFile = iframeJSON.file;
|
||||
var message = CONSTANTS.messages[type].del;
|
||||
|
||||
// Upload is no longer in progress.
|
||||
$form.find('.progress.' + type).hideFade();
|
||||
|
@ -285,38 +285,36 @@ import "sumo/js/kbox";
|
|||
// generate preview
|
||||
if (type === 'file') {
|
||||
// create thumbnail
|
||||
$content = $('<img/>')
|
||||
.attr({
|
||||
alt: upFile.name, title: upFile.name,
|
||||
width: upFile.width, height: upFile.height,
|
||||
$content = $('<img/>').attr({
|
||||
class: 'preview',
|
||||
alt: upFile.name,
|
||||
title: upFile.name,
|
||||
src: upFile.thumbnail_url
|
||||
})
|
||||
.wrap('<div class="preview-' + type + '"/>').parent();
|
||||
});
|
||||
}
|
||||
$previewArea = $(`.preview.${type}`, $form);
|
||||
$previewImageContainer = $previewArea.find(".preview-image");
|
||||
$previewImage = $previewImageContainer.find("img");
|
||||
if ($previewImage.length) {
|
||||
$previewImage.replaceWith($content);
|
||||
} else {
|
||||
$previewImageContainer.append($content);
|
||||
}
|
||||
$preview_area = $('.preview.' + type, $form);
|
||||
$preview_area.filter('.row-right').html($content);
|
||||
// Create cancel button.
|
||||
attrs['data-action'] = $cancel_btn.data('action') +
|
||||
'?field=' + type;
|
||||
attrs['data-name'] = type;
|
||||
$cancel_btn.clone().val(message).attr(attrs)
|
||||
.removeClass('kbox-cancel')
|
||||
.appendTo($preview_area.filter('.row-right'))
|
||||
.makeCancelUpload();
|
||||
$cancel_btn.makeCancelUpload();
|
||||
// Show the preview area and make it a draft
|
||||
$preview_area.showFade();
|
||||
$previewArea.showFade();
|
||||
$form.addClass('draft');
|
||||
},
|
||||
/*
|
||||
* Little helper function to set an error next to the file input.
|
||||
* Little helper function to display a message next to the file input.
|
||||
* Takes the file $input and a reason.
|
||||
*/
|
||||
setInputError: function($input, reason) {
|
||||
setInputMessage: function($input, reason) {
|
||||
var type = $input.attr('name');
|
||||
var message = CONSTANTS.messages[type][reason];
|
||||
var $row_input = $('.upload-media.row-right.' + type);
|
||||
$row_input.find('div.details').addClass('error')
|
||||
.html(message);
|
||||
var $uploadDetails = $(`.upload-media.${type}`).find('div.details');
|
||||
$uploadDetails.html(message);
|
||||
},
|
||||
/*
|
||||
* Fired if isValidFile or isTooLarge is false or server returned failure.
|
||||
|
@ -329,7 +327,7 @@ import "sumo/js/kbox";
|
|||
// Cancel existing upload.
|
||||
$('.progress.' + type).find('a.' + type).trigger('click');
|
||||
// Show an error message.
|
||||
self.setInputError($input, reason);
|
||||
self.setInputMessage($input, reason);
|
||||
},
|
||||
/*
|
||||
* Fired when deleting an uploaded image.
|
||||
|
@ -343,8 +341,7 @@ import "sumo/js/kbox";
|
|||
$mediaForm = $input.closest('.upload-form'),
|
||||
type = $input.data('name');
|
||||
// Clean up all the preview and progress information.
|
||||
$mediaForm.find('.preview.' + type).hideFade()
|
||||
.filter('.row-right').html('');
|
||||
$mediaForm.find('.preview.' + type).hideFade();
|
||||
|
||||
// Send ajax request over to remove file.
|
||||
$.ajax({
|
||||
|
@ -354,8 +351,10 @@ import "sumo/js/kbox";
|
|||
dataType: 'json'
|
||||
// Ignore the response, nothing to do.
|
||||
});
|
||||
self.setInputError($mediaForm.find('input[name="' + type + '"]'),
|
||||
'deleted');
|
||||
self.setInputMessage(
|
||||
$mediaForm.find('input[name="' + type + '"]'),
|
||||
'deleted'
|
||||
);
|
||||
self._reUpload($mediaForm, type);
|
||||
},
|
||||
/*
|
||||
|
@ -366,7 +365,7 @@ import "sumo/js/kbox";
|
|||
*/
|
||||
cancelUpload: function($a) {
|
||||
var self = this,
|
||||
type = $a.attr('class'),
|
||||
type = $a.data('type'),
|
||||
$form = $a.closest('form');
|
||||
var $input = $form.find('input[name="' + type + '"]');
|
||||
var form_target = $input.closest('form').attr('target');
|
||||
|
@ -452,10 +451,8 @@ import "sumo/js/kbox";
|
|||
self.$modal.find('.metadata').hide();
|
||||
// Clean up all the preview and progress information.
|
||||
self.$modal.find('.progress,.preview').hideFade();
|
||||
self.$modal.find('.preview.row-right').html('');
|
||||
self.$modal.find('.progress.row-right span').html('');
|
||||
// Show all the file inputs with default messages.
|
||||
$uploads.filter('.row-right').each(function () {
|
||||
$uploads.each(function () {
|
||||
var $input = $(this).find('input[type="file"]'),
|
||||
type = $input.attr('name');
|
||||
$input.closest('form')[0].reset();
|
||||
|
@ -478,7 +475,7 @@ import "sumo/js/kbox";
|
|||
return true;
|
||||
}
|
||||
|
||||
var kbox = $('#gallery-upload-modal').kbox({preClose: preClose});
|
||||
var kbox = $('#gallery-upload-modal').kbox({preClose: preClose, position: 'none'});
|
||||
|
||||
// Open modal window from media page
|
||||
if (document.location.hash === '#upload' ||
|
||||
|
|
|
@ -70,8 +70,10 @@
|
|||
|
||||
var TEMPLATE = (
|
||||
'<div class="kbox-container">' +
|
||||
'<a href="#close" class="kbox-close">✖</a>' +
|
||||
'<div class="kbox-header">' +
|
||||
'<div class="kbox-title"></div>' +
|
||||
'<a href="#close" class="kbox-close">✖</a>' +
|
||||
'</div>' +
|
||||
'<div class="kbox-wrap"><div class="kbox-placeholder"/></div>' +
|
||||
'</div>'
|
||||
),
|
||||
|
@ -214,8 +216,7 @@ KBox.prototype = {
|
|||
}
|
||||
},
|
||||
setPosition: function (position) {
|
||||
var self = this,
|
||||
toX, toY, $parent, parentOffset, minX, minY, scrollL, scrollT;
|
||||
var self = this;
|
||||
if (!position) {
|
||||
position = self.options.position;
|
||||
}
|
||||
|
|
|
@ -111,10 +111,7 @@ jQuery.fn.ajaxSubmitInput = function (options) {
|
|||
$form = '<form class="upload-input" action="' +
|
||||
options.url + '" target="' + iframeName +
|
||||
'" method="post" enctype="multipart/form-data"/>',
|
||||
$iframe = $('<iframe hidden name="' + iframeName +
|
||||
'" style="position:absolute;top:-9999px;" />')
|
||||
//'" style="position:fixed;top:0px;width:500px;height:350px" />')
|
||||
.appendTo('body'),
|
||||
$iframe = $(`<iframe hidden name="${iframeName}" />`).appendTo('body'),
|
||||
passJSON;
|
||||
|
||||
if (options.accept) {
|
||||
|
|
|
@ -118,7 +118,9 @@ $(function () {
|
|||
ev.preventDefault();
|
||||
var imgUrl = $(this).attr('href'),
|
||||
image = new Image(),
|
||||
html = '<div><img class="loading" /></div>',
|
||||
currentPosX = window.scrollX,
|
||||
currentPosY = window.scrollY,
|
||||
html = '<img class="loading image-attachment" />',
|
||||
kbox = new KBox(html, {
|
||||
modal: true,
|
||||
title: gettext('Image Attachment'),
|
||||
|
@ -126,44 +128,20 @@ $(function () {
|
|||
destroy: true,
|
||||
position: 'none', // Disable automatic positioning
|
||||
closeOnOutClick: true,
|
||||
closeOnEsc: true
|
||||
closeOnEsc: true,
|
||||
preClose: function () {
|
||||
window.scroll(currentPosX, currentPosY);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
kbox.open();
|
||||
|
||||
let $img = $('#image-attachment-kbox img');
|
||||
let $container = $('#image-attachment-kbox');
|
||||
function setDimensions() {
|
||||
// Calculate maximum dimensions based on 80% viewport size
|
||||
let maxWidth = $(window).width() * 0.8;
|
||||
let maxHeight = $(window).height() * 0.8;
|
||||
let imgWidth = image.width;
|
||||
let imgHeight = image.height;
|
||||
|
||||
|
||||
// Calculate the aspect ratio
|
||||
let aspectRatio = imgWidth / imgHeight;
|
||||
|
||||
// Resize the image maintaining the aspect ratio
|
||||
if (imgWidth > maxWidth || imgHeight > maxHeight) {
|
||||
if (imgWidth / maxWidth > imgHeight / maxHeight) {
|
||||
imgWidth = maxWidth;
|
||||
imgHeight = maxWidth / aspectRatio;
|
||||
} else {
|
||||
imgHeight = maxHeight;
|
||||
imgWidth = maxHeight * aspectRatio;
|
||||
}
|
||||
}
|
||||
|
||||
$img.width(imgWidth);
|
||||
$img.height(imgHeight);
|
||||
$container.css({
|
||||
'width': imgWidth,
|
||||
'overflow': 'hidden'
|
||||
});
|
||||
function loadImage() {
|
||||
$img.removeClass('loading').attr('src', imgUrl);
|
||||
kbox.setPosition('center'); // Center the modal after resizing
|
||||
window.scroll({top: 0});
|
||||
}
|
||||
image.onload = setDimensions;
|
||||
image.onload = loadImage;
|
||||
image.src = imgUrl;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,4 +6,16 @@
|
|||
.off {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.preview-image {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
max-width: 300px;
|
||||
max-height: 300px;
|
||||
img.preview {
|
||||
max-width: 300px;
|
||||
max-height: 300px;
|
||||
object-fit: scale-down;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,9 +30,7 @@
|
|||
|
||||
.kbox-close {
|
||||
font-size: 22px !important;
|
||||
position: absolute;
|
||||
right: p.$spacing-sm;
|
||||
top: 5px;
|
||||
@include p.bidi(((margin, 0 p.$spacing-sm 0 0, 0 0 0 p.$spacing-sm),));
|
||||
|
||||
&:link,
|
||||
&:visited,
|
||||
|
@ -50,17 +48,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
.kbox-title {
|
||||
@include c.text-display-sm;
|
||||
font-weight: bold;
|
||||
color: var(--color-heading);
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: p.$spacing-xl p.$spacing-xl 0;
|
||||
.kbox-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.kbox-title {
|
||||
@include c.text-display-sm;
|
||||
font-weight: bold;
|
||||
color: var(--color-heading);
|
||||
margin: 0;
|
||||
padding: p.$spacing-xl p.$spacing-xl 0;
|
||||
}
|
||||
}
|
||||
|
||||
.kbox-wrap {
|
||||
padding: p.$spacing-xl;
|
||||
padding: p.$spacing-lg;
|
||||
|
||||
.hide-until-expanded {
|
||||
display: block;
|
||||
|
@ -69,18 +71,57 @@
|
|||
|
||||
#kbox-overlay {
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 98;
|
||||
}
|
||||
|
||||
#upload-kbox {
|
||||
top: 10%;
|
||||
left: 50%;
|
||||
margin: 0 10px;
|
||||
top: 10vh;
|
||||
max-width: 580px;
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
transform: translateX(-50%);
|
||||
padding: p.$spacing-sm;
|
||||
box-sizing: content-box;
|
||||
width: 80%;
|
||||
height: auto;
|
||||
max-width: 560px;
|
||||
@media screen and (max-width: p.$screen-sm) {
|
||||
max-width: 96%;
|
||||
}
|
||||
@media screen and (max-width: p.$screen-xs) {
|
||||
max-width: 96%;
|
||||
}
|
||||
}
|
||||
|
||||
#image-attachment-kbox {
|
||||
top: 10%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
padding: p.$spacing-sm;
|
||||
box-sizing: content-box;
|
||||
width: 70%;
|
||||
max-width: 70%;
|
||||
height: auto;
|
||||
@media screen and (max-width: p.$screen-sm) {
|
||||
width: 96%;
|
||||
max-width: 96%;
|
||||
}
|
||||
@media screen and (max-width: p.$screen-xs) {
|
||||
width: 96%;
|
||||
max-width: 96%;
|
||||
}
|
||||
|
||||
.kbox-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
padding: p.$spacing-sm;
|
||||
img.image-attachment {
|
||||
object-fit: scale-down;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче