2016-07-28 06:03:09 +02:00
|
|
|
import $ from 'jQuery';
|
|
|
|
import i18n from 'i18n';
|
2016-01-11 02:25:30 +01:00
|
|
|
|
API Use Webpack
The bundle is generated by running “webpack” directly - gulp is no
longer needed as an intermediary. The resulting config is a lot shorter,
although more configuration is pushed into lib.js.
Modules are shared between javascript files as global variables.
Although this global state pollution is a bit messy, I don’t think it’s
practically any worse than the previous state, and it highlights the
heavy coupling between the different packages we have in place.
Reducing the width of the coupling between the core javascript and
add-on modules would probably be a better way of dealing with this than
replacing global variables with some other kind of global state.
The web pack execution seems roughly twice as fast - if I clear out my
framework/client/dist/js folder, it takes 13.3s to rebuild. However,
it’s not rebuilding other files inside dist, only the bundle files.
CSS files are now included from javascript and incorporated into
bundle.css by the webpack. Although the style-loader is helpful in some
dev workflows (it allows live reload), it introduces a flash of
unstyled content which makes it inappropriate for production.
Instead ExtractTextPlugin is used to write all the aggregated CSS
into a single bundle.css file. A style-loader-based configuration could
be introduced for dev environments, if we make use of the webpack live
reloader in the future.
Note that the following features have been removed as they don't appear to be
necessary when using Webpack:
- UMD module generation
- thirdparty dist file copying
LeftAndMain.js deps: Without it, ssui.core.js gets loaded too late,
which leads e.g. to buttons being initialised without this added behaviour.
2016-08-21 03:17:50 +02:00
|
|
|
// entwine also required, but can't be included more than once without error
|
|
|
|
require('../../../thirdparty/jquery-ui/jquery-ui.js');
|
|
|
|
require('../../../admin/client/src/legacy/ssui.core.js');
|
|
|
|
|
2016-09-07 12:21:43 +02:00
|
|
|
window.tmpl = require('blueimp-tmpl/tmpl.js');
|
|
|
|
require('imports?define=>false&this=>window!blueimp-load-image/load-image.js');
|
|
|
|
require('blueimp-file-upload/jquery.iframe-transport.js');
|
|
|
|
require('blueimp-file-upload/cors/jquery.xdr-transport.js');
|
|
|
|
require('blueimp-file-upload/jquery.fileupload.js');
|
|
|
|
require('blueimp-file-upload/jquery.fileupload-ui.js');
|
|
|
|
|
API Use Webpack
The bundle is generated by running “webpack” directly - gulp is no
longer needed as an intermediary. The resulting config is a lot shorter,
although more configuration is pushed into lib.js.
Modules are shared between javascript files as global variables.
Although this global state pollution is a bit messy, I don’t think it’s
practically any worse than the previous state, and it highlights the
heavy coupling between the different packages we have in place.
Reducing the width of the coupling between the core javascript and
add-on modules would probably be a better way of dealing with this than
replacing global variables with some other kind of global state.
The web pack execution seems roughly twice as fast - if I clear out my
framework/client/dist/js folder, it takes 13.3s to rebuild. However,
it’s not rebuilding other files inside dist, only the bundle files.
CSS files are now included from javascript and incorporated into
bundle.css by the webpack. Although the style-loader is helpful in some
dev workflows (it allows live reload), it introduces a flash of
unstyled content which makes it inappropriate for production.
Instead ExtractTextPlugin is used to write all the aggregated CSS
into a single bundle.css file. A style-loader-based configuration could
be introduced for dev environments, if we make use of the webpack live
reloader in the future.
Note that the following features have been removed as they don't appear to be
necessary when using Webpack:
- UMD module generation
- thirdparty dist file copying
LeftAndMain.js deps: Without it, ssui.core.js gets loaded too late,
which leads e.g. to buttons being initialised without this added behaviour.
2016-08-21 03:17:50 +02:00
|
|
|
require('./UploadField_uploadtemplate.js');
|
|
|
|
require('./UploadField_downloadtemplate.js');
|
|
|
|
|
|
|
|
require('../styles/legacy/UploadField.scss');
|
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
$.widget('blueimpUIX.fileupload', $.blueimpUI.fileupload, {
|
|
|
|
_initTemplates: function() {
|
|
|
|
this.options.templateContainer = document.createElement(
|
|
|
|
this._files.prop('nodeName')
|
|
|
|
);
|
|
|
|
this.options.uploadTemplate = window.tmpl(this.options.uploadTemplateName);
|
|
|
|
this.options.downloadTemplate = window.tmpl(this.options.downloadTemplateName);
|
|
|
|
},
|
|
|
|
_enableFileInputButton: function() {
|
|
|
|
$.blueimpUI.fileupload.prototype._enableFileInputButton.call(this);
|
|
|
|
this.element.find('.ss-uploadfield-addfile').show();
|
|
|
|
},
|
|
|
|
_disableFileInputButton: function() {
|
|
|
|
$.blueimpUI.fileupload.prototype._disableFileInputButton.call(this);
|
|
|
|
this.element.find('.ss-uploadfield-addfile').hide();
|
|
|
|
},
|
|
|
|
_onAdd: function(e, data) {
|
|
|
|
// use _onAdd instead of add since we only want it called once for a file set, not for each file
|
|
|
|
var result = $.blueimpUI.fileupload.prototype._onAdd.call(this, e, data);
|
|
|
|
var firstNewFile = this._files.find('.ss-uploadfield-item').slice(data.files.length*-1).first();
|
|
|
|
var top = '+=' + (firstNewFile.position().top - parseInt(firstNewFile.css('marginTop'), 10) || 0 - parseInt(firstNewFile.css('borderTopWidth'), 10) || 0);
|
|
|
|
firstNewFile.offsetParent().animate({scrollTop: top}, 1000);
|
2016-07-28 06:03:09 +02:00
|
|
|
|
|
|
|
/* Compute total size of files */
|
2016-01-11 02:25:30 +01:00
|
|
|
var fSize = 0;
|
|
|
|
for(var i = 0; i < data.files.length; i++){
|
|
|
|
if(typeof data.files[i].size === 'number'){
|
|
|
|
fSize = fSize + data.files[i].size;
|
2016-07-28 06:03:09 +02:00
|
|
|
}
|
2016-01-11 02:25:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
$('.fileOverview .uploadStatus .details .total').text(data.files.length);
|
|
|
|
if(typeof fSize === 'number' && fSize > 0){
|
|
|
|
fSize = this._formatFileSize(fSize);
|
|
|
|
$('.fileOverview .uploadStatus .details .fileSize').text(fSize);
|
2016-07-28 06:03:09 +02:00
|
|
|
}
|
2016-01-11 02:25:30 +01:00
|
|
|
|
|
|
|
//Fixes case where someone uploads a single erroring file
|
|
|
|
if(data.files.length == 1 && data.files[0].error !== null){
|
|
|
|
$('.fileOverview .uploadStatus .state').text(i18n._t('AssetUploadField.UploadField.UPLOADFAIL', 'Sorry your upload failed'));
|
|
|
|
$('.fileOverview .uploadStatus').addClass("bad").removeClass("good").removeClass("notice");
|
|
|
|
}else{
|
|
|
|
$('.fileOverview .uploadStatus .state').text(i18n._t('AssetUploadField.UPLOADINPROGRESS', 'Please wait… upload in progress'));//.show();
|
|
|
|
$('.ss-uploadfield-item-edit-all').hide();
|
|
|
|
$('.fileOverview .uploadStatus').addClass("notice").removeClass("good").removeClass("bad");
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
},
|
|
|
|
_onDone: function (result, textStatus, jqXHR, options) {
|
|
|
|
// Mark form as dirty on completion of successful upload
|
|
|
|
if(this.options.changeDetection) {
|
|
|
|
this.element.closest('form').trigger('dirty');
|
|
|
|
}
|
|
|
|
|
|
|
|
$.blueimpUI.fileupload.prototype._onDone.call(this, result, textStatus, jqXHR, options);
|
|
|
|
},
|
|
|
|
_onSend: function (e, data) {
|
|
|
|
//check the array of existing files to see if we are trying to upload a file that already exists
|
|
|
|
var that = this;
|
|
|
|
var config = this.options;
|
|
|
|
if (config.overwriteWarning && config.replaceFile) {
|
|
|
|
$.get(
|
|
|
|
config['urlFileExists'],
|
|
|
|
{'filename': data.files[0].name},
|
|
|
|
function(response, status, xhr) {
|
|
|
|
if(response.exists) {
|
|
|
|
//display the dialogs with the question to overwrite or not
|
|
|
|
data.context.find('.ss-uploadfield-item-status')
|
|
|
|
.text(config.errorMessages.overwriteWarning)
|
|
|
|
.addClass('ui-state-warning-text');
|
|
|
|
data.context.find('.ss-uploadfield-item-progress').hide();
|
|
|
|
data.context.find('.ss-uploadfield-item-overwrite').show();
|
|
|
|
data.context.find('.ss-uploadfield-item-overwrite-warning').on('click', function(e){
|
|
|
|
data.context.find('.ss-uploadfield-item-progress').show();
|
|
|
|
data.context.find('.ss-uploadfield-item-overwrite').hide();
|
|
|
|
data.context.find('.ss-uploadfield-item-status')
|
|
|
|
.removeClass('ui-state-warning-text');
|
|
|
|
//upload only if the "overwrite" button is clicked
|
|
|
|
$.blueimpUI.fileupload.prototype._onSend.call(that, e, data);
|
2016-07-28 06:03:09 +02:00
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
e.preventDefault(); // Avoid a form submit
|
|
|
|
return false;
|
|
|
|
});
|
2016-03-30 23:45:54 +02:00
|
|
|
} else { //regular file upload
|
2016-01-11 02:25:30 +01:00
|
|
|
return $.blueimpUI.fileupload.prototype._onSend.call(that, e, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return $.blueimpUI.fileupload.prototype._onSend.call(that, e, data);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) {
|
|
|
|
$.blueimpUI.fileupload.prototype._onAlways.call(this, jqXHRorResult, textStatus, jqXHRorError, options);
|
|
|
|
|
|
|
|
if(typeof(jqXHRorError) === 'string') {
|
|
|
|
$('.fileOverview .uploadStatus .state').text(i18n._t('AssetUploadField.UploadField.UPLOADFAIL', 'Sorry your upload failed'));
|
|
|
|
$('.fileOverview .uploadStatus').addClass("bad").removeClass("good").removeClass("notice");
|
|
|
|
} else if (jqXHRorError.status === 200) {
|
|
|
|
$('.fileOverview .uploadStatus .state').text(i18n._t('AssetUploadField.FILEUPLOADCOMPLETED', 'File upload completed!'));//.hide();
|
|
|
|
$('.ss-uploadfield-item-edit-all').show();
|
|
|
|
$('.fileOverview .uploadStatus').addClass("good").removeClass("notice").removeClass("bad");
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_create: function() {
|
|
|
|
$.blueimpUI.fileupload.prototype._create.call(this);
|
|
|
|
// Ensures that the visibility of the fileupload dialog is set correctly at initialisation
|
|
|
|
this._adjustMaxNumberOfFiles(0);
|
|
|
|
},
|
|
|
|
attach: function(data) {
|
|
|
|
if(this.options.changeDetection) {
|
|
|
|
this.element.closest('form').trigger('dirty');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handles attachment of already uploaded files, similar to add
|
|
|
|
var self = this,
|
|
|
|
files = data.files,
|
|
|
|
replaceFileID = data.replaceFileID,
|
|
|
|
valid = true;
|
|
|
|
|
|
|
|
// If replacing an element (and it exists), adjust max number of files at this point
|
|
|
|
var replacedElement = null;
|
|
|
|
if(replaceFileID) {
|
|
|
|
replacedElement = $(".ss-uploadfield-item[data-fileid='"+replaceFileID+"']");
|
|
|
|
if(replacedElement.length === 0) {
|
|
|
|
replacedElement = null;
|
|
|
|
} else {
|
|
|
|
self._adjustMaxNumberOfFiles(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Validate each file
|
|
|
|
$.each(files, function (index, file) {
|
|
|
|
self._adjustMaxNumberOfFiles(-1);
|
2016-02-26 02:43:14 +01:00
|
|
|
valid = self._validate([file]) && valid;
|
2016-01-11 02:25:30 +01:00
|
|
|
});
|
|
|
|
data.isAdjusted = true;
|
|
|
|
data.files.valid = data.isValidated = valid;
|
2016-07-28 06:03:09 +02:00
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
// Generate new file HTMl, and either append or replace (if replacing
|
|
|
|
// an already uploaded file).
|
|
|
|
data.context = this._renderDownload(files);
|
|
|
|
if(replacedElement) {
|
|
|
|
replacedElement.replaceWith(data.context);
|
|
|
|
} else {
|
|
|
|
data.context.appendTo(this._files);
|
|
|
|
}
|
|
|
|
data.context.data('data', data);
|
|
|
|
// Force reflow:
|
|
|
|
this._reflow = this._transition && data.context[0].offsetWidth;
|
|
|
|
data.context.addClass('in');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$.entwine('ss', function($) {
|
|
|
|
|
|
|
|
$('div.ss-upload').entwine({
|
|
|
|
|
|
|
|
Config: null,
|
|
|
|
|
|
|
|
onmatch: function() {
|
|
|
|
|
|
|
|
if (this.is('.readonly,.disabled')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var $fileInput = this.find('.ss-uploadfield-fromcomputer-fileinput'),
|
|
|
|
$dropZone = $('.ss-uploadfield-dropzone'),
|
|
|
|
config = $fileInput.data('config');
|
|
|
|
|
|
|
|
// Drag & drop is opt-in so we have to prevent the default behaviour
|
|
|
|
// (which is 'do nothing') when the drop zone is dragged over.
|
|
|
|
$dropZone.on('dragover', function (e) {
|
|
|
|
e.preventDefault();
|
|
|
|
});
|
|
|
|
|
|
|
|
$dropZone.on('dragenter', function (e) {
|
|
|
|
$dropZone.addClass('hover active');
|
|
|
|
});
|
|
|
|
|
|
|
|
$dropZone.on('dragleave', function (e) {
|
|
|
|
if (e.target === $dropZone[0]) {
|
|
|
|
$dropZone.removeClass('hover active');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
$dropZone.on('drop', function (e) {
|
|
|
|
$dropZone.removeClass('hover active');
|
|
|
|
|
|
|
|
if (e.target !== $dropZone[0]) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
this.setConfig(config);
|
|
|
|
this.fileupload($.extend(true, {
|
|
|
|
formData: function(form) {
|
|
|
|
var idVal = $(form).find(':input[name=ID]').val();
|
|
|
|
var data = [{name: 'SecurityID', value: $(form).find(':input[name=SecurityID]').val()}];
|
|
|
|
if(idVal) data.push({name: 'ID', value: idVal});
|
2016-07-28 06:03:09 +02:00
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
return data;
|
|
|
|
},
|
|
|
|
errorMessages: {
|
|
|
|
// errorMessages for all error codes suggested from the plugin author, some will be overwritten by the config coming from php
|
|
|
|
1: i18n._t('UploadField.PHP_MAXFILESIZE'),
|
|
|
|
2: i18n._t('UploadField.HTML_MAXFILESIZE'),
|
|
|
|
3: i18n._t('UploadField.ONLYPARTIALUPLOADED'),
|
|
|
|
4: i18n._t('UploadField.NOFILEUPLOADED'),
|
|
|
|
5: i18n._t('UploadField.NOTMPFOLDER'),
|
|
|
|
6: i18n._t('UploadField.WRITEFAILED'),
|
|
|
|
7: i18n._t('UploadField.STOPEDBYEXTENSION'),
|
|
|
|
maxFileSize: i18n._t('UploadField.TOOLARGESHORT'),
|
|
|
|
minFileSize: i18n._t('UploadField.TOOSMALL'),
|
|
|
|
acceptFileTypes: i18n._t('UploadField.INVALIDEXTENSIONSHORT'),
|
|
|
|
maxNumberOfFiles: i18n._t('UploadField.MAXNUMBEROFFILESSHORT'),
|
|
|
|
uploadedBytes: i18n._t('UploadField.UPLOADEDBYTES'),
|
|
|
|
emptyResult: i18n._t('UploadField.EMPTYRESULT')
|
|
|
|
},
|
|
|
|
send: function(e, data) {
|
|
|
|
if (data.context && data.dataType && data.dataType.substr(0, 6) === 'iframe') {
|
|
|
|
// Iframe Transport does not support progress events.
|
|
|
|
// In lack of an indeterminate progress bar, we set
|
|
|
|
// the progress to 100%, showing the full animated bar:
|
|
|
|
data.total = 1;
|
|
|
|
data.loaded = 1;
|
|
|
|
$(this).data('fileupload').options.progress(e, data);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
progress: function(e, data) {
|
|
|
|
if (data.context) {
|
|
|
|
var value = parseInt(data.loaded / data.total * 100, 10) + '%';
|
|
|
|
data.context.find('.ss-uploadfield-item-status').html((data.total == 1)?i18n._t('UploadField.LOADING'):value);
|
|
|
|
data.context.find('.ss-uploadfield-item-progressbarvalue').css('width', value);
|
|
|
|
}
|
|
|
|
}
|
2016-07-28 06:03:09 +02:00
|
|
|
},
|
|
|
|
config,
|
2016-01-11 02:25:30 +01:00
|
|
|
{
|
|
|
|
fileInput: $fileInput,
|
|
|
|
dropZone: $dropZone,
|
|
|
|
form: $fileInput.closest('form'),
|
|
|
|
previewAsCanvas: false,
|
|
|
|
acceptFileTypes: new RegExp(config.acceptFileTypes, 'i')
|
|
|
|
}
|
|
|
|
));
|
|
|
|
|
|
|
|
if (this.data('fileupload')._isXHRUpload({multipart: true})) {
|
|
|
|
$('.ss-uploadfield-item-uploador').hide().show();
|
|
|
|
}
|
|
|
|
|
|
|
|
this._super();
|
|
|
|
},
|
|
|
|
onunmatch: function() {
|
|
|
|
$('.ss-uploadfield-dropzone').off('dragover dragenter dragleave drop');
|
|
|
|
this._super();
|
|
|
|
},
|
|
|
|
openSelectDialog: function(uploadedFile) {
|
|
|
|
// Create dialog and load iframe
|
|
|
|
var self = this, config = this.getConfig(), dialogId = 'ss-uploadfield-dialog-' + this.attr('id'), dialog = jQuery('#' + dialogId);
|
|
|
|
if(!dialog.length) dialog = jQuery('<div class="ss-uploadfield-dialog" id="' + dialogId + '" />');
|
2016-07-28 06:03:09 +02:00
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
// If user selected 'Choose another file', we need the ID of the file to replace
|
|
|
|
var iframeUrl = config['urlSelectDialog'];
|
|
|
|
var uploadedFileId = null;
|
|
|
|
if (uploadedFile && uploadedFile.attr('data-fileid') > 0){
|
|
|
|
uploadedFileId = uploadedFile.attr('data-fileid');
|
|
|
|
}
|
2016-07-28 06:03:09 +02:00
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
// Show dialog
|
|
|
|
dialog.ssdialog({iframeUrl: iframeUrl, height: 550});
|
|
|
|
|
|
|
|
// TODO Allow single-select
|
|
|
|
dialog.find('iframe').bind('load', function(e) {
|
2016-07-01 03:37:29 +02:00
|
|
|
var contents = $(this).contents(), gridField = contents.find('.grid-field');
|
2016-01-11 02:25:30 +01:00
|
|
|
// TODO Fix jQuery custom event bubbling across iframes on same domain
|
|
|
|
// gridField.find('.ss-gridfield-items')).bind('selectablestop', function() {
|
|
|
|
// });
|
|
|
|
|
|
|
|
// Remove top margin (easier than including new selectors)
|
2016-07-01 03:37:29 +02:00
|
|
|
contents.find('table.grid-field').css('margin-top', 0);
|
2016-01-11 02:25:30 +01:00
|
|
|
|
|
|
|
// Can't use live() in iframes...
|
|
|
|
contents.find('input[name=action_doAttach]').unbind('click.openSelectDialog').bind('click.openSelectDialog', function() {
|
|
|
|
// TODO Fix entwine method calls across iframe/document boundaries
|
|
|
|
var ids = $.map(gridField.find('.ss-gridfield-item.ui-selected'), function(el) {return $(el).data('id');});
|
|
|
|
if(ids && ids.length) self.attachFiles(ids, uploadedFileId);
|
|
|
|
|
|
|
|
dialog.ssdialog('close');
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
dialog.ssdialog('open');
|
|
|
|
},
|
|
|
|
attachFiles: function(ids, uploadedFileId) {
|
|
|
|
var self = this,
|
|
|
|
config = this.getConfig(),
|
|
|
|
indicator = $('<div class="loader" />'),
|
|
|
|
target = (uploadedFileId) ? this.find(".ss-uploadfield-item[data-fileid='"+uploadedFileId+"']") : this.find('.ss-uploadfield-addfile');
|
|
|
|
|
|
|
|
target.children().hide();
|
|
|
|
target.append(indicator);
|
|
|
|
|
|
|
|
$.ajax({
|
|
|
|
type: "POST",
|
|
|
|
url: config['urlAttach'],
|
|
|
|
data: {'ids': ids},
|
|
|
|
complete: function(xhr, status) {
|
|
|
|
target.children().show();
|
|
|
|
indicator.remove();
|
|
|
|
},
|
|
|
|
success: function(data, status, xhr) {
|
|
|
|
if (!data || $.isEmptyObject(data)) return;
|
|
|
|
|
|
|
|
self.fileupload('attach', {
|
|
|
|
files: data,
|
|
|
|
options: self.fileupload('option'),
|
|
|
|
replaceFileID: uploadedFileId
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
$('div.ss-upload *').entwine({
|
|
|
|
getUploadField: function() {
|
2016-07-28 06:03:09 +02:00
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
return this.parents('div.ss-upload:first');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
$('div.ss-upload .ss-uploadfield-files .ss-uploadfield-item').entwine({
|
|
|
|
onadd: function() {
|
|
|
|
this._super();
|
|
|
|
this.closest('.ss-upload').find('.ss-uploadfield-addfile').addClass('borderTop');
|
|
|
|
},
|
|
|
|
onremove: function() {
|
|
|
|
$('.ss-uploadfield-files:not(:has(.ss-uploadfield-item))').closest('.ss-upload').find('.ss-uploadfield-addfile').removeClass('borderTop');
|
|
|
|
this._super();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
$('div.ss-upload .ss-uploadfield-startall').entwine({
|
|
|
|
onclick: function(e) {
|
|
|
|
this.closest('.ss-upload').find('.ss-uploadfield-item-start button').click();
|
|
|
|
e.preventDefault(); // Avoid a form submit
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
$('div.ss-upload .ss-uploadfield-item-cancelfailed').entwine({
|
|
|
|
onclick: function(e) {
|
|
|
|
this.closest('.ss-uploadfield-item').remove();
|
|
|
|
e.preventDefault(); // Avoid a form submit
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
$('div.ss-upload .ss-uploadfield-item-remove:not(.ui-state-disabled), .ss-uploadfield-item-delete:not(.ui-state-disabled)').entwine({
|
|
|
|
onclick: function(e) {
|
|
|
|
var field = this.closest('div.ss-upload'),
|
|
|
|
config = field.getConfig('changeDetection'),
|
2016-07-28 06:03:09 +02:00
|
|
|
fileupload = field.data('fileupload'),
|
2016-01-11 02:25:30 +01:00
|
|
|
item = this.closest('.ss-uploadfield-item'), msg = '';
|
2016-07-28 06:03:09 +02:00
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
if(this.is('.ss-uploadfield-item-delete')) {
|
|
|
|
if(confirm(i18n._t('UploadField.ConfirmDelete'))) {
|
|
|
|
if(config.changeDetection) {
|
|
|
|
this.closest('form').trigger('dirty');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fileupload) {
|
|
|
|
fileupload._trigger('destroy', e, {
|
|
|
|
context: item,
|
|
|
|
url: this.data('href'),
|
|
|
|
type: 'get',
|
|
|
|
dataType: fileupload.options.dataType
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Removed files will be applied to object on save
|
|
|
|
if(config.changeDetection) {
|
|
|
|
this.closest('form').trigger('dirty');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fileupload) {
|
|
|
|
fileupload._trigger('destroy', e, {context: item});
|
|
|
|
}
|
|
|
|
}
|
2016-07-28 06:03:09 +02:00
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
e.preventDefault(); // Avoid a form submit
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
$('div.ss-upload .ss-uploadfield-item-edit-all').entwine({
|
|
|
|
onclick: function(e) {
|
|
|
|
|
|
|
|
if($(this).hasClass('opened')){
|
|
|
|
$('.ss-uploadfield-item .ss-uploadfield-item-edit .toggle-details-icon.opened').each(function(i){
|
|
|
|
$(this).closest('.ss-uploadfield-item-edit').click();
|
|
|
|
});
|
|
|
|
$(this).removeClass('opened').find('.toggle-details-icon').removeClass('opened');
|
|
|
|
}else{
|
|
|
|
$('.ss-uploadfield-item .ss-uploadfield-item-edit .toggle-details-icon').each(function(i){
|
2016-07-28 06:03:09 +02:00
|
|
|
if(!$(this).hasClass('opened')){
|
2016-01-11 02:25:30 +01:00
|
|
|
$(this).closest('.ss-uploadfield-item-edit').click();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
$(this).addClass('opened').find('.toggle-details-icon').addClass('opened');
|
|
|
|
}
|
|
|
|
|
|
|
|
e.preventDefault(); // Avoid a form submit
|
|
|
|
return false;
|
2016-07-28 06:03:09 +02:00
|
|
|
}
|
2016-01-11 02:25:30 +01:00
|
|
|
});
|
|
|
|
$( 'div.ss-upload:not(.disabled):not(.readonly) .ss-uploadfield-item-edit').entwine({
|
|
|
|
onclick: function(e) {
|
|
|
|
var self = this,
|
|
|
|
editform = self.closest('.ss-uploadfield-item').find('.ss-uploadfield-item-editform'),
|
|
|
|
itemInfo = editform.prev('.ss-uploadfield-item-info'),
|
|
|
|
iframe = editform.find('iframe');
|
|
|
|
|
|
|
|
// Ignore clicks while the iframe is loading
|
|
|
|
if (iframe.parent().hasClass('loading')) {
|
|
|
|
e.preventDefault();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iframe.attr('src') == 'about:blank') {
|
2016-02-19 03:05:54 +01:00
|
|
|
var disabled = this.siblings();
|
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
// Lazy-load the iframe on editform toggle
|
|
|
|
iframe.attr('src', iframe.data('src'));
|
|
|
|
|
|
|
|
// Add loading class, disable buttons while loading is in progress
|
|
|
|
// (_prepareIframe() handles re-enabling them when appropriate)
|
|
|
|
iframe.parent().addClass('loading');
|
|
|
|
disabled.addClass('ui-state-disabled');
|
|
|
|
disabled.attr('disabled', 'disabled');
|
|
|
|
|
|
|
|
iframe.on('load', function() {
|
|
|
|
iframe.parent().removeClass('loading');
|
|
|
|
|
|
|
|
// This ensures we only call _prepareIframe() on load once - otherwise it'll
|
|
|
|
// be superfluously called after clicking 'save' in the editform
|
|
|
|
if (iframe.data('src')) {
|
|
|
|
self._prepareIframe(iframe, editform, itemInfo);
|
|
|
|
iframe.data('src', '');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
self._prepareIframe(iframe, editform, itemInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
e.preventDefault(); // Avoid a form submit
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
_prepareIframe: function(iframe, editform, itemInfo) {
|
|
|
|
var disabled;
|
2016-07-28 06:03:09 +02:00
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
// Mark the row as changed if any of its form fields are edited
|
|
|
|
iframe.contents().ready(function() {
|
|
|
|
// Need to use the iframe's own jQuery, as custom event triggers
|
|
|
|
// (e.g. from TreeDropdownField) can't be captured by the parent jQuery object.
|
|
|
|
var iframe_jQuery = iframe.get(0).contentWindow.jQuery;
|
|
|
|
iframe_jQuery(iframe_jQuery.find(':input')).bind('change', function(e){
|
2016-07-28 06:03:09 +02:00
|
|
|
editform.removeClass('edited');
|
|
|
|
editform.addClass('edited');
|
2016-01-11 02:25:30 +01:00
|
|
|
});
|
|
|
|
});
|
2016-07-28 06:03:09 +02:00
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
if (editform.hasClass('loading')) {
|
2016-07-28 06:03:09 +02:00
|
|
|
// TODO Display loading indication, and register an event to toggle edit form
|
2016-01-11 02:25:30 +01:00
|
|
|
} else {
|
|
|
|
if(this.hasClass('ss-uploadfield-item-edit')){
|
|
|
|
disabled=this.siblings();
|
|
|
|
}else{
|
|
|
|
disabled=this.find('ss-uploadfield-item-edit').siblings();
|
|
|
|
}
|
|
|
|
editform.parent('.ss-uploadfield-item').removeClass('ui-state-warning');
|
|
|
|
editform.toggleEditForm();
|
2016-07-28 06:03:09 +02:00
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
if (itemInfo.find('.toggle-details-icon').hasClass('opened')) {
|
|
|
|
disabled.addClass('ui-state-disabled');
|
|
|
|
disabled.attr('disabled', 'disabled');
|
|
|
|
} else {
|
|
|
|
disabled.removeClass('ui-state-disabled');
|
|
|
|
disabled.removeAttr('disabled');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$('div.ss-upload .ss-uploadfield-item-editform').entwine({
|
|
|
|
fitHeight: function() {
|
|
|
|
var iframe = this.find('iframe'),
|
|
|
|
contents = iframe.contents().find('body'),
|
|
|
|
bodyH = contents.find('form').outerHeight(true), // We set the height to match the form's outer height
|
|
|
|
iframeH = bodyH + (iframe.outerHeight(true) - iframe.height()), // content's height + padding on iframe elem
|
|
|
|
containerH = iframeH + (this.outerHeight(true) - this.height()); // iframe height + padding on container elem
|
|
|
|
|
|
|
|
/* Set height of body except in IE8. Setting this in IE8 breaks the dropdown */
|
|
|
|
if( ! $.browser.msie && $.browser.version.slice(0,3) != "8.0"){
|
2016-07-28 06:03:09 +02:00
|
|
|
contents.find('body').css({'height': bodyH});
|
|
|
|
}
|
|
|
|
|
2016-01-11 02:25:30 +01:00
|
|
|
iframe.height(iframeH);
|
|
|
|
this.animate({height: containerH}, 500);
|
|
|
|
},
|
|
|
|
toggleEditForm: function() {
|
|
|
|
var itemInfo = this.prev('.ss-uploadfield-item-info'), status = itemInfo.find('.ss-uploadfield-item-status');
|
|
|
|
|
|
|
|
var iframe = this.find('iframe').contents(),
|
|
|
|
saved = iframe.find('#Form_EditForm_error');
|
|
|
|
|
|
|
|
var text = "";
|
|
|
|
|
|
|
|
if(this.height() === 0) {
|
|
|
|
text = i18n._t('UploadField.Editing', "Editing ...");
|
|
|
|
this.fitHeight();
|
|
|
|
this.addClass('opened');
|
2016-07-28 06:03:09 +02:00
|
|
|
itemInfo.find('.toggle-details-icon').addClass('opened');
|
2016-01-11 02:25:30 +01:00
|
|
|
status.removeClass('ui-state-success-text').removeClass('ui-state-warning-text');
|
|
|
|
iframe.find('#Form_EditForm_action_doEdit').click(function(){
|
|
|
|
itemInfo.find('label .name').text(iframe.find('#Name input').val());
|
2016-07-28 06:03:09 +02:00
|
|
|
});
|
2016-01-11 02:25:30 +01:00
|
|
|
if($('div.ss-upload .ss-uploadfield-files .ss-uploadfield-item-actions .toggle-details-icon:not(.opened)').index() < 0){
|
|
|
|
$('div.ss-upload .ss-uploadfield-item-edit-all').addClass('opened').find('.toggle-details-icon').addClass('opened');
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2016-07-28 06:03:09 +02:00
|
|
|
this.animate({height: 0}, 500);
|
2016-01-11 02:25:30 +01:00
|
|
|
this.removeClass('opened');
|
|
|
|
itemInfo.find('.toggle-details-icon').removeClass('opened');
|
|
|
|
$('div.ss-upload .ss-uploadfield-item-edit-all').removeClass('opened').find('.toggle-details-icon').removeClass('opened');
|
|
|
|
if(!this.hasClass('edited')){
|
|
|
|
text = i18n._t('UploadField.NOCHANGES', 'No Changes');
|
|
|
|
status.addClass('ui-state-success-text');
|
|
|
|
}else{
|
|
|
|
if(saved.hasClass('good')){
|
|
|
|
text = i18n._t('UploadField.CHANGESSAVED', 'Changes Saved');
|
|
|
|
this.removeClass('edited').parent('.ss-uploadfield-item').removeClass('ui-state-warning');
|
2016-07-28 06:03:09 +02:00
|
|
|
status.addClass('ui-state-success-text');
|
2016-01-11 02:25:30 +01:00
|
|
|
}else{
|
|
|
|
text = i18n._t('UploadField.UNSAVEDCHANGES', 'Unsaved Changes');
|
|
|
|
this.parent('.ss-uploadfield-item').addClass('ui-state-warning');
|
|
|
|
status.addClass('ui-state-warning-text');
|
2016-07-28 06:03:09 +02:00
|
|
|
}
|
2016-01-11 02:25:30 +01:00
|
|
|
}
|
|
|
|
saved.removeClass('good').hide();
|
|
|
|
}
|
2016-07-28 06:03:09 +02:00
|
|
|
status.attr('title',text).text(text);
|
2016-01-11 02:25:30 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
$('div.ss-upload .ss-uploadfield-fromfiles').entwine({
|
|
|
|
onclick: function(e) {
|
|
|
|
this.getUploadField().openSelectDialog(this.closest('.ss-uploadfield-item'));
|
|
|
|
e.preventDefault(); // Avoid a form submit
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|