|
| 1 | +import Setting from './array.js'; |
| 2 | + |
| 3 | +export default class MapList extends Setting { |
| 4 | + constructor(name = 'map') { |
| 5 | + super(name); |
| 6 | + } |
| 7 | + |
| 8 | + default() { |
| 9 | + return new Map(); |
| 10 | + } |
| 11 | + |
| 12 | + element(val = new Map(), update, { container }) { |
| 13 | + const data = [...val.entries()]; |
| 14 | + function invalid(text) { |
| 15 | + return data.some(([value]) => value === text); |
| 16 | + } |
| 17 | + function add(value) { |
| 18 | + function save(remove) { |
| 19 | + if (remove) data.splice(data.indexOf(value), 1); |
| 20 | + update(data.filter(([key]) => key)); |
| 21 | + } |
| 22 | + container.append(createItem({ value, save, invalid })); |
| 23 | + } |
| 24 | + data.forEach(add); |
| 25 | + return $('<button class="btn btn-success glyphicon glyphicon-plus">').on('click', () => { |
| 26 | + const item = ['', '']; |
| 27 | + data.push(item); |
| 28 | + add(item); |
| 29 | + }); |
| 30 | + } |
| 31 | + |
| 32 | + encode(value = []) { |
| 33 | + if (value instanceof Map) { |
| 34 | + return super.encode([...value.entries()]); |
| 35 | + } |
| 36 | + return super.encode(value); |
| 37 | + } |
| 38 | + |
| 39 | + styles() { |
| 40 | + return [ |
| 41 | + '{ border-top: 1px solid white; border-bottom: 1px solid white; padding: 5px 0; }', |
| 42 | + 'label { align-self: flex-end; }', |
| 43 | + '.btn { padding: 3px 6px; }', |
| 44 | + '.item { display: inline-flex; flex-wrap: wrap; align-items: center; padding-top: 5px; }', |
| 45 | + '.item > input { margin: 0 5px; }', |
| 46 | + '.error input:first-child { border-color: red; }', |
| 47 | + '.warning { display: none; color: red; flex-basis: 100%; user-select: none; }', |
| 48 | + '.error .warning { display: block; }', |
| 49 | + ]; |
| 50 | + } |
| 51 | + |
| 52 | + value(value) { |
| 53 | + return new Map(super.value(value)); |
| 54 | + } |
| 55 | +} |
| 56 | + |
| 57 | +function createItem({ |
| 58 | + value = ['key', 'value'], |
| 59 | + save, |
| 60 | + invalid, |
| 61 | +}) { |
| 62 | + const left = $('<input type="text">').val(value[0]).on('blur', () => { |
| 63 | + const newVal = left.val(); |
| 64 | + const isInvalid = newVal !== value[0] && invalid(newVal); |
| 65 | + left.parent().toggleClass('error', isInvalid); |
| 66 | + if (isInvalid || newVal === value[0]) return; |
| 67 | + value[0] = newVal; |
| 68 | + save(); |
| 69 | + }); |
| 70 | + const right = $('<input type="text">').val(value[1]).on('blur', () => { |
| 71 | + const newVal = right.val(); |
| 72 | + if (newVal === value[1]) return; |
| 73 | + value[1] = newVal; |
| 74 | + save(); |
| 75 | + }); |
| 76 | + const button = $('<button class="btn btn-danger glyphicon glyphicon-trash">').on('click', () => { |
| 77 | + save(true); |
| 78 | + button.parent().remove(); |
| 79 | + }); |
| 80 | + const warning = $('<div class="warning clickable">') |
| 81 | + .text('Duplicate value, not updated! Click here to reset.') |
| 82 | + .on('click', () => left.val(value[0]) |
| 83 | + .parent().removeClass('error')); |
| 84 | + return $('<div class="item">').append(left, ' : ', right, button, warning); |
| 85 | +} |
0 commit comments