import $ from 'jquery'; import Sortable from 'sortablejs'; let body = $('body'); class Template { constructor(container) { this.container = $(container); if (this.getName() === undefined) { this.container = this.container.closest('[data-grav-array-name]'); } } getName() { return this.container.data('grav-array-name') || ''; } getKeyPlaceholder() { return this.container.data('grav-array-keyname') || 'Key'; } getValuePlaceholder() { return this.container.data('grav-array-valuename') || 'Value'; } isValueOnly() { return this.container.find('[data-grav-array-mode="value_only"]:first').length || false; } isTextArea() { return this.container.data('grav-array-textarea') || false; } shouldBeDisabled() { // check for toggleables, if field is toggleable and it's not enabled, render disabled let toggle = this.container.closest('.form-field').find('[data-grav-field="toggleable"] input[type="checkbox"]'); return toggle.length && toggle.is(':not(:checked)'); } getNewRow() { let tpl = '';const value = this.isTextArea() ? `` : ``; if (this.isValueOnly()) { tpl += `
${value} `; } else { tpl += `
${value} `; } tpl += `
`; return tpl; } } export default class ArrayField { constructor() { body.on('input', '[data-grav-array-type="key"], [data-grav-array-type="value"]', (event) => this.actionInput(event)); body.on('click touch', '[data-grav-array-action]:not([data-grav-array-action="sort"])', (event) => this.actionEvent(event)); this.arrays = $(); $('[data-grav-field="array"]').each((index, list) => this.addArray(list)); $('body').on('mutation._grav', this._onAddedNodes.bind(this)); } addArray(list) { list = $(list); list.find('[data-grav-array-type="container"]').each((index, container) => { container = $(container); if (container.data('array-sort') || container[0].hasAttribute('data-array-nosort')) { return; } container.data('array-sort', new Sortable(container.get(0), { handle: '.fa-bars', animation: 150, onUpdate: () => { const item = container.find('[data-grav-array-type="row"]:first'); this._setTemplate(item); const template = item.data('array-template'); this.refreshNames(template); } })); }); } actionInput(event) { let element = $(event.target); let type = element.data('grav-array-type'); this._setTemplate(element); let template = element.data('array-template'); let keyElement = type === 'key' ? element : element.siblings('[data-grav-array-type="key"]:first'); let valueElement = type === 'value' ? element : element.siblings('[data-grav-array-type="value"]:first'); let escaped_name = !template.isValueOnly() ? keyElement.val() : this.getIndexFor(element); escaped_name = escaped_name.toString().replace(/\[/g, '%5B').replace(/]/g, '%5D'); let name = `${template.getName()}[${escaped_name}]`; if (!template.isValueOnly() && (!keyElement.val() && !valueElement.val())) { valueElement.attr('name', ''); } else { // valueElement.attr('name', !valueElement.val() ? template.getName() : name); valueElement.attr('name', name); } this.refreshNames(template); } actionEvent(event) { event && event.preventDefault(); let element = $(event.target); let action = element.data('grav-array-action'); let container = element.parents('[data-grav-array-type="container"]'); this._setTemplate(element); this[`${action}Action`](element); let siblings = container.find('> div'); container[siblings.length > 1 ? 'removeClass' : 'addClass']('one-child'); } addAction(element) { let template = element.data('array-template'); let row = element.closest('[data-grav-array-type="row"]'); row.after(template.getNewRow()); } remAction(element) { let template = element.data('array-template'); let row = element.closest('[data-grav-array-type="row"]'); let isLast = !row.siblings().length; if (isLast) { let newRow = $(template.getNewRow()); row.after(newRow); newRow.find('[data-grav-array-type="value"]:last').attr('name', template.getName()); } row.remove(); this.refreshNames(template); } refreshNames(template) { if (!template.isValueOnly()) { return; } let row = template.container.find('> div > [data-grav-array-type="row"]'); let inputs = row.find('[name]:not([name=""])'); inputs.each((index, input) => { input = $(input); const preserved_name = input.closest('[data-grav-array-name]'); const name = `${preserved_name.attr('data-grav-array-name')}[${index}]`; input.attr('name', name); }); if (!inputs.length) { row.find('[data-grav-array-type="value"]').attr('name', template.getName()); } } getIndexFor(element) { let template = element.data('array-template'); let row = element.closest('[data-grav-array-type="row"]'); return template.container.find(`${template.isValueOnly() ? '> div ' : ''} > [data-grav-array-type="row"]`).index(row); } _setTemplate(element) { if (!element.data('array-template')) { element.data('array-template', new Template(element.closest('[data-grav-array-name]'))); } } _onAddedNodes(event, target/* , record, instance */) { let arrays = $(target).find('[data-grav-field="array"]'); if (!arrays.length) { return; } arrays.each((index, list) => { list = $(list); if (!~this.arrays.index(list)) { this.addArray(list); } }); } } export let Instance = new ArrayField();