145 lines
5.3 KiB
JavaScript
145 lines
5.3 KiB
JavaScript
|
import $ from 'jquery';
|
||
|
import { config, uri_params } from 'grav-config';
|
||
|
import request from '../../utils/request';
|
||
|
|
||
|
// const insertTextAt = (string, index, text) => [string.slice(0, index), text, string.slice(index)].join('');
|
||
|
|
||
|
export default class FilePickerField {
|
||
|
|
||
|
constructor(options) {
|
||
|
this.items = $();
|
||
|
this.options = Object.assign({}, this.defaults, options);
|
||
|
|
||
|
$('[data-grav-filepicker]').each((index, element) => this.addItem(element));
|
||
|
$('body').on('mutation._grav', this._onAddedNodes.bind(this));
|
||
|
}
|
||
|
|
||
|
_onAddedNodes(event, target/* , record, instance */) {
|
||
|
let fields = $(target).find('[data-grav-filepicker]');
|
||
|
if (!fields.length) { return; }
|
||
|
|
||
|
fields.each((index, field) => {
|
||
|
field = $(field);
|
||
|
if (!~this.items.index(field)) {
|
||
|
this.addItem(field);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
addItem(element) {
|
||
|
element = $(element);
|
||
|
this.items = this.items.add(element);
|
||
|
|
||
|
let tag = element.prop('tagName').toLowerCase();
|
||
|
let isInput = tag === 'input' || tag === 'select';
|
||
|
|
||
|
let field = (isInput ? element : element.find('input, select'));
|
||
|
|
||
|
let folder = '';
|
||
|
let thumbs = {};
|
||
|
|
||
|
let onDemand = field.closest('[data-ondemand]').length > 0;
|
||
|
|
||
|
if (!field.length || field.get(0).selectize) { return; }
|
||
|
|
||
|
let getData = function getData(field, callback, mode = 'all') {
|
||
|
let url = config.current_url + `.json/task${config.param_sep}getFilesInFolder`;
|
||
|
let parent = field.closest('[data-grav-filepicker]');
|
||
|
let name = parent.data('name');
|
||
|
let value = parent.data('value');
|
||
|
let params = JSON.stringify(uri_params || '{}');
|
||
|
|
||
|
request(url, {
|
||
|
method: 'post',
|
||
|
body: { name, params }
|
||
|
}, (response) => {
|
||
|
if (typeof response.files === 'undefined') {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
let data = [];
|
||
|
thumbs = response.thumbs || {};
|
||
|
|
||
|
for (let i = 0; i < response.files.length; i++) {
|
||
|
if (mode === 'selected' && response.files[i] !== value) { continue; }
|
||
|
data.push({ 'name': response.files[i], 'status': 'available', thumb: thumbs[response.files[i]] || '' });
|
||
|
}
|
||
|
|
||
|
for (let i = 0; i < response.pending.length; i++) {
|
||
|
if (mode === 'selected' && response.pending[i] !== value) { continue; }
|
||
|
data.push({ 'name': response.pending[i], 'status': 'pending', thumb: thumbs[response.pending[i]] || '' });
|
||
|
}
|
||
|
|
||
|
folder = response.folder;
|
||
|
callback(data, value);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
let imagesPreview = field.closest('[data-preview-images]').length > 0;
|
||
|
let selectedIsRendered = false;
|
||
|
|
||
|
let renderOption = function renderOption(item, escape) {
|
||
|
let image = '';
|
||
|
if (imagesPreview && folder && (!item.status || item.status === 'available') && item.name.match(/\.(jpg|jpeg|png|gif)$/i)) {
|
||
|
// const fallback2x = insertTextAt(`${config.base_url_relative}/../${folder}/${item.name}`, -4, '@2x');
|
||
|
// const fallback3x = insertTextAt(`${config.base_url_relative}/../${folder}/${item.name}`, -4, '@3x');
|
||
|
const source = thumbs[item.name] || `${config.base_url_relative}/../${folder}/${item.name}`;
|
||
|
|
||
|
// onerror="if(this.src==='${fallback2x}'){this.src='${fallback3x}';}else{this.src='${fallback2x}'}"
|
||
|
image = `<img class="filepicker-field-image" src="${source}" />`;
|
||
|
}
|
||
|
|
||
|
return `<div>
|
||
|
<span class="title">
|
||
|
${image} <span class="name filepicker-field-name">${escape(item.name)}</span>
|
||
|
</span>
|
||
|
</div>`;
|
||
|
};
|
||
|
|
||
|
field.selectize({
|
||
|
plugins: ['required-fix'],
|
||
|
valueField: 'name',
|
||
|
labelField: 'name',
|
||
|
searchField: 'name',
|
||
|
optgroups: [
|
||
|
{$order: 1, value: 'pending', label: 'Pending'},
|
||
|
{$order: 2, value: 'available', label: 'Available'}
|
||
|
],
|
||
|
optgroupField: 'status',
|
||
|
// lockOptgroupOrder: true,
|
||
|
create: false,
|
||
|
preload: false, // 'focus',
|
||
|
render: {
|
||
|
option: function(item, escape) {
|
||
|
return renderOption(item, escape);
|
||
|
},
|
||
|
|
||
|
item: function(item, escape) {
|
||
|
return renderOption(item, escape);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
onInitialize: function() {
|
||
|
if (!onDemand) {
|
||
|
this.load((callback) => getData(field, (data) => callback(data), 'selected'));
|
||
|
}
|
||
|
},
|
||
|
|
||
|
onLoad: function(/* data */) {
|
||
|
if (!selectedIsRendered) {
|
||
|
let name = this.getValue();
|
||
|
this.updateOption(name, { name });
|
||
|
|
||
|
selectedIsRendered = true;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
onFocus: function() {
|
||
|
this.load((callback) => getData(field, (data) => callback(data)));
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export let Instance = new FilePickerField();
|