(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);