.
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
/* global django, Cl */
|
||||
|
||||
/*
|
||||
This functionality is used in folder/choose_copy_destination.html template
|
||||
to disable submit if there is only one folder to copy
|
||||
*/
|
||||
|
||||
// as of Django 2.x we need to check where jQuery is
|
||||
var djQuery = window.$;
|
||||
|
||||
if (django.jQuery) {
|
||||
djQuery = django.jQuery;
|
||||
}
|
||||
|
||||
djQuery(function ($) {
|
||||
var destinationOptions = $('#destination').find('option');
|
||||
var destinationOptionLength = destinationOptions.length;
|
||||
var submit = $('.js-submit-copy-move');
|
||||
var tooltip = $('.js-disabled-btn-tooltip');
|
||||
|
||||
if (destinationOptionLength === 1 && destinationOptions.prop('disabled')) {
|
||||
submit.hide();
|
||||
tooltip.show().css('display', 'inline-block');
|
||||
}
|
||||
|
||||
Cl.filerTooltip($);
|
||||
});
|
||||
@@ -0,0 +1,191 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: dropdown.js v3.3.6
|
||||
* http://getbootstrap.com/javascript/#dropdowns
|
||||
* ========================================================================
|
||||
* Copyright 2011-2016 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
'use strict';
|
||||
|
||||
// as of Django 2.x we need to check where jQuery is
|
||||
var djQuery = window.$;
|
||||
|
||||
if (django.jQuery) {
|
||||
djQuery = django.jQuery;
|
||||
}
|
||||
|
||||
/* global django */
|
||||
(function ($) {
|
||||
|
||||
// DROPDOWN CLASS DEFINITION
|
||||
// =========================
|
||||
|
||||
var backdrop = '.filer-dropdown-backdrop';
|
||||
var toggle = '[data-toggle="filer-dropdown"]';
|
||||
var Dropdown = function (element) {
|
||||
$(element).on('click.bs.filer-dropdown', this.toggle);
|
||||
};
|
||||
var old = $.fn.dropdown;
|
||||
|
||||
function getParent($this) {
|
||||
var selector = $this.attr('data-target');
|
||||
var $parent = selector && $(selector);
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href');
|
||||
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, ''); // strip for ie7
|
||||
}
|
||||
|
||||
return $parent && $parent.length ? $parent : $this.parent(); // jshint ignore:line
|
||||
}
|
||||
|
||||
function clearMenus(e) {
|
||||
if (e && e.which === 3) {
|
||||
return;
|
||||
}
|
||||
$(backdrop).remove();
|
||||
$(toggle).each(function () {
|
||||
var $this = $(this);
|
||||
var $parent = getParent($this);
|
||||
var relatedTarget = { relatedTarget: this };
|
||||
|
||||
if (!$parent.hasClass('open')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e && e.type === 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) { // jshint ignore:line
|
||||
return;
|
||||
}
|
||||
|
||||
$parent.trigger(e = $.Event('hide.bs.filer-dropdown', relatedTarget));
|
||||
|
||||
if (e.isDefaultPrevented()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this.attr('aria-expanded', 'false');
|
||||
$parent.removeClass('open').trigger($.Event('hidden.bs.filer-dropdown', relatedTarget));
|
||||
});
|
||||
}
|
||||
|
||||
Dropdown.prototype.toggle = function (e) {
|
||||
var $this = $(this);
|
||||
var $parent = getParent($this);
|
||||
var isActive = $parent.hasClass('open');
|
||||
var relatedTarget = { relatedTarget: this };
|
||||
|
||||
if ($this.is('.disabled, :disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearMenus();
|
||||
|
||||
if (!isActive) {
|
||||
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
|
||||
// if mobile we use a backdrop because click events don't delegate
|
||||
$(document.createElement('div')).addClass('filer-dropdown-backdrop')
|
||||
.insertAfter($(this)).on('click', clearMenus);
|
||||
}
|
||||
|
||||
$parent.trigger(e = $.Event('show.bs.filer-dropdown', relatedTarget));
|
||||
|
||||
if (e.isDefaultPrevented()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this.trigger('focus').attr('aria-expanded', 'true');
|
||||
|
||||
$parent.toggleClass('open').trigger($.Event('shown.bs.filer-dropdown', relatedTarget));
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
Dropdown.prototype.keydown = function (e) {
|
||||
var $this = $(this);
|
||||
var $parent = getParent($this);
|
||||
var isActive = $parent.hasClass('open');
|
||||
var desc = ' li:not(.disabled):visible a';
|
||||
var $items = $parent.find('.dropdown-menu' + desc);
|
||||
var index = $items.index(e.target);
|
||||
|
||||
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if ($this.is('.disabled, :disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isActive && e.which !== 27 || isActive && e.which === 27) {
|
||||
if (e.which === 27) {
|
||||
$parent.find(toggle).trigger('focus');
|
||||
}
|
||||
return $this.trigger('click');
|
||||
}
|
||||
|
||||
if (!$items.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.which === 38 && index > 0) {
|
||||
index--; // up
|
||||
}
|
||||
if (e.which === 40 && index < $items.length - 1) {
|
||||
index++; // down
|
||||
}
|
||||
if (!~index) { // jshint ignore:line
|
||||
index = 0;
|
||||
}
|
||||
|
||||
$items.eq(index).trigger('focus');
|
||||
};
|
||||
|
||||
|
||||
// DROPDOWN PLUGIN DEFINITION
|
||||
// ==========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this);
|
||||
var data = $this.data('bs.filer-dropdown');
|
||||
|
||||
if (!data) {
|
||||
$this.data('bs.filer-dropdown', (data = new Dropdown(this)));
|
||||
}
|
||||
if (typeof option === 'string') {
|
||||
data[option].call($this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$.fn.dropdown = Plugin;
|
||||
$.fn.dropdown.Constructor = Dropdown;
|
||||
|
||||
|
||||
// DROPDOWN NO CONFLICT
|
||||
// ====================
|
||||
|
||||
$.fn.dropdown.noConflict = function () {
|
||||
$.fn.dropdown = old;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
// APPLY TO STANDARD DROPDOWN ELEMENTS
|
||||
// ===================================
|
||||
|
||||
$(document)
|
||||
.on('click.bs.filer-dropdown.data-api', clearMenus)
|
||||
.on('click.bs.filer-dropdown.data-api', '.filer-dropdown form', function (e) {
|
||||
e.stopPropagation();
|
||||
})
|
||||
.on('click.bs.filer-dropdown.data-api', toggle, Dropdown.prototype.toggle)
|
||||
.on('keydown.bs.filer-dropdown.data-api', toggle, Dropdown.prototype.keydown)
|
||||
.on('keydown.bs.filer-dropdown.data-api', '.filer-dropdown-menu', Dropdown.prototype.keydown);
|
||||
|
||||
})(djQuery);
|
||||
@@ -0,0 +1,171 @@
|
||||
// #DROPZONE#
|
||||
// This script implements the dropzone settings
|
||||
/* globals Dropzone, django */
|
||||
'use strict';
|
||||
|
||||
// as of Django 2.x we need to check where jQuery is
|
||||
var djQuery = window.$;
|
||||
|
||||
if (django.jQuery) {
|
||||
djQuery = django.jQuery;
|
||||
}
|
||||
|
||||
if (Dropzone) {
|
||||
Dropzone.autoDiscover = false;
|
||||
}
|
||||
|
||||
/* globals Dropzone, django */
|
||||
djQuery(function ($) {
|
||||
var dropzoneTemplateSelector = '.js-filer-dropzone-template';
|
||||
var previewImageSelector = '.js-img-preview';
|
||||
var dropzoneSelector = '.js-filer-dropzone';
|
||||
var dropzones = $(dropzoneSelector);
|
||||
var messageSelector = '.js-filer-dropzone-message';
|
||||
var lookupButtonSelector = '.js-related-lookup';
|
||||
var progressSelector = '.js-filer-dropzone-progress';
|
||||
var previewImageWrapperSelector = '.js-img-wrapper';
|
||||
var filerClearerSelector = '.filerClearer';
|
||||
var fileChooseSelector = '.js-file-selector';
|
||||
var fileIdInputSelector = '.vForeignKeyRawIdAdminField';
|
||||
var dragHoverClass = 'dz-drag-hover';
|
||||
var hiddenClass = 'hidden';
|
||||
var mobileClass = 'filer-dropzone-mobile';
|
||||
var objectAttachedClass = 'js-object-attached';
|
||||
// var dataMaxFileSize = 'max-file-size';
|
||||
var minWidth = 500;
|
||||
var checkMinWidth = function (element) {
|
||||
element.toggleClass(mobileClass, element.width() < minWidth);
|
||||
};
|
||||
var showError = function (message) {
|
||||
try {
|
||||
window.parent.CMS.API.Messages.open({
|
||||
message: message
|
||||
});
|
||||
} catch (e) {
|
||||
if (window.filerShowError) {
|
||||
window.filerShowError(message);
|
||||
} else {
|
||||
alert(message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var createDropzone = function () {
|
||||
var dropzone = $(this);
|
||||
var dropzoneUrl = dropzone.data('url');
|
||||
var inputId = dropzone.find(fileIdInputSelector);
|
||||
var isImage = inputId.is('[name="image"]');
|
||||
var lookupButton = dropzone.find(lookupButtonSelector);
|
||||
var message = dropzone.find(messageSelector);
|
||||
var clearButton = dropzone.find(filerClearerSelector);
|
||||
var fileChoose = dropzone.find(fileChooseSelector);
|
||||
|
||||
if (this.dropzone) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(window).on('resize', function () {
|
||||
checkMinWidth(dropzone);
|
||||
});
|
||||
|
||||
new Dropzone(this, {
|
||||
url: dropzoneUrl,
|
||||
paramName: 'file',
|
||||
maxFiles: 1,
|
||||
// for now disabled as we don't have the correct file size limit
|
||||
// maxFilesize: dropzone.data(dataMaxFileSize) || 20, // MB
|
||||
previewTemplate: $(dropzoneTemplateSelector).html(),
|
||||
clickable: false,
|
||||
addRemoveLinks: false,
|
||||
init: function () {
|
||||
checkMinWidth(dropzone);
|
||||
this.on('removedfile', function () {
|
||||
fileChoose.show();
|
||||
dropzone.removeClass(objectAttachedClass);
|
||||
this.removeAllFiles();
|
||||
clearButton.trigger('click');
|
||||
});
|
||||
$('img', this.element).on('dragstart', function (event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
clearButton.on('click', function () {
|
||||
dropzone.removeClass(objectAttachedClass);
|
||||
inputId.trigger('change');
|
||||
});
|
||||
},
|
||||
maxfilesexceeded: function () {
|
||||
this.removeAllFiles(true);
|
||||
},
|
||||
drop: function () {
|
||||
this.removeAllFiles(true);
|
||||
fileChoose.hide();
|
||||
lookupButton.addClass('related-lookup-change');
|
||||
message.addClass(hiddenClass);
|
||||
dropzone.removeClass(dragHoverClass);
|
||||
dropzone.addClass(objectAttachedClass);
|
||||
},
|
||||
success: function (file, response) {
|
||||
$(progressSelector).addClass(hiddenClass);
|
||||
if (file && file.status === 'success' && response) {
|
||||
if (response.file_id) {
|
||||
inputId.val(response.file_id);
|
||||
inputId.trigger('change');
|
||||
}
|
||||
if (response.thumbnail_180) {
|
||||
if (isImage) {
|
||||
$(previewImageSelector).css({
|
||||
'background-image': 'url(' + response.thumbnail_180 + ')'
|
||||
});
|
||||
$(previewImageWrapperSelector).removeClass(hiddenClass);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (response && response.error) {
|
||||
showError(file.name + ': ' + response.error);
|
||||
}
|
||||
this.removeAllFiles(true);
|
||||
}
|
||||
|
||||
$('img', this.element).on('dragstart', function (event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
},
|
||||
error: function (file, response) {
|
||||
showError(file.name + ': ' + response.error);
|
||||
this.removeAllFiles(true);
|
||||
},
|
||||
reset: function () {
|
||||
if (isImage) {
|
||||
$(previewImageWrapperSelector).addClass(hiddenClass);
|
||||
$(previewImageSelector).css({'background-image': 'none'});
|
||||
}
|
||||
dropzone.removeClass(objectAttachedClass);
|
||||
inputId.val('');
|
||||
lookupButton.removeClass('related-lookup-change');
|
||||
message.removeClass(hiddenClass);
|
||||
inputId.trigger('change');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (dropzones.length && Dropzone) {
|
||||
if (!window.filerDropzoneInitialized) {
|
||||
window.filerDropzoneInitialized = true;
|
||||
Dropzone.autoDiscover = false;
|
||||
}
|
||||
dropzones.each(createDropzone);
|
||||
// window.__admin_utc_offset__ is used as canary to detect Django 1.8
|
||||
// There is no way to feature detect the new behavior implemented in Django 1.9
|
||||
if (!window.__admin_utc_offset__) {
|
||||
$(document).on('formset:added', function (ev, row) {
|
||||
var dropzones = $(row).find(dropzoneSelector);
|
||||
dropzones.each(createDropzone);
|
||||
});
|
||||
} else {
|
||||
$('.add-row a').on('click', function () {
|
||||
var dropzones = $(dropzoneSelector);
|
||||
dropzones.each(createDropzone);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,143 @@
|
||||
// #FOCAL POINT#
|
||||
// This script implements the image focal point setting
|
||||
'use strict';
|
||||
|
||||
var Cl = window.Cl || {};
|
||||
/* globals Class, django */
|
||||
|
||||
// as of Django 2.x we need to check where jQuery is
|
||||
var djQuery = window.$;
|
||||
|
||||
if (django.jQuery) {
|
||||
djQuery = django.jQuery;
|
||||
}
|
||||
|
||||
(function ($) {
|
||||
Cl.FocalPoint = new Class({
|
||||
options: {
|
||||
containerSelector: '.js-focal-point',
|
||||
imageSelector: '.js-focal-point-image',
|
||||
circleSelector: '.js-focal-point-circle',
|
||||
locationSelector: '.js-focal-point-location',
|
||||
draggableClass: 'ui-draggable',
|
||||
hiddenClass: 'hidden',
|
||||
dataLocation: 'location-selector'
|
||||
},
|
||||
_init: function (container) {
|
||||
var focalPointInstance = new Cl.FocalPointConstructor(container, this.options);
|
||||
this.focalPointInstances.push(focalPointInstance);
|
||||
},
|
||||
initialize: function (options) {
|
||||
var that = this;
|
||||
|
||||
this.options = $.extend({}, this.options, options);
|
||||
this.focalPointInstances = [];
|
||||
|
||||
$(this.options.containerSelector).each(function () {
|
||||
that._init(this);
|
||||
});
|
||||
|
||||
Cl.mediator.subscribe('focal-point:init', this._init);
|
||||
},
|
||||
destroy: function () {
|
||||
Cl.mediator.remove('focal-point:init', this._init);
|
||||
|
||||
this.focalPointInstances.forEach(function (focalPointInstance) {
|
||||
focalPointInstance.destroy();
|
||||
});
|
||||
|
||||
this.focalPointInstances = [];
|
||||
}
|
||||
});
|
||||
|
||||
Cl.FocalPointConstructor = new Class({
|
||||
_updateLocationValue: function (x, y) {
|
||||
var locationValue;
|
||||
|
||||
locationValue = Math.round(x * this.ratio) + ',' + Math.round(y * this.ratio);
|
||||
|
||||
this.location.val(locationValue);
|
||||
},
|
||||
_onImageLoaded: function () {
|
||||
var that = this;
|
||||
var x = null;
|
||||
var y = null;
|
||||
var locationValue = this.location.val();
|
||||
var imageWidth = this.image.width();
|
||||
var imageHeight = this.image.height();
|
||||
|
||||
if (this.image[0].naturalWidth === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.circle.removeClass(this.options.hiddenClass);
|
||||
|
||||
if (locationValue.length) {
|
||||
x = Math.round(Number(locationValue.split(',')[0]) / this.ratio);
|
||||
y = Math.round(Number(locationValue.split(',')[1]) / this.ratio);
|
||||
} else {
|
||||
y = imageHeight / 2;
|
||||
x = imageWidth / 2;
|
||||
}
|
||||
|
||||
if (isNaN(x) || isNaN(y)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.circle.css({
|
||||
top: y,
|
||||
left: x
|
||||
});
|
||||
|
||||
this.circle.draggable({
|
||||
containment: 'parent',
|
||||
drag: function (event, ui) {
|
||||
that._updateLocationValue(ui.position.left, ui.position.top);
|
||||
}
|
||||
});
|
||||
|
||||
this._updateLocationValue(x, y);
|
||||
},
|
||||
_getLocation: function () {
|
||||
var newLocationSelector = this.container.data(this.options.dataLocation);
|
||||
var newLocation = $(newLocationSelector);
|
||||
if (newLocation.length) {
|
||||
return newLocation;
|
||||
} else {
|
||||
return this.container.find(this.options.locationSelector);
|
||||
}
|
||||
},
|
||||
initialize: function (container, options) {
|
||||
this.options = $.extend({}, this.options, options);
|
||||
|
||||
this.container = $(container);
|
||||
this.containerOffset = this.container.offset();
|
||||
this.image = this.container.find(this.options.imageSelector);
|
||||
this.circle = this.container.find(this.options.circleSelector);
|
||||
this.ratio = parseFloat(this.image.data('ratio'));
|
||||
this.location = this._getLocation();
|
||||
this._onImageLoaded = $.proxy(this._onImageLoaded, this);
|
||||
|
||||
if (this.image.prop('complete')) {
|
||||
this._onImageLoaded();
|
||||
} else {
|
||||
this.image.on('load', this._onImageLoaded);
|
||||
}
|
||||
|
||||
},
|
||||
destroy: function () {
|
||||
if (this.circle.hasClass(this.options.draggableClass)) {
|
||||
this.circle.draggable('disable');
|
||||
}
|
||||
|
||||
this.options = null;
|
||||
|
||||
this.container = null;
|
||||
this.containerOffset = null;
|
||||
this.image = null;
|
||||
this.circle = null;
|
||||
this.location = null;
|
||||
this.ratio = null;
|
||||
}
|
||||
});
|
||||
})(djQuery);
|
||||
@@ -0,0 +1,59 @@
|
||||
'use strict';
|
||||
/* global django */
|
||||
|
||||
// as of Django 2.x we need to check where jQuery is
|
||||
var djQuery = window.$;
|
||||
|
||||
if (django.jQuery) {
|
||||
djQuery = django.jQuery;
|
||||
}
|
||||
|
||||
(function ($) {
|
||||
function windowname_to_id(text) {
|
||||
text = text.replace(/__dot__/g, '.');
|
||||
text = text.replace(/__dash__/g, '-');
|
||||
return text;
|
||||
}
|
||||
|
||||
window.dismissPopupAndReload = function (win) {
|
||||
document.location.reload();
|
||||
win.close();
|
||||
};
|
||||
window.dismissRelatedImageLookupPopup = function (win, chosenId, chosenThumbnailUrl, chosenDescriptionTxt) {
|
||||
var id = windowname_to_id(win.name);
|
||||
var lookup = $('#' + id);
|
||||
var container = lookup.closest('.filerFile');
|
||||
var image = container.find('.thumbnail_img');
|
||||
var descriptionText = container.find('.description_text');
|
||||
var clearer = container.find('.filerClearer');
|
||||
var dropzoneMessage = container.siblings('.dz-message');
|
||||
var element = container.find(':input');
|
||||
var oldId = element.value;
|
||||
|
||||
element.val(chosenId);
|
||||
element.closest('.js-filer-dropzone').addClass('js-object-attached');
|
||||
image.attr('src', chosenThumbnailUrl).removeClass('hidden');
|
||||
descriptionText.text(chosenDescriptionTxt);
|
||||
clearer.removeClass('hidden');
|
||||
lookup.addClass('related-lookup-change');
|
||||
dropzoneMessage.addClass('hidden');
|
||||
|
||||
if (oldId !== chosenId) {
|
||||
element.trigger('change');
|
||||
}
|
||||
win.close();
|
||||
};
|
||||
window.dismissRelatedFolderLookupPopup = function (win, chosenId, chosenName) {
|
||||
var id = windowname_to_id(win.name);
|
||||
var clearButton = $('#id_' + id + '_clear');
|
||||
var input = $('#id_' + id);
|
||||
var folderName = $('#id_' + id + '_description_txt');
|
||||
var addFolderButton = $('#' + id);
|
||||
|
||||
input.val(chosenId);
|
||||
folderName.text(chosenName);
|
||||
clearButton.removeClass('hidden');
|
||||
addFolderButton.addClass('hidden');
|
||||
win.close();
|
||||
};
|
||||
})(djQuery);
|
||||
@@ -0,0 +1,223 @@
|
||||
// #DROPZONE#
|
||||
// This script implements the dropzone settings
|
||||
'use strict';
|
||||
|
||||
// as of Django 2.x we need to check where jQuery is
|
||||
var djQuery = window.$;
|
||||
|
||||
if (django.jQuery) {
|
||||
djQuery = django.jQuery;
|
||||
}
|
||||
|
||||
/* globals Dropzone, Cl, django */
|
||||
(function ($) {
|
||||
$(function () {
|
||||
var submitNum = 0;
|
||||
var maxSubmitNum = 0;
|
||||
var dropzoneInstances = [];
|
||||
var dropzoneBase = $('.js-filer-dropzone-base');
|
||||
var dropzoneSelector = '.js-filer-dropzone';
|
||||
var dropzones;
|
||||
var infoMessageClass = 'js-filer-dropzone-info-message';
|
||||
var infoMessage = $('.' + infoMessageClass);
|
||||
var folderName = $('.js-filer-dropzone-folder-name');
|
||||
var uploadInfoContainer = $('.js-filer-dropzone-upload-info-container');
|
||||
var uploadInfo = $('.js-filer-dropzone-upload-info');
|
||||
var uploadWelcome = $('.js-filer-dropzone-upload-welcome');
|
||||
var uploadNumber = $('.js-filer-dropzone-upload-number');
|
||||
var uploadCount = $('.js-filer-upload-count');
|
||||
var uploadText = $('.js-filer-upload-text');
|
||||
var uploadFileNameSelector = '.js-filer-dropzone-file-name';
|
||||
var uploadProgressSelector = '.js-filer-dropzone-progress';
|
||||
var uploadSuccess = $('.js-filer-dropzone-upload-success');
|
||||
var uploadCanceled = $('.js-filer-dropzone-upload-canceled');
|
||||
var cancelUpload = $('.js-filer-dropzone-cancel');
|
||||
var dragHoverClass = 'dz-drag-hover';
|
||||
var dataUploaderConnections = 'max-uploader-connections';
|
||||
var dragHoverBorder = $('.drag-hover-border');
|
||||
// var dataMaxFileSize = 'max-file-size';
|
||||
var hiddenClass = 'hidden';
|
||||
var hideMessageTimeout;
|
||||
var hasErrors = false;
|
||||
var baseUrl;
|
||||
var baseFolderTitle;
|
||||
var updateUploadNumber = function () {
|
||||
uploadNumber.text(maxSubmitNum - submitNum + '/' + maxSubmitNum);
|
||||
uploadText.removeClass('hidden');
|
||||
uploadCount.removeClass('hidden');
|
||||
};
|
||||
var destroyDropzones = function () {
|
||||
$.each(dropzoneInstances, function (index) {
|
||||
dropzoneInstances[index].destroy();
|
||||
});
|
||||
};
|
||||
var getElementByFile = function (file, url) {
|
||||
return $(document.getElementById(
|
||||
'file-' +
|
||||
encodeURIComponent(file.name) +
|
||||
file.size +
|
||||
file.lastModified +
|
||||
url
|
||||
));
|
||||
};
|
||||
|
||||
if (dropzoneBase && dropzoneBase.length) {
|
||||
baseUrl = dropzoneBase.data('url');
|
||||
baseFolderTitle = dropzoneBase.data('folder-name');
|
||||
|
||||
$('body').data('url', baseUrl).data('folder-name', baseFolderTitle).addClass('js-filer-dropzone');
|
||||
}
|
||||
|
||||
Cl.mediator.subscribe('filer-upload-in-progress', destroyDropzones);
|
||||
|
||||
dropzones = $(dropzoneSelector);
|
||||
|
||||
if (dropzones.length && Dropzone) {
|
||||
Dropzone.autoDiscover = false;
|
||||
dropzones.each(function () {
|
||||
var dropzone = $(this);
|
||||
var dropzoneUrl = $(this).data('url');
|
||||
var dropzoneInstance = new Dropzone(this, {
|
||||
url: dropzoneUrl,
|
||||
paramName: 'file',
|
||||
maxFiles: 100,
|
||||
// for now disabled as we don't have the correct file size limit
|
||||
// maxFilesize: dropzone.data(dataMaxFileSize) || 20, // MB
|
||||
previewTemplate: '<div></div>',
|
||||
clickable: false,
|
||||
addRemoveLinks: false,
|
||||
parallelUploads: dropzone.data(dataUploaderConnections) || 3,
|
||||
accept: function (file, done) {
|
||||
var uploadInfoClone;
|
||||
|
||||
Cl.mediator.remove('filer-upload-in-progress', destroyDropzones);
|
||||
Cl.mediator.publish('filer-upload-in-progress');
|
||||
|
||||
clearTimeout(hideMessageTimeout);
|
||||
uploadWelcome.addClass(hiddenClass);
|
||||
cancelUpload.removeClass(hiddenClass);
|
||||
|
||||
if (getElementByFile(file, dropzoneUrl).length) {
|
||||
done('duplicate');
|
||||
} else {
|
||||
uploadInfoClone = uploadInfo.clone();
|
||||
|
||||
uploadInfoClone.find(uploadFileNameSelector).text(file.name);
|
||||
uploadInfoClone.find(uploadProgressSelector).width(0);
|
||||
uploadInfoClone
|
||||
.attr(
|
||||
'id',
|
||||
'file-' +
|
||||
encodeURIComponent(file.name) +
|
||||
file.size +
|
||||
file.lastModified +
|
||||
dropzoneUrl
|
||||
)
|
||||
.appendTo(uploadInfoContainer);
|
||||
|
||||
submitNum++;
|
||||
maxSubmitNum++;
|
||||
updateUploadNumber();
|
||||
done();
|
||||
}
|
||||
|
||||
dropzones.removeClass('reset-hover');
|
||||
infoMessage.removeClass(hiddenClass);
|
||||
dropzones.removeClass(dragHoverClass);
|
||||
},
|
||||
dragover: function (dragEvent) {
|
||||
var folderTitle = $(dragEvent.target).closest(dropzoneSelector).data('folder-name');
|
||||
var dropzoneFolder = dropzone.hasClass('js-filer-dropzone-folder');
|
||||
var dropzoneBoundingRect = dropzone[0].getBoundingClientRect();
|
||||
var borderSize = $('.drag-hover-border').css('border-top-width');
|
||||
var dropzonePosition = {
|
||||
top: dropzoneBoundingRect.top,
|
||||
bottom: dropzoneBoundingRect.bottom,
|
||||
width: dropzoneBoundingRect.width,
|
||||
height: dropzoneBoundingRect.height - (parseInt(borderSize, 10) * 2)
|
||||
};
|
||||
if (dropzoneFolder) {
|
||||
dragHoverBorder.css(dropzonePosition);
|
||||
}
|
||||
|
||||
$(dropzones).addClass('reset-hover');
|
||||
uploadSuccess.addClass(hiddenClass);
|
||||
infoMessage.removeClass(hiddenClass);
|
||||
dropzone.addClass(dragHoverClass).removeClass('reset-hover');
|
||||
|
||||
folderName.text(folderTitle);
|
||||
},
|
||||
dragend: function () {
|
||||
clearTimeout(hideMessageTimeout);
|
||||
hideMessageTimeout = setTimeout(function () {
|
||||
infoMessage.addClass(hiddenClass);
|
||||
}, 1000);
|
||||
|
||||
infoMessage.removeClass(hiddenClass);
|
||||
dropzones.removeClass(dragHoverClass);
|
||||
dragHoverBorder.css({ top: 0, bottom: 0, width: 0, height: 0 });
|
||||
},
|
||||
dragleave: function () {
|
||||
clearTimeout(hideMessageTimeout);
|
||||
hideMessageTimeout = setTimeout(function () {
|
||||
infoMessage.addClass(hiddenClass);
|
||||
}, 1000);
|
||||
|
||||
infoMessage.removeClass(hiddenClass);
|
||||
dropzones.removeClass(dragHoverClass);
|
||||
dragHoverBorder.css({ top: 0, bottom: 0, width: 0, height: 0 });
|
||||
|
||||
},
|
||||
sending: function (file) {
|
||||
getElementByFile(file, dropzoneUrl).removeClass(hiddenClass);
|
||||
},
|
||||
uploadprogress: function (file, progress) {
|
||||
getElementByFile(file, dropzoneUrl).find(uploadProgressSelector).width(progress + '%');
|
||||
},
|
||||
success: function (file) {
|
||||
submitNum--;
|
||||
updateUploadNumber();
|
||||
getElementByFile(file, dropzoneUrl).remove();
|
||||
},
|
||||
queuecomplete: function () {
|
||||
if (submitNum !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateUploadNumber();
|
||||
|
||||
cancelUpload.addClass(hiddenClass);
|
||||
uploadInfo.addClass(hiddenClass);
|
||||
|
||||
if (hasErrors) {
|
||||
uploadNumber.addClass(hiddenClass);
|
||||
setTimeout(function () {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
} else {
|
||||
uploadSuccess.removeClass(hiddenClass);
|
||||
window.location.reload();
|
||||
}
|
||||
},
|
||||
error: function (file, errorText) {
|
||||
updateUploadNumber();
|
||||
if (errorText === 'duplicate') {
|
||||
return;
|
||||
}
|
||||
hasErrors = true;
|
||||
if (window.filerShowError) {
|
||||
window.filerShowError(file.name + ': ' + errorText);
|
||||
}
|
||||
}
|
||||
});
|
||||
dropzoneInstances.push(dropzoneInstance);
|
||||
cancelUpload.on('click', function (clickEvent) {
|
||||
clickEvent.preventDefault();
|
||||
cancelUpload.addClass(hiddenClass);
|
||||
uploadCanceled.removeClass(hiddenClass);
|
||||
dropzoneInstance.removeAllFiles(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
})(djQuery);
|
||||
@@ -0,0 +1,90 @@
|
||||
// #TOGGLER#
|
||||
// This script implements the simple element toggle
|
||||
'use strict';
|
||||
|
||||
var Cl = window.Cl || {};
|
||||
/* global Class, django */
|
||||
|
||||
// as of Django 2.x we need to check where jQuery is
|
||||
var djQuery = window.$;
|
||||
|
||||
if (django.jQuery) {
|
||||
djQuery = django.jQuery;
|
||||
}
|
||||
|
||||
(function ($) {
|
||||
Cl.Toggler = new Class({
|
||||
options: {
|
||||
linksSelector: '.js-toggler-link',
|
||||
dataHeaderSelector: 'toggler-header-selector',
|
||||
dataContentSelector: 'toggler-content-selector',
|
||||
collapsedClass: 'js-collapsed',
|
||||
expandedClass: 'js-expanded',
|
||||
hiddenClass: 'hidden'
|
||||
},
|
||||
initialize: function (options) {
|
||||
var that = this;
|
||||
|
||||
this.options = $.extend({}, this.options, options);
|
||||
this.togglerInstances = [];
|
||||
|
||||
$(this.options.linksSelector).each(function () {
|
||||
var togglerInstance = new Cl.TogglerConstructor(this, that.options);
|
||||
that.togglerInstances.push(togglerInstance);
|
||||
});
|
||||
},
|
||||
destroy: function () {
|
||||
this.links = null;
|
||||
|
||||
this.togglerInstances.forEach(function (togglerInstance) {
|
||||
togglerInstance.destroy();
|
||||
});
|
||||
|
||||
this.togglerInstances = [];
|
||||
}
|
||||
});
|
||||
|
||||
Cl.TogglerConstructor = new Class({
|
||||
_updateClasses: function () {
|
||||
if (this.content.hasClass(this.options.hiddenClass)) {
|
||||
this.header.removeClass(this.options.expandedClass);
|
||||
this.header.addClass(this.options.collapsedClass);
|
||||
} else {
|
||||
this.header.addClass(this.options.expandedClass);
|
||||
this.header.removeClass(this.options.collapsedClass);
|
||||
}
|
||||
},
|
||||
_onTogglerClick: function (clickEvent) {
|
||||
this.content.toggleClass(this.options.hiddenClass);
|
||||
this._updateClasses();
|
||||
|
||||
clickEvent.preventDefault();
|
||||
},
|
||||
_initLink: function () {
|
||||
this._updateClasses();
|
||||
|
||||
this._onTogglerClick = $.proxy(this._onTogglerClick, this);
|
||||
this.link.on('click', this._onTogglerClick);
|
||||
},
|
||||
initialize: function (link, options) {
|
||||
this.options = $.extend({}, this.options, options);
|
||||
|
||||
this.link = $(link);
|
||||
this.headerSelector = this.link.data(this.options.dataHeaderSelector);
|
||||
this.contentSelector = this.link.data(this.options.dataContentSelector);
|
||||
this.header = $(this.headerSelector);
|
||||
this.header = this.header.length ? this.header : this.link;
|
||||
this.content = $(this.contentSelector);
|
||||
|
||||
if (this.content.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._initLink();
|
||||
},
|
||||
destroy: function () {
|
||||
this.options = null;
|
||||
this.link = null;
|
||||
}
|
||||
});
|
||||
})(djQuery);
|
||||
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
var Cl = window.Cl || {};
|
||||
|
||||
Cl.filerTooltip = function ($) {
|
||||
var tooltipSelector = '.js-filer-tooltip';
|
||||
|
||||
$(tooltipSelector).on('mouseover', function () {
|
||||
var that = $(this);
|
||||
var title = that.attr('title');
|
||||
|
||||
that.data('filerTooltip', title).removeAttr('title');
|
||||
$('<p class="filer-tooltip"></p>').text(title).appendTo(tooltipSelector);
|
||||
|
||||
}).on('mouseout', function () {
|
||||
var that = $(this);
|
||||
|
||||
that.attr('title', that.data('filerTooltip'));
|
||||
$('.filer-tooltip').remove();
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,142 @@
|
||||
// #UPLOAD BUTTON#
|
||||
// This script implements the upload button logic
|
||||
'use strict';
|
||||
|
||||
// as of Django 2.x we need to check where jQuery is
|
||||
var djQuery = window.$;
|
||||
|
||||
if (django.jQuery) {
|
||||
djQuery = django.jQuery;
|
||||
}
|
||||
|
||||
/* globals qq, Cl, django */
|
||||
(function ($) {
|
||||
$(function () {
|
||||
var submitNum = 0;
|
||||
var maxSubmitNum = 1;
|
||||
var uploadButton = $('.js-upload-button');
|
||||
var uploadButtonDisabled = $('.js-upload-button-disabled');
|
||||
var uploadUrl = uploadButton.data('url');
|
||||
var uploadWelcome = $('.js-filer-dropzone-upload-welcome');
|
||||
var uploadInfoContainer = $('.js-filer-dropzone-upload-info-container');
|
||||
var uploadInfo = $('.js-filer-dropzone-upload-info');
|
||||
var uploadNumber = $('.js-filer-dropzone-upload-number');
|
||||
var uploadFileNameSelector = '.js-filer-dropzone-file-name';
|
||||
var uploadProgressSelector = '.js-filer-dropzone-progress';
|
||||
var uploadSuccess = $('.js-filer-dropzone-upload-success');
|
||||
var uploadCanceled = $('.js-filer-dropzone-upload-canceled');
|
||||
var uploadCancel = $('.js-filer-dropzone-cancel');
|
||||
var infoMessage = $('.js-filer-dropzone-info-message');
|
||||
var hiddenClass = 'hidden';
|
||||
var maxUploaderConnections = uploadButton.data('max-uploader-connections') || 3;
|
||||
var hasErrors = false;
|
||||
var updateUploadNumber = function () {
|
||||
uploadNumber.text(maxSubmitNum - submitNum + '/' + maxSubmitNum);
|
||||
};
|
||||
var removeButton = function () {
|
||||
uploadButton.remove();
|
||||
};
|
||||
// utility
|
||||
var updateQuery = function (uri, key, value) {
|
||||
var re = new RegExp('([?&])' + key + '=.*?(&|$)', 'i');
|
||||
var separator = uri.indexOf('?') !== -1 ? '&' : '?';
|
||||
var hash = window.location.hash;
|
||||
uri = uri.replace(/#.*$/, '');
|
||||
if (uri.match(re)) {
|
||||
return uri.replace(re, '$1' + key + '=' + value + '$2') + hash;
|
||||
} else {
|
||||
return uri + separator + key + '=' + value + hash;
|
||||
}
|
||||
};
|
||||
var reloadOrdered = function () {
|
||||
var uri = window.location.toString();
|
||||
window.location.replace(updateQuery(uri, 'order_by', '-modified_at'));
|
||||
};
|
||||
|
||||
Cl.mediator.subscribe('filer-upload-in-progress', removeButton);
|
||||
|
||||
new qq.FileUploaderBasic({
|
||||
action: uploadUrl,
|
||||
button: uploadButton[0],
|
||||
maxConnections: maxUploaderConnections,
|
||||
onSubmit: function (id) {
|
||||
Cl.mediator.remove('filer-upload-in-progress', removeButton);
|
||||
Cl.mediator.publish('filer-upload-in-progress');
|
||||
submitNum++;
|
||||
|
||||
maxSubmitNum = id + 1;
|
||||
|
||||
infoMessage.removeClass(hiddenClass);
|
||||
uploadWelcome.addClass(hiddenClass);
|
||||
uploadSuccess.addClass(hiddenClass);
|
||||
uploadInfoContainer.removeClass(hiddenClass);
|
||||
uploadCancel.removeClass(hiddenClass);
|
||||
uploadCanceled.addClass(hiddenClass);
|
||||
|
||||
updateUploadNumber();
|
||||
},
|
||||
onProgress: function (id, fileName, loaded, total) {
|
||||
var percent = Math.round(loaded / total * 100);
|
||||
var fileItem = $('#file-' + id);
|
||||
var uploadInfoClone;
|
||||
|
||||
if (fileItem.length) {
|
||||
fileItem.find(uploadProgressSelector).width(percent + '%');
|
||||
} else {
|
||||
uploadInfoClone = uploadInfo.clone();
|
||||
|
||||
uploadInfoClone.find(uploadFileNameSelector).text(fileName);
|
||||
uploadInfoClone.find(uploadProgressSelector).width(percent);
|
||||
uploadInfoClone.removeClass(hiddenClass)
|
||||
.attr('id', 'file-' + id)
|
||||
.appendTo(uploadInfoContainer);
|
||||
}
|
||||
},
|
||||
onComplete: function (id, fileName, responseJSON) {
|
||||
var file = responseJSON;
|
||||
|
||||
$('#file-' + id).remove();
|
||||
|
||||
if (file.error) {
|
||||
hasErrors = true;
|
||||
window.filerShowError(fileName + ': ' + file.error);
|
||||
}
|
||||
|
||||
submitNum--;
|
||||
updateUploadNumber();
|
||||
|
||||
if (submitNum === 0) {
|
||||
maxSubmitNum = 1;
|
||||
|
||||
uploadWelcome.addClass(hiddenClass);
|
||||
uploadNumber.addClass(hiddenClass);
|
||||
uploadCanceled.addClass(hiddenClass);
|
||||
uploadCancel.addClass(hiddenClass);
|
||||
uploadSuccess.removeClass(hiddenClass);
|
||||
|
||||
if (hasErrors) {
|
||||
setTimeout(reloadOrdered, 1000);
|
||||
} else {
|
||||
reloadOrdered();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
uploadCancel.on('click', function (clickEvent) {
|
||||
clickEvent.preventDefault();
|
||||
uploadCancel.addClass(hiddenClass);
|
||||
uploadNumber.addClass(hiddenClass);
|
||||
uploadInfoContainer.addClass(hiddenClass);
|
||||
uploadCanceled.removeClass(hiddenClass);
|
||||
|
||||
setTimeout(function () {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
if (uploadButtonDisabled.length) {
|
||||
Cl.filerTooltip($);
|
||||
}
|
||||
});
|
||||
})(djQuery);
|
||||
@@ -0,0 +1,35 @@
|
||||
'use strict';
|
||||
/* global django */
|
||||
|
||||
// as of Django 2.x we need to check where jQuery is
|
||||
var djQuery = window.$;
|
||||
|
||||
if (django.jQuery) {
|
||||
djQuery = django.jQuery;
|
||||
}
|
||||
|
||||
djQuery(function ($) {
|
||||
var filer_clear = function () {
|
||||
var clearer = $(this);
|
||||
var container = clearer.closest('.filerFile');
|
||||
var input = container.find(':input');
|
||||
var thumbnail = container.find('.thumbnail_img');
|
||||
var description = container.find('.description_text');
|
||||
var addImageButton = container.find('.lookup');
|
||||
var dropzoneMessage = container.siblings('.dz-message');
|
||||
var hiddenClass = 'hidden';
|
||||
|
||||
clearer.addClass(hiddenClass);
|
||||
input.val('');
|
||||
thumbnail.addClass(hiddenClass);
|
||||
thumbnail.parent('a').removeAttr('href');
|
||||
addImageButton.removeClass('related-lookup-change');
|
||||
dropzoneMessage.removeClass(hiddenClass);
|
||||
description.empty();
|
||||
};
|
||||
|
||||
$('.filerFile .vForeignKeyRawIdAdminField').attr('type', 'hidden');
|
||||
//if this file is included multiple time, we ensure that filer_clear is attached only once.
|
||||
$(document).off('click.filer', '.filerFile .filerClearer', filer_clear)
|
||||
.on('click.filer', '.filerFile .filerClearer', filer_clear);
|
||||
});
|
||||
Reference in New Issue
Block a user