2022-03-08 15:55:41 +01:00
|
|
|
$(document).ready(function() {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Setup a live change event for the delete links
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
// not IE < 9
|
|
|
|
$(document).on('change', '.InputfieldFileDelete input', function() {
|
|
|
|
setInputfieldFileStatus($(this));
|
|
|
|
|
|
|
|
}).on('dblclick', '.InputfieldFileDelete', function() {
|
|
|
|
// enable double-click to delete all
|
|
|
|
var $input = $(this).find('input');
|
|
|
|
var $items = $(this).parents('.InputfieldFileList').find('.InputfieldFileDelete input');
|
|
|
|
if($input.is(":checked")) {
|
2024-04-04 14:37:20 +02:00
|
|
|
$items.prop('checked', false).trigger('change');
|
2022-03-08 15:55:41 +01:00
|
|
|
} else {
|
2024-04-04 14:37:20 +02:00
|
|
|
$items.prop('checked', true).trigger('change');
|
2022-03-08 15:55:41 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
function setInputfieldFileStatus($t) {
|
|
|
|
var $info = $t.parents('.InputfieldFileInfo');
|
|
|
|
// collapsed=items that have no description or tags, so need no visible InputfieldFileData container
|
|
|
|
var collapsed = $t.closest('.InputfieldFile').hasClass('InputfieldItemListCollapse');
|
|
|
|
if($t.is(":checked")) {
|
|
|
|
// not an error, but we want to highlight it in the same manner
|
|
|
|
$info.addClass("ui-state-error");
|
|
|
|
if(!collapsed) $info.siblings(".InputfieldFileData").slideUp("fast");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
$info.removeClass("ui-state-error");
|
|
|
|
if(!collapsed) $info.siblings(".InputfieldFileData").slideDown("fast");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make the lists sortable and hoverable
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
function initSortable($fileLists) {
|
|
|
|
|
|
|
|
$fileLists.each(function() {
|
|
|
|
|
|
|
|
var $this = $(this);
|
|
|
|
var qty = $this.children("li").length;
|
|
|
|
if($this.closest('.InputfieldRenderValueMode').length) return;
|
|
|
|
|
|
|
|
var $inputfield = $this.closest('.Inputfield')
|
|
|
|
|
|
|
|
if(qty < 2) {
|
|
|
|
// added to support additional controls when multiple items are present
|
|
|
|
// and to hide them when not present
|
|
|
|
if(qty == 0) $inputfield.addClass('InputfieldFileEmpty').removeClass('InputfieldFileMultiple InputfieldFileSingle');
|
|
|
|
else $inputfield.addClass('InputfieldFileSingle').removeClass('InputfieldFileEmpty InputfieldFileMultiple');
|
|
|
|
// if we're dealing with a single item list, then don't continue with making it sortable
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
$this.closest('.Inputfield').removeClass('InputfieldFileSingle InputfieldFileEmpty').addClass('InputfieldFileMultiple');
|
|
|
|
}
|
|
|
|
|
|
|
|
$this.sortable({
|
|
|
|
//axis: 'y',
|
|
|
|
start: function(e, ui) {
|
|
|
|
ui.item.children(".InputfieldFileInfo").addClass("ui-state-highlight");
|
|
|
|
},
|
|
|
|
stop: function(e, ui) {
|
|
|
|
$(this).children("li").each(function(n) {
|
|
|
|
$(this).find(".InputfieldFileSort").val(n);
|
|
|
|
});
|
|
|
|
ui.item.children(".InputfieldFileInfo").removeClass("ui-state-highlight");
|
|
|
|
// Firefox has a habit of opening a lightbox popup after a lightbox trigger was used as a sort handle
|
|
|
|
// so we keep a 500ms class here to keep a handle on what was a lightbox trigger and what was a sort
|
|
|
|
$inputfield.addClass('InputfieldFileJustSorted InputfieldStateChanged');
|
|
|
|
setTimeout(function() { $inputfield.removeClass('InputfieldFileJustSorted'); }, 500);
|
2022-11-05 18:32:48 +01:00
|
|
|
},
|
|
|
|
update: function(e, ui) {
|
|
|
|
$inputfield.trigger('sorted', [ ui.item ]);
|
2022-03-08 15:55:41 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2024-04-04 14:37:20 +02:00
|
|
|
}).find(".ui-widget-header, .ui-state-default").on('mouseenter', function() {
|
2022-03-08 15:55:41 +01:00
|
|
|
$(this).addClass('ui-state-hover');
|
2024-04-04 14:37:20 +02:00
|
|
|
}).on('mouseleave', function() {
|
2022-03-08 15:55:41 +01:00
|
|
|
$(this).removeClass('ui-state-hover');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function InitOldSchool() {
|
|
|
|
$("body").addClass("ie-no-drop"); // ??
|
|
|
|
|
|
|
|
$(document).on('change', '.InputfieldFileUpload input[type=file]', function() {
|
|
|
|
|
|
|
|
var $t = $(this);
|
|
|
|
var $mask = $t.closest(".InputMask");
|
|
|
|
|
|
|
|
if($t.val().length > 1) {
|
|
|
|
$mask.addClass("ui-state-disabled");
|
|
|
|
} else {
|
|
|
|
$mask.removeClass("ui-state-disabled");
|
|
|
|
}
|
|
|
|
|
|
|
|
if($mask.next(".InputMask").length > 0) return; // not the last one
|
|
|
|
|
|
|
|
var $inputfield = $t.closest('.InputfieldFile');
|
|
|
|
var $upload = $t.closest('.InputfieldFileUpload');
|
|
|
|
var $list = $inputfield.find('.InputfieldFileList');
|
|
|
|
var maxFiles = parseInt($upload.find('.InputfieldFileMaxFiles').val());
|
|
|
|
var numFiles = $list.children('li').length + $upload.find('input[type=file]').length + 1;
|
|
|
|
var maxFilesize = parseInt($upload.attr('data-maxfilesize'));
|
|
|
|
|
|
|
|
var abort = false;
|
|
|
|
$upload.find("input[type=file]").each(function() {
|
|
|
|
if(typeof this.files[0] !== 'undefined'){
|
|
|
|
var size = this.files[0].size;
|
|
|
|
if(size > maxFilesize) {
|
|
|
|
ProcessWire.alert(
|
|
|
|
"File " + this.files[0].name +" is " + size + " bytes which exceeds max allowed size of " + maxFilesize + " bytes"
|
|
|
|
);
|
|
|
|
$(this).val('').closest('.InputMask').removeClass('ui-state-disabled ui-state-active');
|
|
|
|
abort = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if(abort) return false;
|
|
|
|
|
|
|
|
if(maxFiles > 0 && numFiles >= maxFiles) {
|
|
|
|
// no more files allowed
|
|
|
|
} else {
|
|
|
|
$upload.find(".InputMask").not(":last").each(function() {
|
|
|
|
var $m = $(this);
|
|
|
|
if($m.find("input[type=file]").val() < 1) $m.remove();
|
|
|
|
});
|
|
|
|
|
|
|
|
// add another input
|
|
|
|
var $mask2 = $mask.clone().removeClass("ui-state-disabled");
|
|
|
|
var $input = $mask2.find('input[type=file]');
|
|
|
|
$input.attr('id', $input.attr('id') + '-');
|
|
|
|
$input.val('');
|
|
|
|
$mask2.insertAfter($mask);
|
|
|
|
$mask2.css('margin-left', '0.5em').removeClass('ui-state-active');
|
|
|
|
}
|
|
|
|
|
|
|
|
// update file input to contain file name
|
|
|
|
var name = $t.val();
|
|
|
|
var pos = name.lastIndexOf('/');
|
|
|
|
if(pos === -1) pos = name.lastIndexOf('\\');
|
|
|
|
name = name.substring(pos+1);
|
|
|
|
$mask.find('.ui-button-text').text(name).prepend("<i class='fa fa-fw fa-file-o'></i>");
|
|
|
|
$mask.removeClass('ui-state-active');
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize HTML5 uploads
|
|
|
|
*
|
|
|
|
* By apeisa with additional code by Ryan
|
|
|
|
*
|
|
|
|
* Based on the great work and examples of Craig Buckler (http://www.sitepoint.com/html5-file-drag-and-drop/)
|
|
|
|
* and Robert Nyman (http://robertnyman.com/html5/fileapi-upload/fileapi-upload.html)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
function InitHTML5($inputfield) {
|
|
|
|
|
|
|
|
if($inputfield.length > 0) {
|
|
|
|
var $target = $inputfield.find(".InputfieldFileUpload"); // just one
|
|
|
|
} else {
|
|
|
|
var $target = $(".InputfieldFileUpload"); // all
|
|
|
|
}
|
|
|
|
$target.closest('.InputfieldContent').each(function (i) {
|
|
|
|
if($(this).hasClass('InputfieldFileInit')) return;
|
|
|
|
initHTML5Item($(this), i);
|
|
|
|
$(this).addClass('InputfieldFileInit');
|
|
|
|
});
|
|
|
|
|
|
|
|
function initHTML5Item($this, i) {
|
|
|
|
|
|
|
|
var $form = $this.parents('form');
|
|
|
|
var $repeaterItem = $this.closest('.InputfieldRepeaterItem');
|
|
|
|
var postUrl = $repeaterItem.length ? $repeaterItem.attr('data-editUrl') : $form.attr('action');
|
|
|
|
postUrl += (postUrl.indexOf('?') > -1 ? '&' : '?') + 'InputfieldFileAjax=1';
|
|
|
|
|
|
|
|
// CSRF protection
|
|
|
|
var $postToken = $form.find('input._post_token');
|
|
|
|
var postTokenName = $postToken.attr('name');
|
|
|
|
var postTokenValue = $postToken.val();
|
|
|
|
var $uploadData = $this.find('.InputfieldFileUpload');
|
|
|
|
|
|
|
|
var fieldName = $uploadData.data('fieldname');
|
|
|
|
fieldName = fieldName.slice(0,-2);
|
|
|
|
|
|
|
|
var extensions = $uploadData.data('extensions').toLowerCase();
|
|
|
|
var maxFilesize = $uploadData.data('maxfilesize');
|
|
|
|
|
|
|
|
var filesUpload = $this.find("input[type=file]").get(0);
|
|
|
|
var dropArea = $this.get(0);
|
|
|
|
var $fileList = $this.find(".InputfieldFileList");
|
|
|
|
|
|
|
|
if($fileList.length < 1) {
|
|
|
|
$fileList = $("<ul class='InputfieldFileList InputfieldFileListBlank'></ul>");
|
|
|
|
$this.prepend($fileList);
|
|
|
|
$this.parent('.Inputfield').addClass('InputfieldFileEmpty');
|
|
|
|
}
|
|
|
|
|
|
|
|
var fileList = $fileList.get(0);
|
|
|
|
var maxFiles = parseInt($this.find('.InputfieldFileMaxFiles').val());
|
|
|
|
|
|
|
|
$fileList.children().addClass('InputfieldFileItemExisting'); // identify items that are already there
|
|
|
|
|
|
|
|
$this.find('.AjaxUploadDropHere').show();
|
|
|
|
|
|
|
|
var doneTimer = null; // for AjaxUploadDone event
|
|
|
|
|
|
|
|
function uploadFile(file) {
|
|
|
|
|
|
|
|
var $progressItem = $('<li class="InputfieldFile ui-widget AjaxUpload"><p class="InputfieldFileInfo ui-widget ui-widget-header InputfieldItemHeader"></p></li>'),
|
|
|
|
$progressBar = $('<div class="ui-progressbar ui-widget ui-widget-content ui-corner-all" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"></div>'),
|
|
|
|
$progressBarValue = $('<div class="ui-progressbar-value ui-widget-header InputfieldItemHeader ui-corner-left" style="width: 0%; "></div>'),
|
|
|
|
img,
|
|
|
|
reader,
|
|
|
|
xhr,
|
|
|
|
fileData;
|
|
|
|
|
|
|
|
$progressBar.append($progressBarValue);
|
|
|
|
$progressItem.append($progressBar);
|
|
|
|
|
|
|
|
// Uploading - for Firefox, Google Chrome and Safari
|
|
|
|
xhr = new XMLHttpRequest();
|
|
|
|
|
|
|
|
// Update progress bar
|
|
|
|
xhr.upload.addEventListener("progress", function (evt) {
|
|
|
|
if(evt.lengthComputable) {
|
|
|
|
var completion = (evt.loaded / evt.total) * 100;
|
|
|
|
$progressBarValue.width(completion + "%");
|
|
|
|
if(completion > 4) {
|
|
|
|
$progressBarValue.html("<span>" + parseInt(completion) + "%</span>");
|
|
|
|
}
|
|
|
|
$('body').addClass('pw-uploading');
|
|
|
|
/*
|
|
|
|
// code for freezing progressbar during testing
|
|
|
|
$progressBarValue.width("60%");
|
|
|
|
if(completion > 50) setTimeout(function() { alert('test'); }, 10);
|
|
|
|
*/
|
|
|
|
} else {
|
|
|
|
// No data to calculate on
|
|
|
|
}
|
|
|
|
}, false);
|
|
|
|
|
|
|
|
|
|
|
|
// File uploaded: called for each file
|
|
|
|
xhr.addEventListener("load", function() {
|
|
|
|
xhr.getAllResponseHeaders();
|
|
|
|
|
2024-04-04 14:37:20 +02:00
|
|
|
var response = JSON.parse(xhr.responseText);
|
2022-03-08 15:55:41 +01:00
|
|
|
if(response.error !== undefined) response = [response];
|
|
|
|
|
|
|
|
// note the following loop will always contain only 1 item, unless a file containing more files (ZIP file) was uploaded
|
|
|
|
for(var n = 0; n < response.length; n++) {
|
|
|
|
|
|
|
|
var r = response[n];
|
|
|
|
|
|
|
|
if(r.error) {
|
|
|
|
var $pi = $progressItem.clone();
|
|
|
|
$pi.find(".InputfieldFileInfo").addClass('ui-state-error');
|
|
|
|
$pi.find(".InputfieldFileStats").text(' - ' + r.message);
|
|
|
|
$pi.find(".ui-progressbar").remove();
|
|
|
|
$progressItem.after($pi);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if(r.replace) {
|
2024-04-04 14:37:20 +02:00
|
|
|
var $child = $this.find('.InputfieldFileList').children('li').first();
|
2022-03-08 15:55:41 +01:00
|
|
|
if($child.length > 0) $child.slideUp('fast', function() { $child.remove(); });
|
|
|
|
}
|
|
|
|
|
|
|
|
// ie10 file field stays populated, this fixes that
|
|
|
|
var $input = $this.find('input[type=file]');
|
|
|
|
if($input.val()) $input.replaceWith($input.clone(true));
|
|
|
|
|
|
|
|
var $markup = $(r.markup);
|
|
|
|
$markup.hide();
|
|
|
|
|
|
|
|
// look for and handle replacements
|
|
|
|
if(r.overwrite) {
|
|
|
|
var basename = $markup.find('.InputfieldFileName').text();
|
|
|
|
var $item = null;
|
|
|
|
// find an existing item having the same basename
|
|
|
|
$fileList.children('.InputfieldFileItemExisting').each(function() {
|
|
|
|
if($item === null && $(this).find('.InputfieldFileName').text() == basename) {
|
|
|
|
// filenames match
|
|
|
|
$item = $(this);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if($item !== null) {
|
|
|
|
// found replacement
|
|
|
|
var $newInfo = $markup.find(".InputfieldFileInfo");
|
|
|
|
var $newLink = $markup.find(".InputfieldFileLink");
|
|
|
|
var $info = $item.find(".InputfieldFileInfo");
|
|
|
|
var $link = $item.find(".InputfieldFileLink");
|
|
|
|
$info.html($newInfo.html() + "<i class='fa fa-check'></i>");
|
|
|
|
$link.html($newLink.html());
|
|
|
|
$item.addClass('InputfieldFileItemExisting');
|
|
|
|
$item.effect('highlight', 500);
|
|
|
|
} else {
|
|
|
|
// didn't find a match, just append
|
|
|
|
$fileList.append($markup);
|
|
|
|
$markup.slideDown();
|
|
|
|
$markup.addClass('InputfieldFileItemExisting');
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// overwrite mode not active
|
|
|
|
$fileList.append($markup);
|
|
|
|
$markup.slideDown();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(function() {
|
|
|
|
var $inputfields = $markup.find('.Inputfield');
|
|
|
|
if($inputfields.length) {
|
|
|
|
InputfieldsInit($markup.find('.Inputfields'));
|
|
|
|
$inputfields.trigger('reloaded', ['InputfieldFileUpload']);
|
|
|
|
}
|
|
|
|
}, 500);
|
|
|
|
|
|
|
|
} // for
|
|
|
|
|
|
|
|
$progressItem.remove();
|
|
|
|
|
|
|
|
if(doneTimer) clearTimeout(doneTimer);
|
|
|
|
doneTimer = setTimeout(function() {
|
|
|
|
$('body').removeClass('pw-uploading');
|
|
|
|
if(maxFiles != 1 && !$fileList.is('.ui-sortable')) initSortable($fileList);
|
|
|
|
$fileList.trigger('AjaxUploadDone'); // for things like fancybox that need to be re-init'd
|
|
|
|
}, 500);
|
|
|
|
|
|
|
|
}, false);
|
|
|
|
|
|
|
|
// Here we go
|
|
|
|
xhr.open("POST", postUrl, true);
|
|
|
|
//see:https://github.com/ryancramerdesign/ProcessWire/issues/1487
|
|
|
|
//xhr.setRequestHeader("X-FILENAME", unescape(encodeURIComponent(file.name)));
|
|
|
|
xhr.setRequestHeader("X-FILENAME", encodeURIComponent(file.name));
|
|
|
|
xhr.setRequestHeader("X-FIELDNAME", fieldName);
|
|
|
|
xhr.setRequestHeader("Content-Type", "application/octet-stream"); // fix issue 96-Pete
|
|
|
|
xhr.setRequestHeader("X-" + postTokenName, postTokenValue);
|
|
|
|
xhr.setRequestHeader("X-REQUESTED-WITH", 'XMLHttpRequest');
|
|
|
|
xhr.send(file);
|
|
|
|
|
|
|
|
// Present file info and append it to the list of files
|
|
|
|
fileData = '' +
|
|
|
|
"<i class='fa fa-fw fa-spin fa-spinner'></i> " +
|
|
|
|
'<span class="InputfieldFileName">' + file.name + '</span>' +
|
|
|
|
'<span class="InputfieldFileStats"> • ' + parseInt(file.size / 1024, 10) + " kb</span>";
|
|
|
|
|
|
|
|
$progressItem.find('p.ui-widget-header').html(fileData);
|
|
|
|
$fileList.append($progressItem);
|
|
|
|
var $inputfield = $fileList.closest('.Inputfield');
|
|
|
|
$inputfield.addClass('InputfieldStateChanged');
|
|
|
|
var numFiles = $inputfield.find('.InputfieldFileItem').length;
|
|
|
|
if(numFiles == 1) {
|
|
|
|
$inputfield.removeClass('InputfieldFileEmpty').removeClass('InputfieldFileMultiple').addClass('InputfieldFileSingle');
|
|
|
|
} else if(numFiles > 1) {
|
|
|
|
$inputfield.removeClass('InputfieldFileEmpty').removeClass('InputfieldFileSingle').addClass('InputfieldFileMultiple');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function traverseFiles(files) {
|
|
|
|
|
|
|
|
function errorItem(filename, message) {
|
|
|
|
return '<li class="InputfieldFile ui-widget AjaxUpload">' +
|
|
|
|
'<p class="InputfieldFileInfo ui-widget ui-widget-header InputfieldItemHeader ui-state-error"> ' + filename + ' ' +
|
|
|
|
'<span class="InputfieldFileStats"> • ' + message + '</span></p></li>';
|
|
|
|
}
|
|
|
|
|
|
|
|
var errorMsg = '';
|
|
|
|
|
|
|
|
if(typeof files !== "undefined") {
|
|
|
|
for(var i=0, l=files.length; i<l; i++) {
|
|
|
|
|
|
|
|
var extension = files[i].name.split('.').pop().toLowerCase();
|
|
|
|
|
|
|
|
if(extensions.indexOf(extension) == -1) {
|
|
|
|
if(typeof ProcessWire.config.InputfieldFile.labels['bad-ext'] != "undefined") {
|
|
|
|
errorMsg = ProcessWire.config.InputfieldFile.labels['bad-ext'];
|
|
|
|
errorMsg = errorMsg.replace('EXTENSIONS', extensions);
|
|
|
|
} else {
|
|
|
|
errorMsg = extension + ' is a invalid file extension, please use one of: ' + extensions;
|
|
|
|
}
|
|
|
|
$fileList.append(errorItem(files[i].name, errorMsg));
|
|
|
|
|
|
|
|
} else if(files[i].size > maxFilesize && maxFilesize > 2000000) {
|
|
|
|
// I do this test only if maxFilesize is at least 2M (php default).
|
|
|
|
// There might (not sure though) be some issues to get that value so don't want to overvalidate here -apeisa
|
|
|
|
var maxKB = parseInt(maxFilesize / 1024, 10);
|
|
|
|
if(typeof ProcessWire.config.InputfieldFile.labels['too-big'] != "undefined") {
|
|
|
|
errorMsg = ProcessWire.config.InputfieldFile.labels['too-big'];
|
|
|
|
errorMsg = errorMsg.replace('MAX_KB', maxKB);
|
|
|
|
} else {
|
|
|
|
var fileSize = parseInt(files[i].size / 1024, 10);
|
|
|
|
errorMsg = 'Filesize ' + fileSize +' kb is too big. Maximum allowed is ' + maxKB + ' kb';
|
|
|
|
}
|
|
|
|
$fileList.append(errorItem(files[i].name, errorMsg));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
uploadFile(files[i]);
|
|
|
|
}
|
|
|
|
if(maxFiles == 1) break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fileList.innerHTML = "No support for the File API in this web browser";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
filesUpload.addEventListener("change", function(evt) {
|
|
|
|
traverseFiles(this.files);
|
|
|
|
evt.preventDefault();
|
|
|
|
evt.stopPropagation();
|
|
|
|
this.value = '';
|
|
|
|
}, false);
|
|
|
|
|
|
|
|
dropArea.addEventListener("dragleave", function() {
|
|
|
|
$(this).removeClass('ui-state-hover');
|
|
|
|
$(this).closest('.Inputfield').removeClass('pw-drag-in-file');
|
|
|
|
}, false);
|
|
|
|
dropArea.addEventListener("dragenter", function(evt) {
|
|
|
|
evt.preventDefault();
|
|
|
|
$(this).addClass('ui-state-hover');
|
|
|
|
$(this).closest('.Inputfield').addClass('pw-drag-in-file');
|
|
|
|
}, false);
|
|
|
|
|
|
|
|
dropArea.addEventListener("dragover", function (evt) {
|
|
|
|
if(!$(this).is('ui-state-hover')) {
|
|
|
|
$(this).addClass('ui-state-hover');
|
|
|
|
$(this).closest('.Inputfield').addClass('pw-drag-in-file');
|
|
|
|
}
|
|
|
|
evt.preventDefault();
|
|
|
|
evt.stopPropagation();
|
|
|
|
}, false);
|
|
|
|
|
|
|
|
dropArea.addEventListener("drop", function (evt) {
|
|
|
|
traverseFiles(evt.dataTransfer.files);
|
|
|
|
$(this).removeClass("ui-state-hover").closest('.Inputfield').removeClass('pw-drag-in-file');
|
|
|
|
evt.preventDefault();
|
|
|
|
evt.stopPropagation();
|
|
|
|
}, false);
|
|
|
|
} // initHTML5Item
|
|
|
|
} // initHTML5
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize selectize tags
|
|
|
|
*
|
|
|
|
* @param $inputfields
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
function initTags($inputfields) {
|
|
|
|
|
|
|
|
$inputfields.each(function() {
|
|
|
|
|
|
|
|
var $inputfield = $(this);
|
|
|
|
var $inputs = $inputfield.find('input.InputfieldFileTagsInput:not(.selectized)');
|
|
|
|
var $selects = $inputfield.find('input.InputfieldFileTagsSelect:not(.selectized)');
|
|
|
|
|
|
|
|
if($inputs.length) {
|
|
|
|
$inputs.selectize({
|
|
|
|
plugins: ['remove_button', 'drag_drop'],
|
|
|
|
delimiter: ' ',
|
|
|
|
persist: false,
|
|
|
|
createOnBlur: true,
|
|
|
|
submitOnReturn: false,
|
|
|
|
create: function(input) {
|
|
|
|
return {
|
|
|
|
value: input,
|
|
|
|
text: input
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if($selects.length) {
|
|
|
|
if(!$inputfield.hasClass('Inputfield')) $inputfield = $inputfield.closest('.Inputfield');
|
|
|
|
var configName = $inputfield.attr('data-configName');
|
|
|
|
var settings = ProcessWire.config[configName];
|
|
|
|
var options = [];
|
2023-03-10 19:41:40 +01:00
|
|
|
if(typeof settings === 'undefined') {
|
|
|
|
if(configName.indexOf('_repeater') > -1) {
|
|
|
|
configName = configName.replace(/_repeater\d+(_?)/, '$1');
|
|
|
|
settings = ProcessWire.config[configName];
|
|
|
|
if(typeof settings === 'undefined') settings = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(settings) {
|
|
|
|
for(var n = 0; n < settings['tags'].length; n++) {
|
|
|
|
var tag = settings['tags'][n];
|
|
|
|
options[n] = {value: tag};
|
|
|
|
}
|
2022-03-08 15:55:41 +01:00
|
|
|
}
|
|
|
|
$selects.selectize({
|
|
|
|
plugins: ['remove_button', 'drag_drop'],
|
|
|
|
delimiter: ' ',
|
|
|
|
persist: true,
|
|
|
|
submitOnReturn: false,
|
|
|
|
closeAfterSelect: true,
|
|
|
|
createOnBlur: true,
|
|
|
|
maxItems: null,
|
|
|
|
valueField: 'value',
|
|
|
|
labelField: 'value',
|
|
|
|
searchField: ['value'],
|
|
|
|
options: options,
|
|
|
|
create: function(input) {
|
|
|
|
return {
|
|
|
|
value: input,
|
|
|
|
text: input
|
|
|
|
}
|
|
|
|
},
|
|
|
|
createFilter: function(input) {
|
|
|
|
if(settings.allowUserTags) return true;
|
|
|
|
allow = false;
|
|
|
|
for(var n = 0; n < options.length; n++) {
|
|
|
|
if(input == options[n]) {
|
|
|
|
allow = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return allow;
|
|
|
|
},
|
|
|
|
onDropdownOpen: function($dropdown) {
|
|
|
|
$dropdown.closest('li, .InputfieldImageEdit').css('z-index', 100);
|
|
|
|
},
|
|
|
|
onDropdownClose: function($dropdown) {
|
|
|
|
$dropdown.closest('li, .InputfieldImageEdit').css('z-index', 'auto');
|
|
|
|
},
|
|
|
|
render: {
|
|
|
|
item: function(item, escape) {
|
|
|
|
return '<div>' + escape(item.value) + '</div>';
|
|
|
|
},
|
|
|
|
option: function(item, escape) {
|
|
|
|
return '<div>' + escape(item.value) + '</div>';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* MAIN
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
initSortable($(".InputfieldFileList"));
|
|
|
|
initTags($(".InputfieldFileHasTags"));
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Progressive enchanchment for browsers that support html5 File API
|
|
|
|
*
|
|
|
|
* #PageIDIndictator.length indicates PageEdit, which we're limiting AjaxUpload to since only ProcessPageEdit has the ajax handler
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
var allowAjax = false;
|
|
|
|
if (window.File && window.FileList && window.FileReader
|
|
|
|
&& ($("#PageIDIndicator").length > 0 || $('.InputfieldAllowAjaxUpload').length > 0)) {
|
|
|
|
InitHTML5('');
|
|
|
|
allowAjax = true;
|
|
|
|
} else {
|
|
|
|
InitOldSchool();
|
|
|
|
}
|
|
|
|
|
|
|
|
var minContainerWidth = 767; // ...or when the container width is this or smaller
|
|
|
|
var resizeActive = false;
|
|
|
|
|
|
|
|
var windowResize = function() {
|
|
|
|
if(!allowAjax) return;
|
|
|
|
$(".AjaxUploadDropHere").each(function() {
|
|
|
|
var $t = $(this);
|
|
|
|
if($t.parent().width() <= minContainerWidth) {
|
|
|
|
$t.hide();
|
|
|
|
} else {
|
|
|
|
$t.show();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
resizeActive = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(allowAjax) {
|
2024-04-04 14:37:20 +02:00
|
|
|
$(window).on('resize', function() {
|
2022-03-08 15:55:41 +01:00
|
|
|
if(resizeActive) return;
|
|
|
|
resizeActive = true;
|
|
|
|
setTimeout(windowResize, 1000);
|
2024-04-04 14:37:20 +02:00
|
|
|
}).trigger('resize');
|
2022-03-08 15:55:41 +01:00
|
|
|
$(document).on('AjaxUploadDone', '.InputfieldFileHasTags', function(event) {
|
|
|
|
initTags($(this));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
//$(document).on('reloaded', '.InputfieldFileMultiple, .InputfieldFileSingle', function(event) {
|
|
|
|
$(document).on('reloaded', '.InputfieldHasFileList', function(event) {
|
|
|
|
initSortable($(this).find(".InputfieldFileList"));
|
|
|
|
InitHTML5($(this));
|
|
|
|
initTags($(this));
|
|
|
|
if(allowAjax) windowResize();
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|