mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
N°2844 - Fix image attribute display and editing
This commit is contained in:
@@ -2099,16 +2099,13 @@ EOF
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/edit_image.js');
|
||||
$oDocument = $value; // Value is an ormDocument objectm
|
||||
$sDefaultUrl = $oAttDef->Get('default_image');
|
||||
if (is_object($oDocument) && !$oDocument->IsEmpty())
|
||||
{
|
||||
if (is_object($oDocument) && !$oDocument->IsEmpty()) {
|
||||
$sUrl = 'data:'.$oDocument->GetMimeType().';base64,'.base64_encode($oDocument->GetData());
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$sUrl = null;
|
||||
}
|
||||
|
||||
$sHTMLValue = "<div class=\"field_input_zone field_input_image\"><div id=\"edit_$iInputId\" class=\"edit-image\"></div></div>\n";
|
||||
$sHTMLValue = "<div class=\"field_input_zone ibo-input-image-wrapper\"><div id=\"edit_$iInputId\" class=\"ibo-input-image\"></div></div>\n";
|
||||
$sHTMLValue .= "{$sValidationSpan}{$sReloadSpan}\n";
|
||||
|
||||
$aEditImage = array(
|
||||
|
||||
@@ -8112,10 +8112,10 @@ class AttributeImage extends AttributeBlob
|
||||
$sRet = $this->GetHtmlForImageUrl($sCustomImageUrl, $iMaxWidthPx, $iMaxHeightPx);
|
||||
}
|
||||
|
||||
$sCssClasses = 'view-image attribute-image';
|
||||
$sCssClasses = 'ibo-input-image--image-view attribute-image';
|
||||
$sCssClasses .= ' '.(($bIsCustomImage) ? 'attribute-image-custom' : 'attribute-image-default');
|
||||
|
||||
return '<div class="'.$sCssClasses.'" style="width: '.$iMaxWidthPx.'; height: '.$iMaxHeightPx.';"><span class="helper-middle"></span>'.$sRet.'</div>';
|
||||
return '<div class="'.$sCssClasses.'" style="width: '.$iMaxWidthPx.'; height: '.$iMaxHeightPx.';">'.$sRet.'</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -229,7 +229,7 @@ EOF
|
||||
$sUrl = 'data:'.$value->GetMimeType().';base64,'.base64_encode($value->GetData());
|
||||
}
|
||||
$sRet = ($sUrl !== null) ? '<img src="'.$sUrl.'" style="width: '.$iNewWidth.'px; height: '.$iNewHeight.'px">' : '';
|
||||
$sRet = '<div class="view-image">'.$sRet.'</div>';
|
||||
$sRet = '<div class="ibo-input-image--image-view">'.$sRet.'</div>';
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
*/
|
||||
|
||||
@import "input";
|
||||
@import "input-select";
|
||||
@import "input-checkbox";
|
||||
@import "input-date";
|
||||
@import "input-datetime";
|
||||
@import "input-duration";
|
||||
@import "input-image";
|
||||
@import "input-select";
|
||||
@import "input-select-icon";
|
||||
@import "input-string";
|
||||
@import "input-tagset";
|
||||
|
||||
45
css/backoffice/components/input/_input-image.scss
Normal file
45
css/backoffice/components/input/_input-image.scss
Normal file
@@ -0,0 +1,45 @@
|
||||
/*!
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
.ibo-input-image {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.ibo-input-image--image-view {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background-color: $ibo-color-grey-200;
|
||||
border-radius: $ibo-border-radius-500;
|
||||
@extend %ibo-fully-centered-content;
|
||||
|
||||
img[src=""],
|
||||
img[src="null"] {
|
||||
// Hiding "broken" image when src is not set
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
input[type="file"] {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-input-image--edit-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: 0.5rem;
|
||||
|
||||
// Overload original siblings rule as buttons are displayed vertically
|
||||
.ibo-button + .ibo-button {
|
||||
margin-top: 0.5rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
@@ -154,60 +154,6 @@
|
||||
// color: $text-color;
|
||||
//}
|
||||
|
||||
.edit-image {
|
||||
.view-image {
|
||||
display: inline-block;
|
||||
|
||||
img[src=""],
|
||||
img[src="null"] {
|
||||
// Hiding "broken" image when src is not set
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&.dirty {
|
||||
// The image will be modified when saving the changes
|
||||
|
||||
&.compat {
|
||||
// Browser not supporting FileReader
|
||||
background-image: url($approot-relative + "css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=" + $version);
|
||||
|
||||
img {
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.edit-buttons {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-top: 4px;
|
||||
margin-left: 3px;
|
||||
|
||||
.button {
|
||||
cursor: pointer;
|
||||
margin-bottom: 3px;
|
||||
padding: 2px;
|
||||
background-color: $highlight-color;
|
||||
|
||||
&.disabled {
|
||||
cursor: default;
|
||||
background-color: $grey-color;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.ui-icon {
|
||||
background-image: url($approot-relative + "css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=" + $version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-input {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
/* Center the image both horizontally and vertically, withing a box which size is fixed (depends on the attribute definition) */
|
||||
.details .view-image {
|
||||
text-align: center;
|
||||
|
||||
220
js/edit_image.js
220
js/edit_image.js
@@ -27,108 +27,10 @@ $(function()
|
||||
|
||||
// the constructor
|
||||
_create: function () {
|
||||
var me = this;
|
||||
me.bLoadedEmpty = (me.options.current_image_url == '' || me.options.current_image_url == null);
|
||||
this.element.addClass('ibo-input-image');
|
||||
|
||||
var sMarkup = '';
|
||||
sMarkup += '<input type="hidden" id="do_remove_' + me.options.input_name + '" name="' + me.options.input_name + '[remove]" value="0"/>';
|
||||
|
||||
var sCssClasses = "view-image attribute-image";
|
||||
console.debug("edit_image", me.options.current_image_url);
|
||||
var sCssClassToAdd, sImageUrl;
|
||||
if (me.options.current_image_url === null)
|
||||
{
|
||||
sCssClassToAdd = "attribute-image-default";
|
||||
sImageUrl = me.options.default_image_url;
|
||||
}
|
||||
else
|
||||
{
|
||||
sCssClassToAdd = "attribute-image-custom";
|
||||
sImageUrl = me.options.current_image_url;
|
||||
}
|
||||
sCssClasses += ' '+sCssClassToAdd;
|
||||
sMarkup += '<div id="preview_'+me.options.input_name+'" class="'+sCssClasses+'" style="width: '+me.options.max_width_px+'px; height: '+me.options.max_height_px+'px;">';
|
||||
|
||||
sMarkup += '<span class="helper-middle"></span>';
|
||||
sMarkup += '<img src="'+sImageUrl+'" data-original-src="'+sImageUrl+'" data-default-src="'+me.options.default_image_url+'" style="max-width: '+me.options.max_width_px+'px; max-height: '+me.options.max_height_px+'px">';
|
||||
sMarkup += '</div>';
|
||||
sMarkup += '<div id="buttons_' + me.options.input_name + '" class="edit-buttons">';
|
||||
sMarkup += '<div title="' + me.options.labels.reset_button + '" id="reset_' + me.options.input_name + '" class="button disabled"><div class="ui-icon ui-icon-arrowreturnthick-1-w"></div></div>';
|
||||
|
||||
var sDisabled = me.bLoadedEmpty ? 'disabled' : '';
|
||||
var sLoadedDisabled = me.bLoadedEmpty ? 'yes' : 'no';
|
||||
sMarkup += '<div title="' + me.options.labels.remove_button + '" id="remove_' + me.options.input_name + '" data-loaded-disabled="' + sLoadedDisabled + '" class="button ' + sDisabled + '"><div class="ui-icon ui-icon-trash"></div></div>';
|
||||
sMarkup += '</div>';
|
||||
|
||||
sMarkup += '<input type="hidden" name="MAX_FILE_SIZE" value="'+me.options.max_file_size+'" />';
|
||||
sMarkup += '<input class="file-input" title="' + me.options.labels.upload_button + '" name="' + me.options.input_name + '[fcontents]" type="file" id="file_' + me.options.input_name + '" />';
|
||||
|
||||
this.element
|
||||
.addClass('edit-image')
|
||||
.append(sMarkup);
|
||||
|
||||
$('#file_' + me.options.input_name).change(function () {
|
||||
|
||||
$('#do_remove_' + me.options.input_name).val('0');
|
||||
|
||||
me.previewImage(this, '#preview_' + me.options.input_name + ' img');
|
||||
|
||||
var oImage = $('#preview_' + me.options.input_name + ' img');
|
||||
oImage.closest('.view-image').addClass('dirty');
|
||||
|
||||
$('#reset_' + me.options.input_name).removeClass('disabled');
|
||||
$('#remove_' + me.options.input_name).removeClass('disabled');
|
||||
});
|
||||
$('#reset_' + me.options.input_name).click(function () {
|
||||
|
||||
if ($(this).hasClass('disabled')) return;
|
||||
|
||||
$('#do_remove_' + me.options.input_name).val('0');
|
||||
|
||||
// Restore the image
|
||||
var oImage = $('#preview_' + me.options.input_name + ' img');
|
||||
oImage.attr('src', oImage.attr('data-original-src'));
|
||||
oImage.closest('.view-image').removeClass('dirty').removeClass('compat');
|
||||
|
||||
// Reset the file input without losing events bound to it
|
||||
var oInput = $('#file_' + me.options.input_name);
|
||||
oInput.replaceWith(oInput.val('').clone(true));
|
||||
|
||||
$('#reset_' + me.options.input_name).addClass('disabled');
|
||||
var oRemoveBtn = $('#remove_' + me.options.input_name);
|
||||
if (oRemoveBtn.attr('data-loaded-disabled') == 'yes') {
|
||||
oRemoveBtn.addClass('disabled');
|
||||
}
|
||||
else {
|
||||
oRemoveBtn.removeClass('disabled');
|
||||
}
|
||||
});
|
||||
$('#remove_' + me.options.input_name).click(function () {
|
||||
|
||||
if ($(this).hasClass('disabled')) return;
|
||||
|
||||
$('#do_remove_' + me.options.input_name).val('1');
|
||||
|
||||
// Restore the default image
|
||||
var oImage = $('#preview_' + me.options.input_name + ' img');
|
||||
oImage.attr('src', oImage.attr('data-default-src'));
|
||||
oImage.closest('.view-image')
|
||||
.removeClass('compat')
|
||||
.addClass('dirty');
|
||||
|
||||
// Reset the file input without losing events bound to it
|
||||
var oInput = $('#file_' + me.options.input_name);
|
||||
oInput.replaceWith(oInput.val('').clone(true));
|
||||
|
||||
var oRemoveBtn = $('#remove_' + me.options.input_name);
|
||||
if (oRemoveBtn.attr('data-loaded-disabled') == 'yes') {
|
||||
$('#reset_' + me.options.input_name).addClass('disabled');
|
||||
}
|
||||
else {
|
||||
$('#reset_' + me.options.input_name).removeClass('disabled');
|
||||
}
|
||||
oRemoveBtn.addClass('disabled');
|
||||
});
|
||||
this._buildMarkup();
|
||||
this._bindEvents();
|
||||
},
|
||||
// called when created, and later when changing options
|
||||
_refresh: function () {
|
||||
@@ -136,7 +38,7 @@ $(function()
|
||||
// events bound via _bind are removed automatically
|
||||
// revert other modifications here
|
||||
_destroy: function () {
|
||||
this.element.removeClass('edit-image');
|
||||
this.element.removeClass('ibo-input-image');
|
||||
},
|
||||
// _setOptions is called with a hash of all options that are changing
|
||||
_setOptions: function () {
|
||||
@@ -146,6 +48,114 @@ $(function()
|
||||
_setOption: function (key, value) {
|
||||
this._superApply(arguments);
|
||||
},
|
||||
|
||||
_buildMarkup: function () {
|
||||
CombodoJSConsole.Debug('edit_image: '+this.options.current_image_url);
|
||||
|
||||
this.bLoadedEmpty = (this.options.current_image_url == '' || this.options.current_image_url == null);
|
||||
|
||||
const sDisabled = this.bLoadedEmpty ? 'disabled' : '';
|
||||
const sLoadedDisabled = this.bLoadedEmpty ? 'yes' : 'no';
|
||||
const sUploadButtonTooltipAttribute = this.options.labels.upload_button !== '' ? 'data-tooltip-content="'+this.options.labels.upload_button+'"' : '';
|
||||
let sCssClasses = "ibo-input-image--image-view attribute-image";
|
||||
let sCssClassToAdd, sImageUrl;
|
||||
|
||||
if (this.options.current_image_url === null) {
|
||||
sCssClassToAdd = "attribute-image-default";
|
||||
sImageUrl = this.options.default_image_url;
|
||||
} else {
|
||||
sCssClassToAdd = "attribute-image-custom";
|
||||
sImageUrl = this.options.current_image_url;
|
||||
}
|
||||
sCssClasses += ' '+sCssClassToAdd;
|
||||
|
||||
let sMarkup = `
|
||||
<input type="hidden" id="do_remove_${this.options.input_name}" name="${this.options.input_name}[remove]" value="0"/>
|
||||
<div id="preview_${this.options.input_name}" class="${sCssClasses}" data-role="ibo-input-image--image-view" style="width: ${this.options.max_width_px}px; min-width: ${this.options.max_width_px}px; height: ${this.options.max_height_px}px;" min-height: ${this.options.max_height_px}px;">
|
||||
<img src="${sImageUrl}" data-original-src="${sImageUrl}" data-default-src="${this.options.default_image_url}" style="max-width: ${this.options.max_width_px}px; max-height: ${this.options.max_height_px}px">
|
||||
<input id="file_${this.options.input_name}" name="${this.options.input_name}[fcontents]" type="file" ${sUploadButtonTooltipAttribute} />
|
||||
</div>
|
||||
<div id="buttons_${this.options.input_name}" class="ibo-input-image--edit-buttons" data-role="ibo-input-image--edit-buttons">
|
||||
<button id="reset_${this.options.input_name}" class="ibo-button ibo-is-alternative ibo-is-neutral" data-role="ibo-button" type="button" data-tooltip-content="${this.options.labels.reset_button}" data-tooltip-placement="right" disabled>
|
||||
<span class="fas fa-undo-alt"></span>
|
||||
</button>
|
||||
<button id="remove_${this.options.input_name}" class="ibo-button ibo-is-alternative ibo-is-danger" data-role="ibo-button" type="button" data-tooltip-content="${this.options.labels.remove_button}" data-tooltip-placement="right" data-loaded-disabled="${sLoadedDisabled}" ${sDisabled}>
|
||||
<span class="fas fa-trash"></span>
|
||||
</button>
|
||||
</div>
|
||||
<input type="hidden" name="MAX_FILE_SIZE" value="${this.options.max_file_size}" />
|
||||
`;
|
||||
|
||||
this.element.append(sMarkup);
|
||||
|
||||
CombodoGlobalToolbox.InitAllNonInstantiatedTooltips(this.element);
|
||||
},
|
||||
_bindEvents: function () {
|
||||
const me = this;
|
||||
|
||||
$('#file_'+me.options.input_name).change(function () {
|
||||
$('#do_remove_'+me.options.input_name).val('0');
|
||||
|
||||
me.previewImage(this, '#preview_'+me.options.input_name+' img');
|
||||
|
||||
let oImage = $('#preview_'+me.options.input_name+' img');
|
||||
oImage.closest('.ibo-input-image--image-view').addClass('dirty');
|
||||
|
||||
$('#reset_'+me.options.input_name).prop('disabled', false);
|
||||
$('#remove_'+me.options.input_name).prop('disabled', false);
|
||||
});
|
||||
|
||||
$('#reset_'+me.options.input_name).click(function () {
|
||||
if ($(this).prop('disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$('#do_remove_'+me.options.input_name).val('0');
|
||||
|
||||
// Restore the image
|
||||
let oImage = $('#preview_'+me.options.input_name+' img');
|
||||
oImage.attr('src', oImage.attr('data-original-src'));
|
||||
oImage.closest('.ibo-input-image--image-view').removeClass('dirty');
|
||||
|
||||
// Reset the file input without losing events bound to it
|
||||
let oInput = $('#file_'+me.options.input_name);
|
||||
oInput.replaceWith(oInput.val('').clone(true));
|
||||
|
||||
$('#reset_'+me.options.input_name).prop('disabled', true);
|
||||
let oRemoveBtn = $('#remove_'+me.options.input_name);
|
||||
if (oRemoveBtn.attr('data-loaded-disabled') == 'yes') {
|
||||
oRemoveBtn.prop('disabled', true);
|
||||
} else {
|
||||
oRemoveBtn.prop('disabled', false);
|
||||
}
|
||||
});
|
||||
|
||||
$('#remove_'+me.options.input_name).click(function () {
|
||||
if ($(this).prop('disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$('#do_remove_'+me.options.input_name).val('1');
|
||||
|
||||
// Restore the default image
|
||||
let oImage = $('#preview_'+me.options.input_name+' img');
|
||||
oImage.attr('src', oImage.attr('data-default-src'));
|
||||
oImage.closest('.ibo-input-image--image-view')
|
||||
.addClass('dirty');
|
||||
|
||||
// Reset the file input without losing events bound to it
|
||||
let oInput = $('#file_'+me.options.input_name);
|
||||
oInput.replaceWith(oInput.val('').clone(true));
|
||||
|
||||
let oRemoveBtn = $('#remove_'+me.options.input_name);
|
||||
if (oRemoveBtn.attr('data-loaded-disabled') == 'yes') {
|
||||
$('#reset_'+me.options.input_name).prop('disabled', true);
|
||||
} else {
|
||||
$('#reset_'+me.options.input_name).prop('disabled', false);
|
||||
}
|
||||
oRemoveBtn.prop('disabled', true);
|
||||
});
|
||||
},
|
||||
previewImage: function (input, sImageSelector) {
|
||||
if (input.files && input.files[0]) {
|
||||
if (window.FileReader) {
|
||||
@@ -157,12 +167,6 @@ $(function()
|
||||
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
}
|
||||
else {
|
||||
$(sImageSelector).closest('.view-image').addClass('compat');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$(sImageSelector).closest('.view-image').addClass('compat');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -343,7 +343,7 @@ JS
|
||||
// Make image attributes zoomable
|
||||
$this->add_ready_script(
|
||||
<<<JS
|
||||
$('.view-image img').each(function(){
|
||||
$('.ibo-input-image--image-view img').each(function(){
|
||||
$(this).attr('href', $(this).attr('src'))
|
||||
})
|
||||
.magnificPopup({type: 'image', closeOnContentClick: true });
|
||||
|
||||
Reference in New Issue
Block a user