var newFiles = {}; var sl = {}; function checkAll(el) { const objectKey = el.dataset.objectKey; sl[objectKey] = []; all('#' + objectKey + ' .file-img [data-del]', e => { e.checked = el.checked === true; if (el.checked) { if (e.dataset.del) { sl[objectKey].push(e.dataset.del); } e.parentNode.addClass('checked'); } else { e.parentNode.removeClass('checked'); } }) updateActionButtons(objectKey); } function checkSingle(e) { const objectKey = e.dataset.objectKey; sl[objectKey] = sl[objectKey] || []; if (e.checked) { if (e.dataset.del) { sl[objectKey].push(e.dataset.del); } e.parentNode.addClass('checked'); } else { one('#' + e.dataset.objectKey + ' .all-files input').checked = false; e.parentNode.removeClass('checked'); if (e.dataset.del) { const f = sl[objectKey].indexOf(e.dataset.del); sl[objectKey].splice(f, 1); } } updateActionButtons(objectKey); } function updateActionButtons(id) { let checkedCounter = 0; let checkedCounterUploaded = 0; all('#' + id + ' .file-img input', c => { if (c.checked === true) checkedCounter++; if (c.checked === true && c.dataset.del) checkedCounterUploaded++; }) const btnDelete = one('#' + id + ' .btnDelete'); const delCount = one('#' + id + ' .delCount'); const btnEdit = one('#' + id + ' .btnEdit'); if (btnDelete) { if (checkedCounter > 0) { btnDelete.removeClass('disabled'); delCount.innerHTML = '(' + checkedCounter + ')' } else { btnDelete.addClass('disabled'); delCount.innerHTML = '(0)' } } if (btnEdit) { if (checkedCounterUploaded === 1) { btnEdit.removeClass('disabled'); } else { btnEdit.addClass('disabled'); } } } function addFileImage(e) { const max_file_size = one('#' + e.dataset.objectKey + ' .max_file_size').value; const error_message = one('#' + e.dataset.objectKey + ' .error_message').value; const file = document.createElement('input'); let filesContainer = one('#' + e.dataset.objectKey + ' .files-container'); newFiles[e.dataset.objectKey] = newFiles[e.dataset.objectKey] || []; file.type = 'file'; file.name = e.dataset.objectKey file.multiple = !e.dataset.singleFile; //file.accept = 'image/jpeg, image/png' file.click(); file.addEventListener('change', function () { var cIndex = 0; for (let i = 0; i < this.files.length; i++) { const f = this.files[i]; if (f.size > max_file_size * (1024 * 1024)) { flash.error(error_message); } else if(f.type !== 'image/jpeg' && f.type !== 'image/jpg' && f.type !== 'image/png') { flash.error('Позволените формати са jpeg и png') } else { filesContainer.style.display = 'flex'; const fileContainer = one('file-img', filesContainer); const imgId = e.dataset.objectKey + '_' + cIndex; cIndex++; const img = new Image(); img.src = URL.createObjectURL(f); img.id = imgId; const check = document.createElement('input') check.type = 'checkbox'; check.setAttribute('data-del', ''); check.setAttribute('data-id', imgId); check.setAttribute('data-object-key', e.dataset.objectKey) check.addEventListener('click', e => { checkSingle(check); }) fileContainer.appendChild(img); fileContainer.appendChild(check); one('crops', fileContainer); const progress = one('progress', fileContainer); img.addEventListener('load', function () { fileContainer.addClass('visible'); check.focus(); }); img.addEventListener('click', () => { editSingleFileImage(img); }) orderItem(fileContainer, function (img_id, order_index) { newFiles[img_id][3] = order_index.toString(); }) newFiles[imgId] = [f, progress, e.dataset.objectKey, fileContainer.dataset.index, check]; if (e.dataset.singleFile) { e.addClass('disabled'); } } } uploadAllFilesByAttach(e.dataset.objectKey, cIndex, e.dataset.editMode); }); } function removeFileImage(el) { let checkedCounter = 0; let forDelete = []; all('#' + el.dataset.objectKey + ' .file-img input', c => { if (c.checked === true) { checkedCounter++; forDelete.push(c); } }); let message = ''; if (checkedCounter > 1) { message = 'Сигурни ли сте, че истате да премахнете тези ' + checkedCounter + ' изображения'; } else { message = 'Сигурни ли сте, че искате да премахнете 1 изображение'; } modal.confirm(message, function () { forDelete.forEach(fd => { fd.parentNode.remove(); delete newFiles[fd.dataset.id]; }); el.querySelector('.delCount').innerHTML = '(0)'; el.addClass('disabled'); one('#' + el.dataset.objectKey + ' .btnEdit').addClass('disabled'); if (sl[el.dataset.objectKey].length > 0) { let del_ids = JSON.stringify(sl[el.dataset.objectKey]); request({ url: '/delete-file-cms/', post: { del_ids: del_ids }, done: r => { if (r.success) { flash.success(r.success, true); } } }); } const addButton = one('#' + el.dataset.objectKey + ' [data-single-file]'); if (all('#' + el.dataset.objectKey + ' .file-img input').length === 0) { one('#' + el.dataset.objectKey + ' .files-container').style.display = 'none'; if (addButton.dataset.singleFile) { addButton.removeClass('disabled'); } } one('#' + el.dataset.objectKey + ' .all-files input').checked = false; }) } function uploadAllFilesByAttach(object_key, for_upload, editMode) { console.log(newFiles); const newFilesIds = Object.keys(newFiles), media_key = one('[name="media_key"]').value, model_class = one('[name="model_class"]').value, model_id = one('[name="model_id"]').values if (newFilesIds.length > 0) { var cc = 0; all(`#${object_key} .file-img`).forEach(e => { e.addClass('no-events'); }) newFilesIds.forEach(id => { if (newFiles[id][5] === undefined) { const f = newFiles[id][0]; const progressBar = newFiles[id][1]; const object_key = newFiles[id][2]; const order_index = newFiles[id][3]; const check = newFiles[id][4]; let formData = new FormData(); console.log(object_key); formData.append('media_key', media_key); formData.append('model_class', model_class); formData.append('object_key', object_key); formData.append('order_index', order_index); formData.append('model_id', model_id); formData.append(id, f); if (editMode) { formData.append('has_article', 1) } request({ url: '/upload-file-cms/', post: formData, progress: percentage => { if (progressBar) { progressBar.style.width = percentage + '%' if (percentage < 100) { progressBar.parentNode.addClass('disabled') } else { if (progressBar) { if (progressBar.parentNode) progressBar.parentNode.removeClass('disabled') progressBar.remove() } } } }, done: data => { check.setAttribute('data-del', data.id); check.setAttribute('data-file-type', data.fileType) check.setAttribute('data-src-raw', data.srcRaw) check.setAttribute('data-media-key', data.mediaKey) check.setAttribute('data-file-name', data.fileName) check.setAttribute('data-crop-files', '[]') newFiles[id][5] = 'uploaded'; cc++ if (for_upload === cc) { all(`#${object_key} .file-img`).forEach(e => { e.removeClass('disabled'); e.removeClass('no-events'); }) } } }) } }); } } function editSingleFileImage(e) { const check = e.parentNode.querySelector('input'); editFileSelectedImage(check, check.dataset.objectKey) } function editFileImage(e) { const check = one('#' + e.dataset.objectKey + ' .file-img input:checked'); editFileSelectedImage(check, e.dataset.objectKey) } function editFileSelectedImage(check, objectKey) { const bufferFiles = {}; const allowed_resolutions = JSON.parse(one('#' + objectKey + ' .allowed_resolutions').value); const cropFiles = JSON.parse(check.dataset.cropFiles); const img = document.createElement('img'); img.src = check.dataset.srcRaw; img.style.height = '100%'; img.style.width = 'auto'; let aspectRation = 1; let rez = '1:1'; if (allowed_resolutions.length > 0) { aspectRation = allowed_resolutions[0][0] / allowed_resolutions[0][1]; rez = allowed_resolutions[0][0] + ':' + allowed_resolutions[0][1]; } const cropContainer = document.createElement('div'); cropContainer.addClass('crop-container'); const cropImgContainer = one('crop-container-img', cropContainer); const cropsContainer = one('crops-container', cropContainer); const select = document.createElement('select'); cropImgContainer.addClass('invisible') const options = []; allowed_resolutions.forEach(r => { options.push(''); }); select.innerHTML = options.join(''); cropsContainer.innerHTML = ''; select.addEventListener('change', function () { cropper.setAspectRatio(parseFloat(this.value)); const s = select.querySelector('option[value="' + this.value + '"]'); rez = s.dataset.rez; }); cropsContainer.appendChild(select); const cropBtn = one('btn-ib btn-default', cropsContainer); cropBtn.innerHTML = ' Изрежи'; cropImgContainer.appendChild(img); const cropsImgContainer = one('crops-img-container', cropsContainer); cropsContainer.addClass('disabled'); const cropper = new Cropper(img, { autoCrop: false, aspectRatio: aspectRation, viewMode: 0, ready() { this.cropper.crop(); cropImgContainer.removeClass('invisible') cropImgContainer.removeClass('invisible') cropsContainer.removeClass('disabled') }, }); cropBtn.addEventListener('click', function () { const modalBtnConfirm = one('.modal-button-confirm'); modalBtnConfirm.removeClass('disabled'); const existCrop = one('[data-row-rez="' + rez + '"]'); if (existCrop) { if (existCrop.querySelector('img')) existCrop.querySelector('img').remove(); if (existCrop.querySelector('canvas')) existCrop.querySelector('canvas').remove(); const canvas = cropper.getCroppedCanvas(); existCrop.prepend(canvas); canvas.toBlob(function (blob) { bufferFiles[rez] = new File([blob], check.dataset.fileName, {type: check.dataset.fileType}); }, check.dataset.fileType, 0.5) } else { createCanvasCropRow(cropper, cropsImgContainer, rez, canvas => { canvas.toBlob(function (blob) { bufferFiles[rez] = new File([blob], check.dataset.fileName, {type: check.dataset.fileType}); }, check.dataset.fileType, 0.5) }, del_rez => { delete bufferFiles[rez]; if (Object.keys(bufferFiles).length === 0) { modalBtnConfirm.addClass('disabled'); } }) } }); Object.keys(cropFiles).forEach(k => { createImageCropRow(cropFiles[k], cropsImgContainer, k, check); }) modal.confirm(cropContainer, () => { const keyRez = Object.keys(bufferFiles); check.checked = false; check.parentNode.removeClass('checked'); updateActionButtons(check.dataset.objectKey); const form = one('form'); form.addClass('form-wait'); const waitingType = !one('.waiting-tape') ? one('waiting-tape', document.body) : null; const fd = new FormData(); fd.append('object_key', check.dataset.objectKey); fd.append('media_key', check.dataset.mediaKey); fd.append('file_name', check.dataset.fileName); fd.append('resolutions', JSON.stringify(keyRez)); keyRez.forEach(rez => { const file = bufferFiles[rez]; fd.append(rez, file); }); request({ url: '/upload-crop/', post: fd, done: r => { if (r.resolutions) { const crops = check.parentNode.querySelector('.crops'); crops.innerHTML = ''; r.resolutions.forEach(rez => { const cr = document.createElement('span'); cr.innerHTML = rez; crops.appendChild(cr); }) } if (r.files) { check.setAttribute('data-crop-files', JSON.stringify(r.files)) } form.removeClass('form-wait'); waitingType.remove(); flash.success('Изображението с резолюцията ' + keyRez.join(', ') + ' е актуализирано успешно', true); } }) }, () => { }, { width: '80%', height: '75%' }, () => { const modalBtnConfirm = one('.modal-button-confirm'); modalBtnConfirm.addClass('disabled'); } ); } function createCanvasCropRow(cropper, cropsImgContainer, rez, callback, callbackDel) { const canvas = cropper.getCroppedCanvas(); const cropsImgRow = one('crops-img-row', cropsImgContainer); const cropsImgRez = one('crops-img-rez', cropsImgRow); cropsImgRez.innerHTML = rez; const cropsImgDel = one('crops-img-del btn-ib btn-default', cropsImgRow); cropsImgDel.innerHTML = ''; cropsImgDel.title = 'Изтрий резолюцията'; cropsImgDel.addEventListener('click', function () { cropsImgDel.parentNode.remove(); callbackDel(rez); flash.success('Резолюцията е изтрита'); }) cropsImgRow.prepend(canvas); cropsImgRow.setAttribute('data-row-rez', rez); callback(canvas); } function createImageCropRow(src, cropsImgContainer, rez, check) { const img = new Image(); img.src = src + '?t=' + (new Date().getTime()); const cropsImgRow = one('crops-img-row', cropsImgContainer); const cropsImgRez = one('crops-img-rez', cropsImgRow); cropsImgRez.innerHTML = rez; const cropsImgDel = one('crops-img-del btn-ib btn-default', cropsImgRow); cropsImgDel.innerHTML = ''; cropsImgDel.title = 'Изтрий резолюцията'; cropsImgDel.addEventListener('click', function () { cropsImgDel.parentNode.remove(); request({ url: '/delete-crop/', post: { del_id: check.dataset.del, rez: rez }, done: r => { if (r.resolutions) { const crops = check.parentNode.querySelector('.crops'); crops.innerHTML = ''; r.resolutions.forEach(rez => { const cr = document.createElement('span'); cr.innerHTML = rez; crops.appendChild(cr); }) } if (r.files) { check.setAttribute('data-crop-files', JSON.stringify(r.files)) } flash.success('Резолюцията е изтрита', true); } }) }) cropsImgRow.prepend(img); cropsImgRow.setAttribute('data-row-rez', rez); } //region [ORDER] orderItems('.file-img', '/update-file-indexes/'); //endregion