From f1873d04106e83342ae14f023f5b386309cbe9f7 Mon Sep 17 00:00:00 2001 From: Bartek Fabiszewski Date: Wed, 25 Dec 2019 23:45:14 +0100 Subject: [PATCH] Add dialog class --- js/src/dialog.js | 86 ++++++++++++++++++++++++++++++ js/test/dialog.test.js | 116 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 js/src/dialog.js create mode 100644 js/test/dialog.test.js diff --git a/js/src/dialog.js b/js/src/dialog.js new file mode 100644 index 0000000..d8334cb --- /dev/null +++ b/js/src/dialog.js @@ -0,0 +1,86 @@ +/* + * μlogger + * + * Copyright(C) 2019 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +import { lang as $ } from './initializer.js'; + +export default class uDialog { + + /** + * Builds modal dialog + * @param {(string|Node|NodeList|Array.)} content + */ + constructor(content) { + const dialog = document.createElement('div'); + dialog.setAttribute('id', 'modal'); + const dialogHeader = document.createElement('div'); + dialogHeader.setAttribute('id', 'modal-header'); + const buttonClose = document.createElement('button'); + buttonClose.setAttribute('id', 'modal-close'); + buttonClose.setAttribute('type', 'button'); + buttonClose.setAttribute('class', 'button-reject'); + buttonClose.setAttribute('data-bind', 'onCancel'); + const img = document.createElement('img'); + img.setAttribute('src', 'images/close.svg'); + img.setAttribute('alt', $._('close')); + buttonClose.append(img); + dialogHeader.append(buttonClose); + dialog.append(dialogHeader); + const dialogBody = document.createElement('div'); + dialogBody.setAttribute('id', 'modal-body'); + if (typeof content === 'string') { + dialogBody.innerHTML = content; + } else if (content instanceof NodeList || content instanceof Array) { + for (const node of content) { + dialogBody.append(node); + } + } else { + dialogBody.append(content); + } + dialog.append(dialogBody); + this.element = dialog; + this.visible = false; + } + + /** + * Show modal dialog + */ + show() { + if (!this.visible) { + document.body.append(this.element); + this.visible = true; + } + } + + /** + * Remove modal dialog + */ + destroy() { + document.body.removeChild(this.element); + this.visible = false + } + + /** + * Show confirmation dialog and return user decision + * @param {string} message + * @return {boolean} True if confirmed, false otherwise + */ + static isConfirmed(message) { + return confirm(message); + } +} diff --git a/js/test/dialog.test.js b/js/test/dialog.test.js new file mode 100644 index 0000000..a0741b7 --- /dev/null +++ b/js/test/dialog.test.js @@ -0,0 +1,116 @@ +/* + * μlogger + * + * Copyright(C) 2019 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +import { config, lang } from '../src/initializer.js'; +import uDialog from '../src/dialog.js'; +import uObserve from '../src/observe.js'; + +describe('Dialog tests', () => { + + let content; + let dialog; + + beforeEach(() => { + config.reinitialize(); + lang.init(config); + spyOn(lang, '_').and.returnValue('{placeholder}'); + content = 'Test content'; + dialog = new uDialog(content); + }); + + afterEach(() => { + document.body.innerHTML = ''; + uObserve.unobserveAll(lang); + }); + + it('should create dialog with string content', () => { + // when + const body = dialog.element.querySelector('#modal-body'); + // then + expect(body.innerHTML).toBe(content); + expect(dialog.visible).toBe(false); + }); + + it('should create dialog with node content', () => { + // given + content = document.createElement('div'); + dialog = new uDialog(content); + // when + const body = dialog.element.querySelector('#modal-body'); + // then + expect(body.firstChild).toBe(content); + }); + + it('should create dialog with node array content', () => { + // given + content = [ + document.createElement('div'), + document.createElement('div') + ]; + dialog = new uDialog(content); + // when + const body = dialog.element.querySelector('#modal-body'); + // then + expect(body.children[0]).toBe(content[0]); + expect(body.children[1]).toBe(content[1]); + }); + + it('should create dialog with node list content', () => { + // given + const div1 = document.createElement('div'); + const div2 = document.createElement('div'); + const el = document.createElement('div'); + el.append(div1, div2); + content = el.childNodes; + dialog = new uDialog(content); + // when + const body = dialog.element.querySelector('#modal-body'); + // then + expect(body.childNodes).toEqual(content); + }); + + it('should show dialog', () => { + // when + dialog.show(); + // then + expect(document.querySelector('#modal')).toBe(dialog.element); + expect(dialog.visible).toBe(true); + }); + + it('should destroy dialog', () => { + // given + dialog.show(); + // when + dialog.destroy(); + // then + expect(document.querySelector('#modal')).toBe(null); + expect(dialog.visible).toBe(false); + }); + + it('should show confirm dialog', () => { + // given + const message = 'confirm message'; + spyOn(window, 'confirm'); + // when + uDialog.isConfirmed(message); + // then + expect(window.confirm).toHaveBeenCalledWith(message); + }); + +});