class SelectorBase { find(selector, parent) { const p = parent || document return parent.querySelector(selector) } findAll(selector, parent, callback) { const p = parent || document, result = parent.querySelectorAll(selector) result.forEach((e, i) => { callback(e, i) }) return result; } set(obj) { obj = obj || {}; const element = document.createElement(obj.tagName || 'div') if (obj.type) element.type = obj.type if (obj.className) element.className = obj.className if (obj.innerHTML) element.innerHTML = obj.innerHTML if (obj.name) element.name = obj.name if (obj.events) { Object.keys(obj.events).forEach(event => { element.addEventListener(event, e => { obj.events[event](element) }) }) } if (obj.attributes) { Object.keys(obj.attributes).forEach(attr => { element.setAttribute(attr, obj.attributes[attr]) }) } if (obj.parent) obj.parent.appendChild(element) return element } toggleClass(e, classFrom, classTo) { e.classList.remove(classFrom) e.classList.add(classTo) } } class InnerTableItems extends SelectorBase { updateUrl constructor() { super(); this.setDefault() } setChangeToSelect(e) { this.typeValueSelectorChange(e, e.name.replace('user_interface_type', 'select_data')) } setChangeDataType(e) { console.log(e.value) } setUpdateUrl(url) { this.updateUrl = url; } setDefault() { this.findAll('.type-value-selector', document, e => { e.addEventListener('change', () => { this.typeValueSelectorChange(e, e.name.replace('user_interface_type', 'select_data')) }) }) this.findAll('.inner-td-table .add-row', document, e => { e.addEventListener('click', () => { this.addNewRow(e) }) }) this.findAll('.inner-td-table .remove', document, e => { e.addEventListener('click', () => { this.deleteRow(e) }) }) this.findAll('.inner-td-table .add-bg, .inner-td-table .add-en', document, e => { e.addEventListener('keydown', () => { this.addNewRow(e) }) }) this.findAll('.inner-td-table .update-bg, .inner-td-table .update-en', document, e => { e.addEventListener('keydown', () => { this.updateRow(e) }) e.addEventListener('blur', () => { this.updateRow(e) }) }) } addNewRow(e) { const erd = this.eventRetrieveData(e) if (erd) { const lg = !erd.inputEn ? 1 : null; const row = this.setRow(erd.tbody, erd.dataTable, 'update', lg) row.inputBg.value = erd.inputBg.value if (row.inputEn && erd.inputEn) { row.inputEn.value = erd.inputEn.value } if(erd.inputBg.value !== '') { if (erd.tbody.dataset.id !== 'undefined') { console.log(erd.tbody.dataset.id) if (this.updateUrl && erd.tbody.dataset.id) { erd.tr.classList.add('disabled') this.request({ url: this.updateUrl, data: { parent_id: erd.tbody.dataset.id, bg: erd.inputBg.value, en: erd.inputEn ? erd.inputEn.value : '', }, success: r => { if (r.id) { row.tr.setAttribute('data-option-id', r.id); erd.tbody.insertBefore(row.tr, erd.tr) erd.inputBg.value = '' if (erd.inputEn) erd.inputEn.value = '' erd.tr.classList.remove('disabled') erd.inputBg.focus() this.setData(erd.tbody, erd.hidden) flash.success('Опцията е добавена успешно') } else { flash.error('Опцията не беше добавена поради грешка в системата') } } }) } } else { erd.tbody.insertBefore(row.tr, erd.tr) erd.inputBg.value = '' if (erd.inputEn) erd.inputEn.value = '' erd.tr.classList.remove('disabled') erd.inputBg.focus() this.setData(erd.tbody, erd.hidden) } } else { errorElement(erd.inputBg, 'Стойността не може да бъде празна') } } } updateRow(e) { const erd = this.eventRetrieveData(e) if (erd) { if(erd.tr && erd.tr.dataset.optionId) { erd.tr.classList.add('disabled'); this.request({ url: this.updateUrl, data: { id: erd.tr.dataset.optionId, bg: erd.inputBg.value, en: erd.inputEn ? erd.inputEn.value : '', }, success: r => { if(r.id) { this.setData(erd.tbody, erd.hidden) flash.success('Опцията е актуализирана успешно') } else { flash.error('Опцията не беше актуализирана поради грешка в системата') } erd.tr.classList.remove('disabled'); } }) } } } deleteRow(e) { const erd = this.eventRetrieveData(e) if (erd) { erd.tr.classList.add('disabled'); if(erd.tr && erd.tr.dataset.optionId) { this.request({ url: this.updateUrl, data: { id: erd.tr.dataset.optionId, remove: 1 }, success: r => { if(r.success) { erd.tr.remove() this.setData(erd.tbody, erd.hidden) flash.success('Опцията е премахната успешно') } else { flash.error('Опцията не беше премахната поради грешка в системата') erd.tr.classList.remove('disabled') } } }) } } } setRow(tbody, dataTable, type, lg) { const trObj = {tagName: 'tr', attributes: {"data-table": dataTable}}; if (type === 'add') trObj.parent = tbody const tr = this.set(trObj), tdBg = this.set({tagName: 'td', parent: tr}), inputBg = this.set({ tagName: 'input', parent: tdBg, className: `${type}-bg`, events: { keydown: () => { if (type === 'add') this.addNewRow(inputBg) if (type === 'update') this.updateRow(inputBg) } } }), tdEn = this.set({tagName: 'td', parent: tr}), inputEn = this.set({ tagName: 'input', parent: tdEn, className: `${type}-en`, events: { keydown: () => { if (type === 'add') this.addNewRow(inputEn) if (type === 'update') this.updateRow(inputEn) } } }) if (lg === 1) tdEn.remove() const button = this.set({ tagName: 'td', className: type === 'add' ? 'add-row' : 'remove', parent: tr, innerHTML: ``, events: { click: () => { if (type === 'add') this.addNewRow(button) if (type === 'update') this.deleteRow(button) } } }) if (type === 'add') inputBg.focus() if (type === 'update') { tr.className = 'added-row' tr.setAttribute('data-table', dataTable) } return {tr, inputBg, inputEn}; } eventRetrieveData(e) { if (event.keyCode && event.keyCode !== 13) return var tr = ""; if (event.keyCode === 13) event.preventDefault() if (e.tagName === "INPUT") tr = e.parentNode.parentNode if (e.tagName === "TD") tr = e.parentNode const dataTable = tr.dataset.table, tbody = document.querySelector(`.inner-td-table[data-table="${dataTable}"] tbody`), hidden = document.querySelector(`input[name="${dataTable}"]`), button = this.find('.add-row', tr), inputBg = this.find('td:nth-child(1) input', tr), inputEn = this.find('td:nth-child(2) input', tr) return {dataTable, tr, inputBg, inputEn, tbody, hidden, button} } setData(tbody, hidden) { const data = [] this.findAll('.added-row', tbody, (e, i) => { e.setAttribute('data-index', i) const objectRow = {}; const bg = this.find('td:nth-child(1) input', e) const en = this.find('td:nth-child(2) input', e) if(e.dataset.optionId) objectRow['id'] = e.dataset.optionId if (bg) objectRow['bg'] = bg.value if (en) objectRow['en'] = en.value data.push(objectRow) }) hidden.value = JSON.stringify(data) return data } request(o) { console.log(o); const xhr = new XMLHttpRequest() xhr.responseType = 'json' xhr.onload = () => { if(o.success) { o.success(xhr.response) } } xhr.open('post', o.url) const fd = new FormData() if(o.data) { Object.keys(o.data).forEach(key => { fd.append(key, o.data[key]) }) } xhr.send(fd) } typeValueSelectorChange(elem, dataTable) { const existHidden = elem.parentNode.querySelector('input[type="hidden"]'), existTable = elem.parentNode.querySelector('table.inner-td-table') if(existHidden) existHidden.remove() if(existTable) existTable.remove() if (elem.value === 'list') { const hidden = this.set({tagName: 'input', type: 'hidden', name: dataTable}), table = this.set({ tagName: 'table', className: 'inner-td-table', innerHTML: ` стойност (bg)стойност (en) `, attributes: {"data-table": dataTable} }), tbody = this.set({tagName: 'tbody', parent: table, attributes: {"data-id": elem.dataset.id}}) this.setRow(tbody, dataTable, 'add') elem.parentNode.appendChild(hidden) elem.parentNode.appendChild(table) } else if (elem.value === 'list_simple') { const hidden = this.set({tagName: 'input', type: 'hidden', name: dataTable}), table = this.set({ tagName: 'table', className: 'inner-td-table', innerHTML: ` стойност `, attributes: {"data-table": dataTable} }), tbody = this.set({tagName: 'tbody', parent: table, attributes: {"data-id": elem.dataset.id}}) this.setRow(tbody, dataTable, 'add', 1) elem.parentNode.appendChild(hidden) elem.parentNode.appendChild(table) } else { const hidden = this.find('input[type="hidden"]', elem.parentNode), table = this.find('table.inner-td-table', elem.parentNode) if (hidden) hidden.remove() if (table) table.remove() } } }