UNPKG

silegismg-editor-articulacao

Version:
209 lines (178 loc) 5.58 kB
/* Copyright 2017 Assembleia Legislativa de Minas Gerais * * This file is part of Editor-Articulacao. * * Editor-Articulacao is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, version 3. * * Editor-Articulacao 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Editor-Articulacao. If not, see <http://www.gnu.org/licenses/>. */ import ArticulacaoChangeEvent from './eventos/ArticulacaoChangeEvent'; /** * Monitora alterações no editor de articulação e dispara o evento change. */ class ControleAlteracao { constructor(editorCtrl) { this._editorCtrl = editorCtrl; editorCtrl.registrarEventListener('focus', event => { this._comFoco = true; this.iniciar(event.target, editorCtrl); }, true); editorCtrl.registrarEventListener('blur', event => { this._comFoco = false; this.finalizar(event.target, editorCtrl); this.comprometer(); }, true); } get alterado() { throw 'Não implementado.'; } set alterado(valor) { throw 'Não implementado.'; } /** * Inicia a monitoração de alterações. * * @param {Element} elemento * @param {EditorArticulacaoController} editorCtrl Editor de articulação */ iniciar(elemento, editorCtrl) { throw 'Não implementado'; } /** * Finaliza a monitoração de alterações. * * @param {Element} elemento * @param {EditorArticulacaoController} editorCtrl Editor de articulação */ finalizar(elemento, editorCtrl) { throw 'Não implementado'; } comprometer() { if (this.alterado) { this.alterado = false; this._editorCtrl.dispatchEvent(new ArticulacaoChangeEvent(this._editorCtrl)); } } } /** * Monitora as alterações utilizando MutationObserver. */ class ControleAlteracaoMutationObserver extends ControleAlteracao { constructor(editorCtrl) { super(editorCtrl); this._observer = new MutationObserver(this._mutationCallback.bind(this)); this._iniciado = false; this._alterado = false; } get alterado() { return this._alterado; } set alterado(valor) { this._alterado = valor; if (!this._alterado && !this._conectado && this._comFoco) { this.iniciar(this._editorCtrl._elemento, this._editorCtrl); } if (this._alterado && !this._comFoco) { this.comprometer(); } if (this._alterado) { this.finalizar(); } } /** * Inicia a monitoração de alterações. * * @param {Element} elemento * @param {EditorArticulacaoController} editorCtrl Editor de articulação */ iniciar(elemento, editorCtrl) { if (!this._conectado) { this._observer.observe(elemento, { childList: true, attributes: true, characterData: true, subtree: true }); this._conectado = true; } this._iniciado = true; } /** * Finaliza a monitoração de alterações. * * @param {Element} elemento * @param {EditorArticulacaoController} editorCtrl Editor de articulação */ finalizar(elemento, editorCtrl) { if (this._conectado) { this._observer.disconnect(); this._conectado = false; } this._iniciado = false; } _mutationCallback() { try { this._conectado = false; this._observer.disconnect(); } finally { this.alterado = true; } } } /** * Monitora as alterações comparando o lexml no foco e no blur. */ class ControleAlteracaoComparativo extends ControleAlteracao { constructor(editorCtrl) { super(editorCtrl); this._alteradoCache = false; } get alterado() { if (this._alteradoCache) { return true; } else { this._alteradoCache = this._editorCtrl.lexmlString !== this._lexml; return this._alteradoCache; } } set alterado(valor) { this._lexml = valor ? '' : this._editorCtrl.lexmlString; this._alteradoCache = !!valor; if (valor && !this._comFoco) { this.comprometer(); } } /** * Inicia a monitoração de alterações. * * @param {Element} elemento * @param {EditorArticulacaoController} editorCtrl Editor de articulação */ iniciar(elemento, editorCtrl) { this._lexml = editorCtrl.lexmlString; } /** * Finaliza a monitoração de alterações. * * @param {Element} elemento * @param {EditorArticulacaoController} editorCtrl Editor de articulação */ finalizar(elemento, editorCtrl) { } } function criarControleAlteracao(editorCtrl) { if ('MutationObserver' in window) { return new ControleAlteracaoMutationObserver(editorCtrl); } else { return new ControleAlteracaoComparativo(editorCtrl); } } export default criarControleAlteracao;