(function ($) { 'use strict'; var galleryDefaults = { csrfToken: $('meta[name=csrf-token]').attr('content'), csrfTokenName: $('meta[name=csrf-param]').attr('content'), nameLabel: 'Name', descriptionLabel: 'Description', hasName: true, hasDesc: true, uploadUrl: '', deleteUrl: '', updateUrl: '', arrangeUrl: '', photos: [] }; function galleryManager(el, options) { //Extending options: var opts = $.extend({}, galleryDefaults, options); //code var csrfParams = opts.csrfToken ? '&' + opts.csrfTokenName + '=' + opts.csrfToken : ''; var photos = {}; // photo elements by id var $gallery = $(el); if (!opts.hasName) { if (!opts.hasDesc) { $gallery.addClass('no-name-no-desc'); $('.edit_selected', $gallery).hide(); } else $gallery.addClass('no-name'); } else if (!opts.hasDesc) $gallery.addClass('no-desc'); var $sorter = $('.sorter', $gallery); var $images = $('.images', $sorter); var $editorModal = $('.editor-modal', $gallery); var $progressOverlay = $('.progress-overlay', $gallery); var $uploadProgress = $('.upload-progress', $progressOverlay); var $editorForm = $('.form', $editorModal); function htmlEscape(str) { return String(str) .replace(/&/g, '&') .replace(/"/g, '"') .replace(/'/g, ''') .replace(//g, '>'); } function createEditorElement(id, src, name, description) { var html = '
'; if( typeof src === 'string' || src instanceof String ){ html += '
' + '' + '
'; } html += '
' + (opts.hasName ? '
' + '' + '' + '
' : '') + (opts.hasDesc ? '
' + '' + '' + '
' : '') + '
' + '
'; return $(html); } var photoTemplate = '
' + '
'; if (opts.hasName) { photoTemplate += '
'; } if (opts.hasDesc) { photoTemplate += '

'; } photoTemplate += '
'; if (opts.hasName || opts.hasDesc) { photoTemplate += ' '; } photoTemplate += '' + '
'; function addPhoto(id, src, name, description, rank) { var photo = $(photoTemplate); photos[id] = photo; photo.data('id', id); photo.data('rank', rank); if( typeof src === 'string' || src instanceof String ){ $('img', photo).attr('src', src); }else{ $('.image-preview', photo).css('display', 'none'); $('.caption p', photo).css('height', '9em'); } if (opts.hasName){ // name = ''; $('.caption h5', photo).text(name); } if (opts.hasDesc){ $('.caption p', photo).text(description); } $images.append(photo); return photo; } function editPhotos(ids) { var l = ids.length; var form = $editorForm.empty(); for (var i = 0; i < l; i++) { var id = ids[i]; var photo = photos[id], src = $('img', photo).attr('src'), name = $('.caption h5', photo).text(), description = $('.caption p', photo).text(); form.append(createEditorElement(id, src, name, description)); } if (l > 0){ $editorModal.modal('show'); } } function removePhotos(ids) { $.ajax({ type: 'POST', url: opts.deleteUrl, data: 'id[]=' + ids.join('&id[]=') + csrfParams, success: function (t) { if (t == 'OK') { for (var i = 0, l = ids.length; i < l; i++) { photos[ids[i]].remove(); delete photos[ids[i]]; } } else { alert(t); } } }); } function deleteClick(e) { e.preventDefault(); var photo = $(this).closest('.photo'); var id = photo.data('id'); // here can be question to confirm delete // if (!confirm(deleteConfirmation)) return false; removePhotos([id]); return false; } function editClick(e) { e.preventDefault(); var photo = $(this).closest('.photo'); var id = photo.data('id'); editPhotos([id]); return false; } function updateButtons() { var selectedCount = $('.photo.selected', $sorter).length; $('.select_all', $gallery).prop('checked', $('.photo', $sorter).length == selectedCount); if (selectedCount == 0) { $('.edit_selected, .remove_selected', $gallery).addClass('disabled'); } else { $('.edit_selected, .remove_selected', $gallery).removeClass('disabled'); } } function selectChanged() { var $this = $(this); if ($this.is(':checked')) $this.closest('.photo').addClass('selected'); else $this.closest('.photo').removeClass('selected'); updateButtons(); } function sending(xhr, fd, fixer){ console.log(fixer); if( fixer.CurUploaded <= fixer.MaxUploaded ){ xhr.send(fd); fixer.CurUploaded++; }else{ setTimeout( sending,5000, xhr, fd, fixer); } } $images .on('click', '.photo .deletePhoto', deleteClick) .on('click', '.photo .editPhoto', editClick) .on('click', '.photo .photo-select', selectChanged); $('.images', $sorter).sortable({tolerance: "pointer"}).disableSelection().bind("sortstop", function () { var data = []; $('.photo', $sorter).each(function () { var t = $(this); data.push('order[' + t.data('id') + ']=' + t.data('rank')); }); $.ajax({ type: 'POST', url: opts.arrangeUrl, data: data.join('&') + csrfParams, dataType: "json" }).done(function (data) { for (var id in data[id]) { photos[id].data('rank', data[id]); } // order saved! // we can inform user that order saved }); }); if (window.FormData !== undefined) { // if XHR2 available var uploadFileName = $('.afile', $gallery).attr('name'); var multiUpload = function (files) { if (files.length == 0) return; $progressOverlay.show(); $uploadProgress.css('width', '5%'); var filesCount = files.length; var uploadedCount = 0; var ids = []; var poper = new Map(); var fixer = {MaxUploaded:3, CurUploaded:0, MaxScreen:12}; for (var i = 0; i < filesCount; i++) { var fd = new FormData(); fd.append(uploadFileName, files[i]); if (opts.csrfToken) { fd.append(opts.csrfTokenName, opts.csrfToken); } let xhr = new XMLHttpRequest(); xhr.open('POST', opts.uploadUrl, true); xhr.onload = function () { uploadedCount++; fixer.CurUploaded--; if (this.status == 200) { var resp = JSON.parse(this.response); addPhoto(resp['id'], resp['preview'], '', resp['description'], resp['rank']); ids.push(resp['id']); var poperm = poper.get(resp['name']); poperm.toast('hide'); setTimeout(() => { poperm.remove(); },2000, poperm); } else { // exception !!! } $uploadProgress.css('width', '' + (5 + 95 * uploadedCount / filesCount) + '%'); if (uploadedCount === filesCount) { $uploadProgress.css('width', '100%'); $progressOverlay.hide(); if (opts.hasName || opts.hasDesc) editPhotos(ids); } }; var templ = $("#noty0").clone(); var fname = files[i].name; xhr.nn = fname; $(xhr.upload).bind('progress', function (e) { // xhr.upload.addEventListener("progress", (event) => { let percent = Math.round(event.loaded *100/ event.total); // console.log(xhr.nn); // console.log(xhr); // console.log(percent); var el = poper.get(xhr.nn); el.find(".progress-bar").css("width", percent+"%"); if( percent > 98 ){ el.find(".text-muted").text("Обработка"); } }); templ.find(".toast-body").text(files[i].name); $("#notycont").prepend(templ); templ.toast('show'); poper.set(files[i].name, templ); console.log(fixer); if( fixer.CurUploaded >= fixer.MaxUploaded ){ console.log("pause"); setTimeout( sending,5000, xhr, fd, fixer); }else{ fixer.CurUploaded ++; xhr.send(fd); } } }; (function () { // add drag and drop var el = $gallery[0]; var isOver = false; var lastIsOver = false; setInterval(function () { if (isOver != lastIsOver) { if (isOver) el.classList.add('over'); else el.classList.remove('over'); lastIsOver = isOver } }, 30); function handleDragOver(e) { e.preventDefault(); isOver = true; return false; } function handleDragLeave() { isOver = false; return false; } function handleDrop(e) { e.preventDefault(); e.stopPropagation(); var files = e.dataTransfer.files; multiUpload(files); isOver = false; return false; } function handleDragEnd() { isOver = false; } el.addEventListener('dragover', handleDragOver, false); el.addEventListener('dragleave', handleDragLeave, false); el.addEventListener('drop', handleDrop, false); el.addEventListener('dragend', handleDragEnd, false); })(); $('.afile', $gallery).attr('multiple', 'true').on('change', function (e) { e.preventDefault(); multiUpload(this.files); $(this).val(null); }); } else { $('.afile', $gallery).on('change', function (e) { e.preventDefault(); var ids = []; $progressOverlay.show(); $uploadProgress.css('width', '5%'); var data = {}; if (opts.csrfToken) data[opts.csrfTokenName] = opts.csrfToken; $.ajax({ type: 'POST', url: opts.uploadUrl, data: data, files: $(this), iframe: true, processData: false, dataType: "json" }).done(function (resp) { addPhoto(resp['id'], resp['preview'], '', resp['description'], resp['rank']); ids.push(resp['id']); $uploadProgress.css('width', '100%'); $progressOverlay.hide(); if (opts.hasName || opts.hasDesc) editPhotos(ids); }); }); } $('.save-changes', $editorModal).click(function (e) { e.preventDefault(); $.post(opts.updateUrl, $('input, textarea', $editorForm).serialize() + csrfParams, function (data) { var count = data.length; for (var key = 0; key < count; key++) { var p = data[key]; var photo = photos[p.id]; $('img', photo).attr('src', p['src']); if (opts.hasName) $('.caption h5', photo).text(p['name']); if (opts.hasDesc) $('.caption p', photo).text(p['description']); } $editorModal.modal('hide'); //deselect all items after editing $('.photo.selected', $sorter).each(function () { $('.photo-select', this).prop('checked', false) }).removeClass('selected'); $('.select_all', $gallery).prop('checked', false); updateButtons(); }, 'json'); }); $('.edit_selected', $gallery).click(function (e) { e.preventDefault(); var ids = []; $('.photo.selected', $sorter).each(function () { ids.push($(this).data('id')); }); editPhotos(ids); return false; }); $('.remove_selected', $gallery).click(function (e) { e.preventDefault(); var ids = []; $('.photo.selected', $sorter).each(function () { ids.push($(this).data('id')); }); removePhotos(ids); }); $('.select_all', $gallery).change(function () { if ($(this).prop('checked')) { $('.photo', $sorter).each(function () { $('.photo-select', this).prop('checked', true) }).addClass('selected'); } else { $('.photo.selected', $sorter).each(function () { $('.photo-select', this).prop('checked', false) }).removeClass('selected'); } updateButtons(); }); for (var i = 0, l = opts.photos.length; i < l; i++) { var resp = opts.photos[i]; addPhoto(resp['id'], resp['preview'], resp['name'], resp['description'], resp['rank']); } let selfo = addPhoto; $('.savehtml', $gallery).click(function (e) { slSave($(e.target).attr('rel-mid'),$(e.target).attr('rel-id'), selfo); ids,push($(e.target).attr('rel-id')); }); } // The actual plugin $.fn.galleryManager = function (options) { if (this.length) { this.each(function () { galleryManager(this, options); }); } }; })(jQuery);