/**
* Guess what, Javascript doesn't have .sort() by integer out-of-the-box.
*/
function sortNumber(a, b) {
return parseInt(a) - parseInt(b);
}
function CasImage(element, gallery) {
var image = this;
image.element = element;
image.gallery = gallery;
image.id = image.element.attr("data-id");
image.isSelected = function() {
return image.element.attr("data-selected") == "true";
};
image.markAsSelected = function() {
image.element.attr("data-selected", "true");
};
image.unselect = function() {
image.element.find(".selection").hide();
image.element.attr("data-selected", "false");
image.element.find(".unselected-but-selectable").show();
};
image.toggleSelection = function() {
if (image.isSelected()) {
image.unselect();
} else {
image.markAsSelected();
image.element.find(".unselected-but-selectable").hide();
image.element.find(".selection").show();
}
};
image.showEditOptions = function() {
gallery.element.find(".image .image-options").hide();
image.element.find(".image .image-options").show();
image.markAsSelected();
};
return {
click: function() {
if (image.gallery.isSelectionEnabled) {
image.toggleSelection();
} else {
image.showEditOptions();
}
},
unselect: function() {
if (image.isSelected()) {
image.unselect();
}
},
recordId: function() {
return image.element.data("id");
},
addOrderedInput: function(order) {
if (!image.element.find("input.js-image-input").length) {
image.element.append("");
}
}
}
}
function CasImageGallery(options) {
var gallery = this;
gallery.element = options.element;
gallery.isSelectionEnabled = options.selectionEnabled || false;
gallery.preloadedImagesSelector = options.preloadedImagesElements || gallery.element.find(".cas-gallery-preloaded");
gallery.allItems = function() {
return gallery.element.find(".image-container");
};
gallery.unselectAll = function() {
gallery.allItems().each(function(index) {
var image = new CasImage($(this), gallery);
image.unselect();
});
};
gallery.getSelectedItems = function() {
var result = [];
return gallery.element.find(".image-container[data-selected=true]").map(function(index, value) {
return $(value)
});
};
gallery.toggleSelection = function() {
gallery.isSelectionEnabled = !gallery.isSelectionEnabled;
if (!gallery.isSelectionEnabled) {
gallery.unselectAll();
} else {
gallery.unselectAll();
gallery.element.find(".unselected-but-selectable").show();
}
gallery.updateUi();
};
gallery.markAsCover = function(id) {
gallery.element.find(".image-container").attr("data-is-cover", "false");
gallery.element.find(".image-container[data-id="+id+"]").attr("data-is-cover", "true");
gallery.element.find("input.js-image-cover-input").remove();
gallery.element.append("");
};
gallery.deleteImages = function() {
var ids = [];
gallery.getSelectedItems().each(function(index, imageElement) {
var image = new CasImage(imageElement, gallery);
ids.push( String(image.recordId()) );
});
var response = options.onDelete(ids);
if (response) {
response.done(function() {
var imageSelectors = [];
$.each(ids, function(index, value) {
imageSelectors.push(".image-container[data-id="+value+"]");
});
gallery.element.find(imageSelectors.join(", ")).remove();
gallery.unselectAll();
if (gallery.isSelectionEnabled) {
gallery.toggleSelection();
}
}).fail(function() {
alert("Error!");
});
}
};
gallery.imageClicked = function(element) {
if (!gallery.isSelectionEnabled) {
gallery.unselectAll();
}
var image = new CasImage($(element), gallery);
image.click();
gallery.updateUi();
};
gallery.setupEvents = function() {
options.element.on("click", ".image-container", function() {
gallery.imageClicked($(this));
});
options.element.on("click", ".js-toggle-selection", function() {
gallery.toggleSelection();
});
options.element.on("click", ".js-delete-image", function() {
gallery.deleteImages();
});
options.element.on("click", ".js-mark-as-cover", function() {
var id = $(this).parents(".image-container").data("id");
gallery.markAsCover(id);
});
/*
* There's a bug with dragleave when over child elements, flickering. This
* fixes it.
*/
var dropzoneLastEnter;
$(document)
.on('dragover dragenter', ".dropzone", function(e) {
dropzoneLastEnter = event.target;
e.preventDefault();
var dataTransfer = e.originalEvent.dataTransfer;
if (dataTransfer.types && (dataTransfer.types.indexOf ? dataTransfer.types.indexOf('Files') != -1 : dataTransfer.types.contains('Files'))) {
$(this).addClass('in');
}
})
.on('dragleave drop', ".dropzone", function(e) {
if (dropzoneLastEnter === event.target) {
$(this).removeClass('in');
}
});
};
gallery.preloadImages = function() {
var images = gallery.preloadedImagesSelector;
$.each(images, function(index, value) {
var image = $(value);
var url = image.data("src");
var id = image.data("id");
var filename = image.data("filename");
var originalOrder = image.data("original-order");
var isCover = image.data("is-cover");
gallery.addImage({
url: url,
id: id,
filename: filename,
orderBy: "order",
originalOrder: originalOrder,
isCover: isCover
});
});
};
gallery.imageTemplate = $("#cas-gallery-image-template").html();
gallery.addImage = function(options) {
var url = options.url,
id = options.id,
filename = options.filename,
orderBy = options.orderBy,
// order that comes from the server
originalOrder = options.originalOrder,
isCover = options.isCover;
/**
* The new image information/HTML code
*/
var finalHtml = $(gallery.imageTemplate);
finalHtml.attr("data-id", id);
finalHtml.attr("data-filename", filename);
finalHtml.attr("data-original-order", originalOrder);
finalHtml.find(".image").css("backgroundImage", "url('"+url+"')");
/**
* We need to add images in order by filename. The sorting algorithm
* compares current image with the new image, and when the new image is
* going to be the last one, the algorithm in the loop below doesn't
* add it to the list of images.
*
* So we create `addedImage` to false. In case it's still false after the
* loop, we append the file to the end of the list.
*/
var addedImage = false;
gallery.allItems().each(function(index) {
if (addedImage === true) {
return false;
}
var ordering;
if (orderBy == "filename") {
var listedItemFilename = $(this).data("filename");
ordering = [listedItemFilename, filename].sort();
/**
* We compare the crrent file name and new file name. We sort them
* both.
*
* Say current images are 3.jpg and 6.jpg and new image is 5.jpg.
* We compare ["3.jpg", "5.jpg"].sort() and see that element zero is not
* 5.jpg. We discard it.
*
* Then ["6.jpg", "5.jpg"].sort() and "5.jpg" is the first element,
* therefore we surpassed the position 5.jpg should be in. At this
* point we take 5.jpg and `insertBefore()` 6.jpg.
*/
if (ordering[0] === filename) {
finalHtml.insertBefore($(this));
addedImage = true;
return;
}
} else if (orderBy == "order") {
var listedItemOrder = $(this).data("original-order");
ordering = [listedItemOrder, originalOrder].sort(sortNumber);
/**
* We compare the crrent file name and new file name. We sort them
* both.
*
* Say current images are 3.jpg and 6.jpg and new image is 5.jpg.
* We compare ["3.jpg", "5.jpg"].sort() and see that element zero is not
* 5.jpg. We discard it.
*
* Then ["6.jpg", "5.jpg"].sort() and "5.jpg" is the first element,
* therefore we surpassed the position 5.jpg should be in. At this
* point we take 5.jpg and `insertBefore()` 6.jpg.
*/
if (ordering[0] === originalOrder) {
finalHtml.insertBefore($(this));
addedImage = true;
return;
}
}
});
if (addedImage === false) {
gallery.element.find(".images").append(finalHtml);
}
gallery.refreshImagesFormInputs();
gallery.unselectAll();
if (isCover) {
gallery.markAsCover(id);
}
gallery.updateUi();
};
gallery.refreshImagesFormInputs = function() {
$(".js-image-input").remove();
gallery.allItems().each(function(index) {
var image = new CasImage($(this), gallery);
image.addOrderedInput(index);
});
};
gallery.updateUi = function() {
if (gallery.isSelectionEnabled) {
gallery.element.find(".when-selection-enabled").show();
gallery.element.find(".when-selection-disabled").hide();
gallery.element.find(".image .image-options").hide();
} else {
gallery.element.find(".unselected-but-selectable").hide();
gallery.element.find(".when-selection-enabled").hide();
gallery.element.find(".when-selection-disabled").show();
}
};
return {
init: function() {
gallery.preloadImages();
gallery.setupEvents();
gallery.updateUi();
},
addImage: function(options) {
gallery.addImage({
url: options.url,
id: options.id,
filename: options.filename,
orderBy: options.orderBy,
isCover: options.isCover
});
},
resetImagesOrder: function() {
gallery.element.find("input.js-image-input").remove();
gallery.refreshImagesFormInputs();
},
attachable: function() {
return {
type: gallery.element.data("attachable-type"),
id: gallery.element.data("attachable-id")
};
}
}
}