//Este script depende da biblioteca https://js.livro.online/bibliotecas_de_terceiros/qrcode.min.js e de imagens na mesma pasta deste arquivo //Variáveis globais var elementosNaPagina = []; var observer; let ref_cap_busca = {}; window.onload = (event) => { // A variavel metadados está definida no head do html. Foi colocada pelo script preparacao-moan.py const Interruptor_Som = new Audio('https://js.livro.online/moan-quarto/Interruptor.mp3'); const livroUrl = metadados.livroUrl; // 0 -> branco, 1 -> creme, 2 -> textura, 3 -> antigo const tipo_de_papel = ['#fff', 'antiquewhite', "url('https://js.livro.online/moan-quarto/olga-thelavart-HZm2XR0whdw-unsplash_P.jpg')", "url('https://js.livro.online/moan-quarto/paper-g5d2cae661_1280_Pixabay_user_geralt.jpg')"]; let indiceTipoPapel = 0; //Índice do tipo de papel const corpo = document.querySelector('body'); const quartoContent = document.getElementById('quarto-content'); const divPageNavigation = document.querySelector('.page-navigation'); const sidebar = document.getElementById('quarto-sidebar'); const marginSidebar = document.getElementById('quarto-margin-sidebar'); const sidebarItemContainer = document.querySelectorAll('.sidebar-item-container'); const spansChapterNumber = document.querySelectorAll('span.chapter-number'); const tocTitle = document.getElementById('toc-title'); let luz_apagada = false; const papel = document.querySelector('#papel'); const main = document.querySelector('main'); //Criar o menu de configuração do texto do livro var divMenuTexto = document.createElement('div'); divMenuTexto.id = 'moan-menu-texto'; // Função para criar um botão com uma imagem e atribuir uma função a ele function criarBotaoComFuncao(imagemSrc, funcao) { const botao = document.createElement('button'); const imagem = document.createElement('img'); imagem.src = imagemSrc; botao.appendChild(imagem); botao.addEventListener('click', function(){funcao()}); return botao; } let header = document.querySelector('header'); const tamanhoPadraoFonte_ = window.getComputedStyle( papel, null ).getPropertyValue( 'font-size' ); const tamanhoPadraoFonteArr = tamanhoPadraoFonte_.split('p'); const tamanhoPadraoFonte = tamanhoPadraoFonteArr[0]; function aplicarOpcoesUsuario(){ //**************** //Índices do array // 0 => fonte // 1 => papel // 2 => luz_apagada //***************** let salvo = localStorage.getItem('livro.online@'+livroUrl+'.config'); const quartoColorScheme = localStorage.getItem('quarto-color-scheme'); let modo_escuro = false; quartoColorScheme == "default"? modo_escuro = false : modo_escuro = true; let obj = JSON.parse(salvo); if(salvo){ if(obj[0]){//verifica se tem tamanho de fonte salvo aumentarFonte(obj[0]); // quando é passado um valor, a funcao nao aumenta, mas aplica o valor passado } if(obj[1]){//verifica se tem tipo de papel salvo indiceTipoPapel = obj[1]; papel.style.background = tipo_de_papel[obj[1]]; if (luz_apagada && !modo_escuro) { divPageNavigation.style.background = tipo_de_papel[obj[1]]; } if(modo_escuro){ papel.style.removeProperty('background'); } } if(obj[2]){//verifica se tem luz_apagada salvo luz_apagada = obj[2]; if(luz_apagada && !modo_escuro){ apagarLuz(); } } } } aplicarOpcoesUsuario(); function salvarOpcoesUsuario(chave,valor){ //**************** //Índices do array // 0 => fonte // 1 => papel // 2 => luz_apagada //***************** let salvo = localStorage.getItem('livro.online@'+livroUrl+'.config'); if(salvo){ let jsonSalvo = JSON.parse(salvo); let stringDados; switch(chave){ case 'fonte': jsonSalvo[0] = valor; stringDados = JSON.stringify(jsonSalvo); localStorage.setItem('livro.online@'+livroUrl+'.config',stringDados); break; case 'papel': jsonSalvo[1] = valor; stringDados = JSON.stringify(jsonSalvo); localStorage.setItem('livro.online@'+livroUrl+'.config',stringDados); break; case 'luz_apagada': jsonSalvo[2] = valor; stringDados = JSON.stringify(jsonSalvo); localStorage.setItem('livro.online@'+livroUrl+'.config',stringDados); break; }//fecha switch } else { let dados = []; let stringDados; switch(chave){ case 'fonte': dados[0] = valor; stringDados = JSON.stringify(dados); localStorage.setItem('livro.online@'+livroUrl+'.config',stringDados); break; case 'papel': dados[1] = valor; stringDados = JSON.stringify(dados); localStorage.setItem('livro.online@'+livroUrl+'.config',stringDados); break; case 'fundo': dados[2] = valor; stringDados = JSON.stringify(dados); localStorage.setItem('livro.online@'+livroUrl+'.config',stringDados); break; }//fecha switch do else }//fecha else }//fecha a função salvarOpcoesUsuario(chave,valor) // Adicionar a biblioteca para gerar qrcode // Crie um elemento script const scriptElement = document.createElement('script'); // Defina o atributo src para o caminho da biblioteca QRCode.js scriptElement.src = 'https://js.livro.online/bibliotecas_de_terceiros/qrcode.min.js'; // Adicione o elemento script ao final do corpo do documento document.body.appendChild(scriptElement); //Criar a janela modal para mostrar as referencias // Crie a div da janela modal const modal = document.createElement("div"); modal.id = "modal"; modal.className = "modal"; modal.style.display = "none"; // Crie o conteúdo da janela modal const modalContent = document.createElement("div"); modalContent.className = "modal-content"; // Crie o botão de fechar const closeBtn = document.createElement("span"); closeBtn.className = "close"; closeBtn.innerHTML = "×"; closeBtn.style.fontSize = "20px"; // Crie o conteúdo da modal const referenciaDiv = document.createElement("div"); const referenciaLabel = document.createElement("p"); referenciaLabel.innerHTML = "Referência"; const referenciaSpan = document.createElement("span"); referenciaSpan.id = "ref"; referenciaDiv.appendChild(referenciaLabel); referenciaDiv.appendChild(referenciaSpan); const linkDiv = document.createElement("div"); const linkLabel = document.createElement("p"); linkLabel.innerHTML = "Link"; const linkSpan = document.createElement("span"); linkSpan.id = "link"; linkDiv.appendChild(linkLabel); linkDiv.appendChild(linkSpan); const qrCodeLabel = document.createElement("p"); qrCodeLabel.innerHTML = "QR Code"; const qrCodeContainer = document.createElement("div"); qrCodeContainer.id = "qrcode_container"; // Adicione todos os elementos à janela modal modalContent.appendChild(closeBtn); modalContent.appendChild(referenciaDiv); modalContent.appendChild(linkDiv); modalContent.appendChild(qrCodeLabel); modalContent.appendChild(qrCodeContainer); modal.appendChild(modalContent); // Adicione a janela modal ao corpo do documento document.body.appendChild(modal); // Função para diminuir a fonte function diminuirFonte() { let tamDivMenuTexto = window.getComputedStyle( divMenuTexto, null ).getPropertyValue( 'font-size' ); let tamHeader = window.getComputedStyle( header, null ).getPropertyValue( 'font-size' ); let TamString = window.getComputedStyle( papel, null ).getPropertyValue( 'font-size' ); let TamArr = TamString.split('p'); let Tam = parseInt(TamArr[0]); let novoTamanho = Tam-2; papel.style.fontSize = `${novoTamanho}px`; divMenuTexto.style.fontSize = tamDivMenuTexto; header.style.fontSize = tamHeader; salvarOpcoesUsuario('fonte', novoTamanho); } // Função para aumentar a fonte function aumentarFonte(tamSalvo) { let tamDivMenuTexto = window.getComputedStyle( divMenuTexto, null ).getPropertyValue( 'font-size' ); let tamHeader = window.getComputedStyle( header, null ).getPropertyValue( 'font-size' ); if(tamSalvo !== undefined){ papel.style.fontSize = `${tamSalvo}px`; divMenuTexto.style.fontSize = tamDivMenuTexto; header.style.fontSize = tamHeader; } else { let TamString = window.getComputedStyle( papel, null ).getPropertyValue( 'font-size' ); let TamArr = TamString.split('p'); let Tam = parseInt(TamArr[0]); let novoTamanho = Tam+2; papel.style.fontSize = `${novoTamanho}px`; divMenuTexto.style.fontSize = tamDivMenuTexto; header.style.fontSize = tamHeader; salvarOpcoesUsuario('fonte', novoTamanho); } } // Função para retornar o tamanho da fonte ao padrão function retornarFonteSize() { papel.style.fontSize = tamanhoPadraoFonte+"px"; salvarOpcoesUsuario('fonte', tamanhoPadraoFonte); } // Função para mudar o papel function mudarPapel() { if (corpo.classList.contains('quarto-dark')) {//Nao permitir a mudanca de papel no modo escuro alert("Você precisa desabilitar o modo escuro para poder alterar o papel."); return } indiceTipoPapel+= 1 if (indiceTipoPapel > tipo_de_papel.length-1) { indiceTipoPapel = 0 } papel.style.background = tipo_de_papel[indiceTipoPapel]; salvarOpcoesUsuario('papel', indiceTipoPapel); if (luz_apagada){ divPageNavigation.style.background = tipo_de_papel[indiceTipoPapel]; } } function acenderLuz() { quartoContent.classList.remove('luz_apagada'); divPageNavigation.style.removeProperty('background'); sidebar.style.removeProperty('color') sidebar.classList.remove('luz_apagada'); sidebarItemContainer.forEach(item => { item.style.removeProperty('color'); }); spansChapterNumber.forEach((span) => { if(span.parentNode.nodeName.toUpperCase() !== 'H1' && !span.parentNode.classList.contains('nav-page-text')){ span.style.removeProperty('color'); } }); marginSidebar.style.removeProperty('color'); if(tocTitle){tocTitle.style.removeProperty('color');} luz_apagada = false; } function apagarLuz() { quartoContent.classList.add('luz_apagada'); divPageNavigation.style.backgroundColor = tipo_de_papel[indiceTipoPapel]; papel.style.background = tipo_de_papel[indiceTipoPapel]; sidebar.style.color = '#fff' sidebar.classList.add('luz_apagada'); sidebarItemContainer.forEach(item => { item.style.color = '#fff'; }); spansChapterNumber.forEach((span) => { if(span.parentNode.nodeName.toUpperCase() !== 'H1' && !span.parentNode.classList.contains('nav-page-text')){ span.style.color = '#fff'; } }); marginSidebar.style.color = '#fff'; if(tocTitle){tocTitle.style.color = '#fff';} luz_apagada = true; } // Função para alternar o estado da luz function alternarEstadoDaLuz() { if (corpo.classList.contains('quarto-dark')) {//Nao permitir a mudanca de papel no modo escuro alert("Você precisa desabilitar o modo escuro para o estado da luz de fundo."); return } if (luz_apagada) {//está apagada a luz papel.style.background = tipo_de_papel[indiceTipoPapel]; Interruptor_Som.play(); acenderLuz(); salvarOpcoesUsuario('luz_apagada', false); } else {// luz acesa papel.style.background = tipo_de_papel[indiceTipoPapel]; Interruptor_Som.play(); apagarLuz(); salvarOpcoesUsuario('luz_apagada', true); } } // Crie e adicione os botões com as respectivas funções divMenuTexto.appendChild(criarBotaoComFuncao('https://js.livro.online/moan-quarto/text_decrease_FILL0_wght400_GRAD0_opsz24.svg', diminuirFonte)); divMenuTexto.appendChild(criarBotaoComFuncao('https://js.livro.online/moan-quarto/text_increase_FILL0_wght400_GRAD0_opsz24.svg', aumentarFonte)); divMenuTexto.appendChild(criarBotaoComFuncao('https://js.livro.online/moan-quarto/format_clear_FILL0_wght400_GRAD0_opsz24.svg', retornarFonteSize)); divMenuTexto.appendChild(criarBotaoComFuncao('https://js.livro.online/moan-quarto/note_FILL0_wght400_GRAD0_opsz24.svg', mudarPapel)); divMenuTexto.appendChild(criarBotaoComFuncao('https://js.livro.online/moan-quarto/emoji_objects_FILL0_wght400_GRAD0_opsz24.svg', alternarEstadoDaLuz)); main.insertBefore(divMenuTexto, main.firstChild); //Observar a mudanca de classe no body para ver se está no modo escuro ou nao // Defina as opções para o MutationObserver (observe mudanças nos atributos do elemento) const observerOptions = { attributes: true, attributeFilter: ["class"], }; // Crie uma função de retorno de chamada que será acionada quando a classe do body mudar function classeBodyMudou(mutationsList, observerClassCorpo) { for (const mutation of mutationsList) { if (mutation.type === "attributes" && mutation.attributeName === "class") { if (corpo.classList.contains('quarto-dark')) {// Ativar tudo para o padrao de luz acesa e papel padrao para nao afetar o efeito do modo escuro acenderLuz(); papel.style.removeProperty('background'); } else { aplicarOpcoesUsuario(); } } } } // Crie um MutationObserver com a função de retorno de chamada const observerClassCorpo = new MutationObserver(classeBodyMudou); // Inicie a observação do body com as opções definidas observerClassCorpo.observe(corpo, observerOptions); // Adiciona o container com a classe 'referencias_capitulo' quando o body estiver carregado var divBuscarRef = document.createElement('div'); divBuscarRef.className = 'referencias_capitulo'; var divContRef = document.createElement('div'); //Essa div é container apenas das referencia, e nao do input da busca. Foi colocado para a caixa de busca nao se mover conforme as refencias mudam com o scroll da página divContRef.className = 'cont_ref'; // Adiciona o span com id 'PaginacaoInicio' var paginacao = document.createElement('span'); paginacao.id = 'Paginacao'; divContRef.appendChild(paginacao); divBuscarRef.appendChild(divContRef); // Adiciona o input com a classe 'buscar_ref' var inputBusca = document.createElement('input'); inputBusca.id = 'busca_ref'; inputBusca.className = 'buscar_ref'; inputBusca.setAttribute('placeholder', 'Referência...'); inputBusca.style.backgroundImage = 'url("https://js.livro.online/moan-quarto/search_FILL0_wght400_GRAD0_opsz24.svg")'; inputBusca.style.backgroundRepeat = 'no-repeat'; inputBusca.style.backgroundPosition = '5px center'; inputBusca.style.paddingLeft = '25px'; // Ajuste o valor conforme necessário divBuscarRef.appendChild(inputBusca); //colocar icone de pegar referencia. "Link" // Crie o botão const botao = document.createElement("button"); botao.className = "pegarLink"; // Crie o span dentro do botão para conter a imagem e o texto const spanDentroDoBotao = document.createElement("span"); // Defina o estilo CSS para fazer o layout em coluna spanDentroDoBotao.style.display = "flex"; spanDentroDoBotao.style.flexDirection = "column"; spanDentroDoBotao.style.alignItems = "center"; // Centraliza os itens verticalmente // Adicione a imagem ao span const imagem = document.createElement("img"); imagem.src = "https://js.livro.online/moan-quarto/link_FILL0_wght400_GRAD0_opsz24.svg"; spanDentroDoBotao.appendChild(imagem); // Crie o texto const texto = document.createTextNode("link"); spanDentroDoBotao.appendChild(texto); // Adicione o span à classe "pegarLink" botao.appendChild(spanDentroDoBotao); // Adicione à divBuscarRef divBuscarRef.appendChild(botao); // Adicione um ouvinte de eventos para chamar a função quando o botão for pressionado botao.addEventListener("click", pegarReferencia); document.body.appendChild(divBuscarRef); const buscaRefInput = document.getElementById('busca_ref'); //Ativar um event listener para toda vez que a página correr, ou seja, toda vez que der scroll window.addEventListener("scroll", () => { elementosNaPagina = []; observarClasseUnidade(); console.log("Observador ativado"); }); // Montar e ativar o observador para conseguir fazer a "paginação", isto é, dizer se está entre 3P10 até 3P18, por exemplo //Primeiro montar a função que o observador vai executar function gerenciarPaginacao (entradas) { let QtdeEl = entradas.length; //quantidade total de elementos no array entradas let CountElAnalisados = 0; //conta quantos elementos já foram analisados se estão ou não na tela //ElementosNaPagina é transformado em array vazio toda vez que o capítulo, livro e a página mudam let AprontarLista = new Promise((resolve) => { QtdeEl === 0? resolve('lista vazia'): null; entradas.forEach( (entrada) => { CountElAnalisados++; if(entrada.isIntersecting){ elementosNaPagina.push(entrada) } if (CountElAnalisados === QtdeEl && elementosNaPagina.length != 0) {//Se o array entradas for vazio, teremos CountElAnalisados = 1 e QtdeEl = 0, logo, esse if vai para o else e damos um reject para não colocar os elementos iniciais e finais da classe unidade, pois significa que não temos elementos com a classe unidade resolve('lista pronta') } }) }); let ListaOrdenada = new Promise((resolve) => { let lista = elementosNaPagina.sort(function (a,b) { let aARR = a.target.id.split('P') let bARR = b.target.id.split('P') if (parseInt(aARR[1]) < parseInt(bARR[1])) return -1 if (parseInt(aARR[1]) > parseInt(bARR[1])) return 1 }); resolve(lista); }) AprontarLista.then( (resposta) => { if(resposta === 'lista pronta'){ ListaOrdenada.then((lista) => { let IndiceUltimo = lista.length - 1 if(lista[0].target.id === lista[IndiceUltimo].target.id){ paginacao.innerHTML = `${lista[0].target.id}`; } else { paginacao.innerHTML = `${lista[0].target.id} a ${lista[IndiceUltimo].target.id}`; } }).catch((err)=> console.log('Erro na lista: '+err)); } else if( resposta === 'lista vazia'){//Não faça nada console.log('Não tenho Unidade'); paginacao.innerHTML = '...'; } }).catch((err) => console.log('Erro: '+err)); } let options = { root: null, rootMargin: '0px', threshold: 0.01, delay: 1000, trackVisibility: true } // Agora sim setar o observador quando ativado function observarClasseUnidade(){ if(observer) observer.disconnect(); var ListaDeObservados = papel.querySelectorAll('.unidade'); var observados = Array.from(ListaDeObservados); if(observados.length === 0) { return } observer = new IntersectionObserver(gerenciarPaginacao, options); observados.map( (observado) => observer.observe(observado) ); } observarClasseUnidade(); //Fim observar a Classe Unidade // Use a função fetch para buscar o arquivo JSON com as referencias do capitulo para usar na busca por referencia buscaRefInput.addEventListener('focus', () => { // Quando o campo de entrada obtiver o foco, execute o fetch fetch('ref_capitulos.json') .then(response => { if (!response.ok) { throw new Error('Não foi possível carregar o arquivo JSON.'); } return response.json(); // Converte a resposta em JSON }) .then(data => { // Agora, a variável 'data' contém o conteúdo do arquivo JSON console.log(data); ref_cap_busca = data; }) .catch(error => { console.error(error); }); }); //Funcao para buscar a referencia function buscar_referencia(){ // Quando os livros antigos forem inseridos na plataforma, será necessário usar tb a funcao antiga, pois as referencias sao diferenetes let ref = buscaRefInput.value; const ref_maiuscula = ref.toUpperCase(); const refArr = ref_maiuscula.split('P'); const marcador_capitulo = refArr[0]; const urlCap = ref_cap_busca[marcador_capitulo]; if (!urlCap) { console.log('Referência não encontrada'); alert('Referência que começa com ' + marcador_capitulo + ' é inválida neste livro.'); return; } const caminho_a_seguir = '/' + urlCap + '#' + ref_maiuscula; window.location.href = caminho_a_seguir; } buscaRefInput.addEventListener('keydown', (event) => { if (event.key === 'Enter' || event.keyCode === 13) { event.preventDefault(); // Impede que o formulário seja enviado (se aplicável) buscar_referencia(); } }); //Funcao para mostrar a referencia na janela modal function mostrarReferencias(ref, link_completo) { // Preencha os elementos da modal com os valores document.getElementById("ref").textContent = ref; document.getElementById("link").textContent = link_completo; // Exiba a janela modal const modal = document.getElementById("modal"); modal.style.display = "block"; let qr_div = document.getElementById("qrcode_container"); qr_div.innerHTML = ""; let link = link_completo; const match = link.match(/:\/\/([^/]+)\/(.+)/); let link_para_gerar_qr_code = match[2]; //captura o que vem depois do domínio console.log("Verificando: " +link_para_gerar_qr_code); link_para_gerar_qr_code = link_para_gerar_qr_code.replace(/\//g, "--"); link_para_gerar_qr_code = link_para_gerar_qr_code.replace(/#/g, "__"); link_para_gerar_qr_code = "https://livro.online/qr-code/?livro=" + link_para_gerar_qr_code; // Crie o QR Code e adicione-o à div qrcode_container const qrcode = new QRCode(qr_div, { text: link_para_gerar_qr_code, colorDark: "#000000", colorLight: "#ffffff", correctLevel: QRCode.CorrectLevel.H }); } // Feche a janela modal ao clicar no botão "x" document.querySelector(".close").addEventListener("click", function() { const modal = document.getElementById("modal"); modal.style.display = "none"; }); //Pegar a referência da seleção //Funcao para pegar o ID do elemento function pegarID (el) { let i = 0 for(i; i < 10; i++){//busca a classe unidade ou unidade_silenciosa até o nono ancestral if(el && (el.classList.contains('unidade') || el.classList.contains('unidade_silenciosa'))){ return el.id } el.parentElement? el = el.parentElement: el = el; } } //Funcao para pegar a selecao function pegarReferencia(){ let selection; if (window.getSelection) { selection = window.getSelection(); } else if (document.selection) { selection = document.selection.createRange(); } if (selection.toString() === "") {//Se nao há selecao, pede para o usuário selecionar algum texto alert("Selecione um texto primeiro..."); return } let inicio = window.getSelection().anchorNode.parentElement let fim = window.getSelection().focusNode.parentElement if(inicio && fim) { let IdInicioSelecao = pegarID(inicio) let IdFimSelecao = pegarID(fim) let url = window.location.href; const urlObj = new URL(url); // Remove a query (parâmetros) da URL urlObj.search = ''; // Remove o hash (fragmento) da URL urlObj.hash = ''; //a URL Limpa let url_pagina_atual = urlObj.href; if(IdInicioSelecao === IdFimSelecao){ let link_completo = `${url_pagina_atual}${IdInicioSelecao? '#'+IdInicioSelecao:''}`; let ref = IdInicioSelecao; // Antes de preencher os elementos da modal, verifique se 'ref' é vazio ou consiste apenas de espaços em branco if (!ref || ref.trim() === "") { ref = "Elemento sem referência direta"; referenciaSpan.style.fontSize = "14px"; } else { referenciaSpan.style.fontSize = "30px"; } mostrarReferencias(ref, link_completo); } else if (IdInicioSelecao < IdFimSelecao){ let link_completo = `${url_pagina_atual}${IdInicioSelecao? '#'+IdInicioSelecao:'#'+IdFimSelecao}`; let ref = IdInicioSelecao; // Antes de preencher os elementos da modal, verifique se 'ref' é vazio ou consiste apenas de espaços em branco if (!ref || ref.trim() === "") { ref = "Elemento sem referência direta"; referenciaSpan.style.fontSize = "14px"; } else { referenciaSpan.style.fontSize = "30px"; } mostrarReferencias(ref, link_completo); } else { let link_completo = `${url_pagina_atual}${IdFimSelecao? '#'+IdFimSelecao:'#'+IdInicioSelecao}`; let ref = IdFimSelecao; // Antes de preencher os elementos da modal, verifique se 'ref' é vazio ou consiste apenas de espaços em branco if (!ref || ref.trim() === "") { ref = "Elemento sem referência direta"; referenciaSpan.style.fontSize = "14px"; } else { referenciaSpan.style.fontSize = "30px"; } mostrarReferencias(ref, link_completo); }//fecha else if de id de selecao inicio e fim }//fecha o if de inicio e fim }//fecha funcao pegarReferencia };