Skip to content

Commit

Permalink
Merge pull request jdorn#702 from JElchison/dev-table-copy-button
Browse files Browse the repository at this point in the history
Add copy button to arrays in table format
  • Loading branch information
schmunk42 authored Apr 17, 2020
2 parents c3cb832 + c36e348 commit ffdb663
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 82 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Fix of #701 - editors/number.js and editors/integer.js don't change values when validation is failed
- Fix of #716 - add ignore for allOf to fall in line with existing ignores of anyOf/oneOf for additionalProperties validation
- Fix of #714 - Checkboxes inside object tables duplicate labels from heading
- Added copy button to arrays in table format

### 2.0.0-dev
- Fix of #643 - Allow use of themes not compiled directly into the build
Expand Down
4 changes: 4 additions & 0 deletions src/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ languages.en = {
*/
button_delete_row_title_short: 'Delete',
/**
* Title on Copy Row buttons, short version (no parameter with the object title)
*/
button_copy_row_title_short: 'Copy',
/**
* Title on Collapse buttons
*/
button_collapse: 'Collapse',
Expand Down
157 changes: 92 additions & 65 deletions src/editors/table.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,31 +207,49 @@ export class TableEditor extends ArrayEditor {
refreshRowButtons () {
/* If we currently have minItems items in the array */
const minItems = this.schema.minItems && this.schema.minItems >= this.rows.length
/* If we currently have maxItems items in the array */
const maxItems = this.schema.maxItems && this.schema.maxItems <= this.rows.length

let needRowButtons = false
this.rows.forEach((editor, i) => {
/* Hide the move down button for the last row */
if (editor.movedown_button) {
if (i === this.rows.length - 1) {
editor.movedown_button.style.display = 'none'
if (editor.delete_button) {
/* Hide the delete button if we have minItems items */
if (minItems) {
editor.delete_button.style.display = 'none'
} else {
needRowButtons = true
editor.movedown_button.style.display = ''
editor.delete_button.style.display = ''
}
}

/* Hide the delete button if we have minItems items */
if (editor.delete_button) {
if (minItems) {
editor.delete_button.style.display = 'none'
if (editor.copy_button) {
/* Hide the copy button if we have maxItems items */
if (maxItems) {
editor.copy_button.style.display = 'none'
} else {
needRowButtons = true
editor.delete_button.style.display = ''
editor.copy_button.style.display = ''
}
}

if (editor.moveup_button) {
needRowButtons = true
/* Hide the moveup button for the first row */
if (i === 0) {
editor.moveup_button.style.display = 'none'
} else {
needRowButtons = true
editor.moveup_button.style.display = ''
}
}

if (editor.movedown_button) {
/* Hide the movedown button for the last row */
if (i === this.rows.length - 1) {
editor.movedown_button.style.display = 'none'
} else {
needRowButtons = true
editor.movedown_button.style.display = ''
}
}
})

Expand All @@ -249,49 +267,38 @@ export class TableEditor extends ArrayEditor {
this.controls_header_cell.style.display = 'none'
}

let controlsNeeded = false

if (!this.value.length) {
this.delete_last_row_button.style.display = 'none'
this.remove_all_rows_button.style.display = 'none'
this.table.style.display = 'none'
} else if (this.value.length === 1) {
this.table.style.display = ''
this.remove_all_rows_button.style.display = 'none'

/* If there are minItems items in the array, or configured to hide the delete_last_row button, hide the delete button beneath the rows */
if (minItems || this.hide_delete_last_row_buttons) {
this.delete_last_row_button.style.display = 'none'
} else {
this.delete_last_row_button.style.display = ''
controlsNeeded = true
}
} else {
this.table.style.display = ''

if (minItems || this.hide_delete_last_row_buttons) {
this.delete_last_row_button.style.display = 'none'
} else {
this.delete_last_row_button.style.display = ''
controlsNeeded = true
}

if (minItems || this.hide_delete_all_rows_buttons) {
this.remove_all_rows_button.style.display = 'none'
} else {
this.remove_all_rows_button.style.display = ''
controlsNeeded = true
}
}

/* If there are maxItems in the array, hide the add button beneath the rows */
if ((this.schema.maxItems && this.schema.maxItems <= this.rows.length) || this.hide_add_button) {
let controlsNeeded = false

/* If there are maxItems items in the array, or configured to hide the add_row_button button, hide the button beneath the rows */
if (maxItems || this.hide_add_button) {
this.add_row_button.style.display = 'none'
} else {
this.add_row_button.style.display = ''
controlsNeeded = true
}

/* If there are minItems items in the array, or configured to hide the delete_last_row button, hide the button beneath the rows */
if (!this.value.length || minItems || this.hide_delete_last_row_buttons) {
this.delete_last_row_button.style.display = 'none'
} else {
this.delete_last_row_button.style.display = ''
controlsNeeded = true
}

/* If there are minItems items in the array, or configured to hide the remove_all_rows_button button, hide the button beneath the rows */
if (this.value.length <= 1 || minItems || this.hide_delete_all_rows_buttons) {
this.remove_all_rows_button.style.display = 'none'
} else {
this.remove_all_rows_button.style.display = ''
controlsNeeded = true
}

if (!controlsNeeded) {
this.controls.style.display = 'none'
} else {
Expand All @@ -316,7 +323,7 @@ export class TableEditor extends ArrayEditor {

const controlsHolder = this.rows[i].table_controls

/* Buttons to delete row, move row up, and move row down */
/* Buttons to delete row, copy row, move row up, and move row down */
if (!this.hide_delete_buttons) {
this.rows[i].delete_button = this.getButton('', 'delete', this.translate('button_delete_row_title_short'))
this.rows[i].delete_button.classList.add('delete', 'json-editor-btntype-delete')
Expand All @@ -329,33 +336,54 @@ export class TableEditor extends ArrayEditor {
return false
}

const i = e.currentTarget.getAttribute('data-i') * 1
const newval = this.getValue().filter((row, j) => j !== i) /* If this is the one we're deleting */
this.setValue(newval)
const j = e.currentTarget.getAttribute('data-i') * 1
const value = this.getValue()

value.splice(j, 1)

this.setValue(value)
this.onChange(true)
this.jsoneditor.trigger('deleteRow', this.rows[i])
this.jsoneditor.trigger('deleteRow', this.rows[j])
})
controlsHolder.appendChild(this.rows[i].delete_button)
}

if (i && !this.hide_move_buttons) {
if (this.show_copy_button) {
this.rows[i].copy_button = this.getButton('', 'copy', this.translate('button_copy_row_title_short'))
this.rows[i].copy_button.classList.add('copy', 'json-editor-btntype-copy')
this.rows[i].copy_button.setAttribute('data-i', i)
this.rows[i].copy_button.addEventListener('click', e => {
e.preventDefault()
e.stopPropagation()

const j = e.currentTarget.getAttribute('data-i') * 1
const value = this.getValue()

value.splice(j + 1, 0, value[j])

this.setValue(value)
this.onChange(true)
this.jsoneditor.trigger('copyRow', this.rows[j + 1])
})
controlsHolder.appendChild(this.rows[i].copy_button)
}

if (!this.hide_move_buttons) {
this.rows[i].moveup_button = this.getButton('', 'moveup', this.translate('button_move_up_title'))
this.rows[i].moveup_button.classList.add('moveup', 'json-editor-btntype-move')
this.rows[i].moveup_button.setAttribute('data-i', i)
this.rows[i].moveup_button.addEventListener('click', e => {
e.preventDefault()
e.stopPropagation()
const i = e.currentTarget.getAttribute('data-i') * 1

if (i <= 0) return
const rows = this.getValue()
const tmp = rows[i - 1]
rows[i - 1] = rows[i]
rows[i] = tmp
const j = e.currentTarget.getAttribute('data-i') * 1
const value = this.getValue()

this.setValue(rows)
value.splice(j - 1, 0, value.splice(j, 1)[0])

this.setValue(value)
this.onChange(true)
this.jsoneditor.trigger('moveRow', this.rows[i - 1])
this.jsoneditor.trigger('moveRow', this.rows[j - 1])
})
controlsHolder.appendChild(this.rows[i].moveup_button)
}
Expand All @@ -367,16 +395,15 @@ export class TableEditor extends ArrayEditor {
this.rows[i].movedown_button.addEventListener('click', e => {
e.preventDefault()
e.stopPropagation()
const i = e.currentTarget.getAttribute('data-i') * 1
const rows = this.getValue()
if (i >= rows.length - 1) return
const tmp = rows[i + 1]
rows[i + 1] = rows[i]
rows[i] = tmp

this.setValue(rows)

const j = e.currentTarget.getAttribute('data-i') * 1
const value = this.getValue()

value.splice(j + 1, 0, value.splice(j, 1)[0])

this.setValue(value)
this.onChange(true)
this.jsoneditor.trigger('moveRow', this.rows[i + 1])
this.jsoneditor.trigger('moveRow', this.rows[j + 1])
})
controlsHolder.appendChild(this.rows[i].movedown_button)
}
Expand Down
25 changes: 18 additions & 7 deletions tests/codeceptjs/editors/array_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,44 @@ Scenario('should trigger array (table) editing triggers', async (I) => {
I.amOnPage('table-move-events.html');
I.seeElement('[data-schemapath="root.0"]');
I.seeElement('[data-schemapath="root.1"]');
I.seeElement('[data-schemapath="root.2"]');
I.seeElement('[data-schemapath="root.3"]');
I.seeElement('[data-schemapath="root.4"]');
I.click('.get-value');
value = await I.grabValueFrom('.debug');
assert.equal(value, '["A","B"]');
assert.equal(value, '["A","B","C","D","E"]');

I.amAcceptingPopups();
I.click('.json-editor-btn-moveup');
I.click('//button[contains(@class, "json-editor-btn-moveup") and @data-i="1"]');
I.seeInPopup('moveRow');
I.acceptPopup();
I.click('.get-value');
value = await I.grabValueFrom('.debug');
assert.equal(value, '["B","A"]');
assert.equal(value, '["B","A","C","D","E"]');

I.amAcceptingPopups();
I.click('.json-editor-btn-movedown');
I.click('//button[contains(@class, "json-editor-btn-movedown") and @data-i="1"]');
I.seeInPopup('moveRow');
I.acceptPopup();
I.click('.get-value');
value = await I.grabValueFrom('.debug');
assert.equal(value, '["A","B"]');
assert.equal(value, '["B","C","A","D","E"]');

I.amAcceptingPopups();
I.click('//button[contains(@class, "json-editor-btn-copy") and @data-i="2"]');
I.seeInPopup('copyRow');
I.acceptPopup();
I.click('.get-value');
value = await I.grabValueFrom('.debug');
assert.equal(value, '["B","C","A","A","D","E"]');

I.amAcceptingPopups();
I.click('.json-editor-btntype-add');
I.seeInPopup('addRow');
I.acceptPopup();
I.click('.get-value');
value = await I.grabValueFrom('.debug');
assert.equal(value, '["A","B",""]');
assert.equal(value, '["B","C","A","A","D","E",""]');

// This test will fail when using Puppeteer due to the way Puppeteer handles popups.
// Puppeteer apparently only sees the text in the last popup, so it doesn't see the
Expand All @@ -54,7 +65,7 @@ Scenario('should trigger array (table) editing triggers', async (I) => {
I.acceptPopup();
I.click('.get-value');
value = await I.grabValueFrom('.debug');
assert.equal(value, '["A","B"]');
assert.equal(value, '["B","C","A","A","D","E"]');

// This test will fail when using Puppeteer due to the way Puppeteer handles popups.
I.amAcceptingPopups();
Expand Down
25 changes: 15 additions & 10 deletions tests/pages/table-move-events.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,32 @@
}
};
var editor = new JSONEditor(container, {
schema: schema
schema: schema,
enable_array_copy: true
});
document.querySelector('.get-value').addEventListener('click', function () {
debug.value = JSON.stringify(editor.getValue());
});
editor.setValue(["A","B"]);
editor.setValue(["A","B","C","D","E"]);
editor.on('copyRow', function () {
alert('copyRow');
console.log('copyRow');
});
editor.on('moveRow', function () {
alert('moveRow')
console.log('moveRow')
alert('moveRow');
console.log('moveRow');
});
editor.on('addRow', function () {
alert('addRow')
console.log('addRow')
alert('addRow');
console.log('addRow');
});
editor.on('deleteRow', function () {
alert('deleteRow')
console.log('deleteRow')
alert('deleteRow');
console.log('deleteRow');
});
editor.on('deleteAllRows', function () {
alert('deleteAllRows')
console.log('deleteAllRows')
alert('deleteAllRows');
console.log('deleteAllRows');
});
</script>

Expand Down

0 comments on commit ffdb663

Please sign in to comment.