Skip to content

PandaDev

Menu
  • Blog
  • Manuais
  • Política de Privacidade
  • Página Inicial
Menu
três cubos um perto do outro, todos numa visão de cima e da diagonal direta. Cor de chumbo, desenhados à mão.

Módulos do Koha

2
  • Módulo de Administração do Koha – Parte 1: Parâmetros básicos: Bibliotecas
  • Módulo de Administração do Koha – Parte 2: Parâmetros Básicos: Grupos de Bibliotecas
desenhado a mão uma pasta de arquivo azul e amarela com um pincel em cima

Personalização

3
  • Snippets CSS
  • Citação ABNT no Koha
  • Inserindo menus de redes sociais no topo da OPAC
computador antigo, tela verde, cpu amarelada

Marc21

1
  • Marc21 – Guia rápido
lâmpada desenhada à mão com conteúdo em amarelo e um cérebro em vermelho dentro dela simbolizando uma nova ideia

Resolução de Problemas

1
  • Bug de Pagamento de Multas
Ver categorias
  • Página inicial
  • Tutoriais
  • Personalização
  • Citação ABNT no Koha

Citação ABNT no Koha

Tempo estimado de leitura: 11 minutos de leitura

SISTEMA USADO: Koha 25.05.05 || Fevereiro de 2026.

Tudo (ou quase tudo) no Koha pode ser modificado. E o guia de hoje pretende criar um sistema de alteração do Modal de citações. Parece confuso? Calma que vamos explicar.

A primeira coisa que eu fiz foi pesquisar por “Machado de Assis”, isto, porque me renderia um sem fim de opções de títulos.

Recorte de tela do catálogo do Koha identificando livros de Machados de Assis na busca.

E a seguir vou clicar no exemplar de “O alienista” para checarmos seus detalhes.

Estes detalhes são padrão e vão mostrar o koha assim:

Recorte de tela de Helena / O alienista

Neste recorte existem incongruências de catalogação, este não é o foco de nossa busca então peço a gentileza de relevarem essa questão. O que vamos nos focar aqui é em personalizar aquele pequeno menu lateral direto onde lemos “CITAR”

Recorte de tela com zoom no menu “citar”

Clicando aqui, um pop-up se abre. (como eu já tinha realizado a alteração, a imagem a seguir será de um recorte de outra obra, mas a visualização deve ser como a que aparece para você no Koha 25.05.05

Recorte de tela mostrando a obra “Lady Barberina” com pop-up aberto para citações tipo APA, Chicago, Harvard e MLA.

Como você nota, e se seu usuário precisar citar no Brasil? E se a pessoa em questão tiver dúvidas? (Quem nunca sofreu com a ABNT que atire a primeira pedra!). Nosso papel como bibliotecários (as) é também ajudar nessa questão. É facilitar essa busca. E se o koha pudesse mostrar pra nós a ABNT? Nosso objetivo aqui é justamente essa automatização.

Vamos customizar o modal de citações bibliográficas no OPAC do Koha para exibir formatadas corretamente segundo as normas:

  • ABNT NBR 6023:2018 (padrão brasileiro).
  • APA 7ª edição.
  • Chicago 17ª edição.
  • Harvard.
  • MLA 9ª edição.

O modal de citações original do Koha apresentava a formatação incorreta para todas as normas, ausência do local de publicação, títulos com capitalização errada, subtítulos não separados corretamente e ausência de elementos essenciais da ABNT.

Exemplo de problema:

❌ Itice Y., . (2024). Do Contra: Herança. Barueri, SP: Panini Brasil.

Mas o que precisávamos que aparecesse?

✅ YOSHI, Itice. Do contra: herança. Barueri: Panini Brasil, 2024.

Do que vamos precisar? 

  • Acesso à parte administrativa do Koha.
  • Permissão de Administrador ou acesso à Preferências do Sistema com todas as permissões necessárias.
  • Um navegador (!)
  • Conexão estável com a internet (!)

Tenha a prática de backup. Faça backup do conteúdo atual. Vá em Ferramentas > Personalização HTML > OpacUserJs

Copie tudo que tiver ali. Salve num bloco de notas. GUARDE. É seu backup. Se você não souber o que está fazendo, não altere rs. (inclusive fica aqui a minha dica de boa prática de nome para um arquivo de backup no formato backup-opacuserjs-AAAA-MM-DD.txt

Repita o processo para OPACUserCSS e salve como backup-opacusercss-AAAA-MM-DD.txt

Vamos editar o JavaScript que é como faremos nossa mágica. Cole em OpacUserJs.

$(document).ready(function(){
    // Interceptar quando o modal de citações for aberto
    $(document).on('show.bs.modal', '#citeModal', function (e) {
        setTimeout(function() {
            substituirCitacoes();
        }, 200);
    });
function substituirCitacoes() {
        var dados = {
            autor: extrairAutor(),
            titulo: extrairTitulo(),
            subtitulo: extrairSubtitulo(),
            edicao: extrairEdicao(),
            local: extrairLocal(),
            editora: extrairEditora(),
            ano: extrairAno(),
            tradutor: extrairTradutor(),
            isbn: extrairISBN(),
            paginas: extrairPaginas()
        };
        
        console.log('Dados extraídos:', dados);
        
        var htmlCitacoes = `
            <div class="citation-block abnt">
                <div class="citation-header">
                    <h4>ABNT <span class="citation-badge">NBR 6023:2018</span></h4>
                    <button class="btn-copy-citation" data-citation="abnt">
                        <i class="fa fa-copy"></i> Copiar
                    </button>
                </div>
                <p class="citation-text" id="citation-abnt">${gerarABNT(dados)}</p>
            </div>
            
            <div class="citation-block">
                <div class="citation-header">
                    <h4>APA <span class="citation-badge">7ª edição</span></h4>
                    <button class="btn-copy-citation" data-citation="apa">
                        <i class="fa fa-copy"></i> Copiar
                    </button>
                </div>
                <p class="citation-text" id="citation-apa">${gerarAPA(dados)}</p>
            </div>
            
            <div class="citation-block">
                <div class="citation-header">
                    <h4>Chicago <span class="citation-badge">17ª edição</span></h4>
                    <button class="btn-copy-citation" data-citation="chicago">
                        <i class="fa fa-copy"></i> Copiar
                    </button>
                </div>
                <p class="citation-text" id="citation-chicago">${gerarChicago(dados)}</p>
            </div>
            
            <div class="citation-block">
                <div class="citation-header">
                    <h4>Harvard</h4>
                    <button class="btn-copy-citation" data-citation="harvard">
                        <i class="fa fa-copy"></i> Copiar
                    </button>
                </div>
                <p class="citation-text" id="citation-harvard">${gerarHarvard(dados)}</p>
            </div>
            
            <div class="citation-block">
                <div class="citation-header">
                    <h4>MLA <span class="citation-badge">9ª edição</span></h4>
                    <button class="btn-copy-citation" data-citation="mla">
                        <i class="fa fa-copy"></i> Copiar
                    </button>
                </div>
                <p class="citation-text" id="citation-mla">${gerarMLA(dados)}</p>
            </div>
        `;
        
        $('#citeModal .modal-body').html(htmlCitacoes);
        
        $('.btn-copy-citation').on('click', function() {
            var tipo = $(this).data('citation');
            var textoElemento = $('#citation-' + tipo);
            var texto = textoElemento.text();
            
            navigator.clipboard.writeText(texto).then(function() {
                var botao = $('[data-citation="' + tipo + '"]');
                var textoOriginal = botao.html();
                botao.addClass('copied').html('<i class="fa fa-check"></i> Copiado!');
                
                setTimeout(function() {
                    botao.removeClass('copied').html(textoOriginal);
                }, 2000);
            }).catch(function(err) {
                console.error('Erro ao copiar:', err);
                alert('Erro ao copiar citação');
            });
        });
    }
// ====================================
    // FUNÇÕES AUXILIARES DE LIMPEZA
    // ====================================
    
    function limparAutor(autor) {
        autor = autor.replace(/\d{4}-\d{4}/g, '').trim();
        autor = autor.replace(/\([^)]+\)/g, '').trim();
        autor = autor.replace(/\[AUTOR\],?\s*/i, '').trim();
        autor = autor.replace(/\s+/g, ' ').trim();
        autor = autor.replace(/,\s*$/, '');
        return autor;
    }
    
    function limparTitulo(titulo) {
        titulo = titulo.replace(/\[[^\]]+\]/g, '').trim();
        if (titulo.includes(';')) {
            titulo = titulo.split(';')[0].trim();
        }
        return titulo;
    }
    
    function capitalizarNomeProprio(texto) {
        return texto.split(' ').map(palavra => {
            if (['de', 'da', 'do', 'das', 'dos', 'e'].includes(palavra.toLowerCase())) {
                return palavra.toLowerCase();
            }
            return palavra.charAt(0).toUpperCase() + palavra.slice(1).toLowerCase();
        }).join(' ');
    }
    
    // ====================================
    // FUNÇÕES DE EXTRAÇÃO DE DADOS
    // ====================================
    
    function extrairAutor() {
        var autor = $('.author a').first().text().trim();
        
        if (!autor) {
            autor = $('span[property="author"]').text().trim();
        }
        
        if (!autor) {
            autor = $('h5.author').text().replace('Por:', '').trim();
        }
        
        autor = limparAutor(autor);
        return autor || 'Autor não identificado';
    }
    
    function extrairTitulo() {
        var tituloCompleto = $('h1.title').first().text().trim();
        
        if (!tituloCompleto) {
            tituloCompleto = $('#catalogue_detail_biblio h1').first().text().trim();
        }
        
        tituloCompleto = limparTitulo(tituloCompleto);
        
        var titulo = tituloCompleto;
        if (tituloCompleto.includes(':')) {
            titulo = tituloCompleto.split(':')[0].trim();
        }
        
        titulo = titulo.replace(/\s+(graphic|msp|dvd|cd|audiobook).*$/i, '').trim();
        return titulo;
    }
    
    function extrairSubtitulo() {
        var tituloCompleto = $('h1.title').first().text().trim();
        tituloCompleto = limparTitulo(tituloCompleto);
        
        if (tituloCompleto.includes(':')) {
            var subtitulo = tituloCompleto.split(':').slice(1).join(':').trim();
            subtitulo = subtitulo.replace(/\s+(graphic|msp|dvd|cd|audiobook).*$/i, '').trim();
            return subtitulo;
        }
        return '';
    }
    
    function extrairTradutor() {
        var detalhes = $('#catalogue_detail_biblio').text();
        
        var match = detalhes.match(/tradução[^:]*:\s*([^;]+)/i);
        if (match) {
            var tradutor = match[1].trim();
            tradutor = tradutor.replace(/para\s+[^:]+:\s*/i, '');
            return tradutor;
        }
        
        var statement = $('span.results_summary.author').text();
        match = statement.match(/tradução[^:]*:\s*([^;]+)/i);
        if (match) {
            return match[1].trim();
        }
        
        return '';
    }
    
    function extrairEdicao() {
        var edicaoTexto = $('span.results_summary.edition').text();
        
        if (!edicaoTexto) {
            edicaoTexto = $('#catalogue_detail_biblio').text();
        }
        
        var match = edicaoTexto.match(/Edição:\s*(\d+)/i);
        if (match) {
            return match[1];
        }
        
        match = edicaoTexto.match(/(\d+)ª\s*ed/i);
        if (match) {
            return match[1];
        }
        
        return '';
    }
    
    function extrairLocal() {
        var detalhes = $('span.results_summary.publisher').text();
        
        if (!detalhes) {
            detalhes = $('.results_summary:contains("Detalhes da publicação")').text();
        }
        
        var localLink = $('a[href*="q=pl:"]').first().text().trim();
        
        if (localLink) {
            localLink = localLink.replace(/,\s*(SP|RJ|MG|RS|PR|SC|BA|PE|CE|PA|AM|GO|DF|MT|MS|RO|AC|RR|AP|TO|MA|PI|RN|PB|AL|SE|ES).*$/i, '').trim();
            return localLink;
        }
        
        var match = detalhes.match(/\[([^\]]+),\s*[A-Z]{2}\]/);
        if (match) {
            return match[1];
        }
        
        return 'Local não identificado';
    }
    
    function extrairEditora() {
        var editoraLink = $('a[href*="Provider:"]').first().text().trim();
        
        if (editoraLink) {
            editoraLink = editoraLink.replace(/^Editora\s+/i, '');
            return editoraLink;
        }
        
        var detalhes = $('span.results_summary.publisher').text();
        var match = detalhes.match(/\]\s*([^\[]+)\s*\[/);
        if (match) {
            return match[1].trim();
        }
        
        return 'Editora não identificada';
    }
    
    function extrairAno() {
        var anoLink = $('a[href*="copydate:"]').first().text().trim();
        
        if (anoLink) {
            return anoLink;
        }
        
        var detalhes = $('span.results_summary.publisher').text();
        var match = detalhes.match(/\[(\d{4})\]/);
        if (match) {
            return match[1];
        }
        
        return 's.d.';
    }
    
    function extrairISBN() {
        var isbn = $('span.results_summary.isbn').text().trim();
        var match = isbn.match(/\d+[- ]?\d+[- ]?\d+[- ]?\d+/);
        return match ? match[0] : '';
    }
    
    function extrairPaginas() {
        var detalhes = $('span.results_summary.extent, span.results_summary.physical').text();
        var match = detalhes.match(/(\d+)\s*(p\.|páginas|pages)/i);
        return match ? match[1] : '';
    }
    
    // ====================================
    // FUNÇÕES DE FORMATAÇÃO
    // ====================================
    
    function gerarABNT(d) {
        var autor = formatarAutorABNT(d.autor);
        
        var titulo = d.titulo.toLowerCase();
        titulo = titulo.charAt(0).toUpperCase() + titulo.slice(1);
        
        var citacao = autor + '. ';
        citacao += '<strong>' + titulo;
        
        if (d.subtitulo) {
            var subtitulo = d.subtitulo.toLowerCase();
            citacao += ': ' + subtitulo;
        }
        citacao += '</strong>. ';
        
        // Adicionar tradutor se houver
        if (d.tradutor) {
            var tradutorFormatado = capitalizarNomeProprio(d.tradutor);
            citacao += 'Tradução: ' + tradutorFormatado + '. ';
        }
        
        if (d.edicao && d.edicao !== '1') {
            citacao += d.edicao + '. ed. ';
        }
        
        citacao += d.local + ': ' + d.editora + ', ' + d.ano + '.';
        
        if (d.paginas) {
            citacao += ' ' + d.paginas + ' p.';
        }
        
        return citacao;
    }
    
    function formatarAutorABNT(autor) {
        if (!autor || autor === 'Autor não identificado') {
            return 'AUTOR NÃO IDENTIFICADO';
        }
        
        autor = autor.replace(/,+/g, '').trim();
        var partes = autor.split(/\s+/);
        
        if (partes.length === 1) {
            return partes[0].toUpperCase();
        }
        
        var sobrenome = partes[partes.length - 1].toUpperCase();
        var nomes = partes.slice(0, -1).join(' ');
        
        return sobrenome + ', ' + nomes;
    }
    
    function gerarAPA(d) {
        var autorLimpo = d.autor.replace(/,+/g, '').trim();
        var partes = autorLimpo.split(/\s+/);
        var sobrenome = partes[partes.length - 1];
        var iniciais = partes.slice(0, -1).map(n => n.charAt(0).toUpperCase() + '.').join(' ');
        
        var citacao = sobrenome + ', ' + iniciais + ' (' + d.ano + '). ';
        citacao += '<em>' + d.titulo.charAt(0).toUpperCase() + d.titulo.slice(1).toLowerCase();
        
        if (d.subtitulo) {
            citacao += ': ' + d.subtitulo.charAt(0).toUpperCase() + d.subtitulo.slice(1).toLowerCase();
        }
        citacao += '</em>';
        
        if (d.edicao && d.edicao !== '1') {
            citacao += ' (' + d.edicao + 'ª ed.)';
        }
        
        citacao += '. ' + d.editora + '.';
        
        return citacao;
    }
    
    function gerarChicago(d) {
        var autorLimpo = d.autor.replace(/,+/g, '').trim();
        var partes = autorLimpo.split(/\s+/);
        var sobrenome = partes[partes.length - 1];
        var nomes = partes.slice(0, -1).join(' ');
        
        var citacao = sobrenome + ', ' + nomes + '. ';
        citacao += '<em>' + d.titulo.charAt(0).toUpperCase() + d.titulo.slice(1).toLowerCase();
        
        if (d.subtitulo) {
            citacao += ': ' + d.subtitulo.charAt(0).toUpperCase() + d.subtitulo.slice(1).toLowerCase();
        }
        citacao += '</em>. ';
        
        if (d.edicao && d.edicao !== '1') {
            citacao += d.edicao + 'ª ed. ';
        }
        
        citacao += d.local + ': ' + d.editora + ', ' + d.ano + '.';
        
        return citacao;
    }
    
    function gerarHarvard(d) {
        var autorLimpo = d.autor.replace(/,+/g, '').trim();
        var partes = autorLimpo.split(/\s+/);
        var sobrenome = partes[partes.length - 1];
        var iniciais = partes.slice(0, -1).map(n => n.charAt(0).toUpperCase()).join('');
        
        var citacao = sobrenome + ', ' + iniciais + ' (' + d.ano + ') ';
        citacao += '<em>' + d.titulo.charAt(0).toUpperCase() + d.titulo.slice(1).toLowerCase();
        
        if (d.subtitulo) {
            citacao += ': ' + d.subtitulo.charAt(0).toUpperCase() + d.subtitulo.slice(1).toLowerCase();
        }
        citacao += '</em>';
        
        if (d.edicao && d.edicao !== '1') {
            citacao += ', ' + d.edicao + 'ª edn';
        }
        
        citacao += '. ' + d.local + ': ' + d.editora + '.';
        
        return citacao;
    }
    
    function gerarMLA(d) {
        var autorLimpo = d.autor.replace(/,+/g, '').trim();
        var partes = autorLimpo.split(/\s+/);
        var sobrenome = partes[partes.length - 1];
        var nomes = partes.slice(0, -1).join(' ');
        
        var citacao = sobrenome + ', ' + nomes + '. ';
        citacao += '<em>' + d.titulo.charAt(0).toUpperCase() + d.titulo.slice(1).toLowerCase();
        
        if (d.subtitulo) {
            citacao += ': ' + d.subtitulo.charAt(0).toUpperCase() + d.subtitulo.slice(1).toLowerCase();
        }
        citacao += '</em>. ';
        
        if (d.edicao && d.edicao !== '1') {
            citacao += d.edicao + 'ª ed., ';
        }
        
        citacao += d.editora + ', ' + d.ano + '.';
        
        return citacao;
    }
});

Eu não vou explicar linha por linha o que nosso código faz, mas de maneira mais suscita pra você entender a lógica. No bloco acima você está estruturando como você quer que a citação seja formatada e o que você quer que o código interprete como cada parte do item (título, sobrenome do autor, edição,etc). Como se cada parte fosse um item marc. E aqui nós formatamos porque a ABNT é só esse “como” apresentar a informação.

Então aqui ele vai ficar “seco”. Se você parar por aqui, já terá o código funcional. Mas se quiser deixar com cores melhores, visualmente mais agradável, então precisaremos de uma regra de css para melhorar isso. Vou deixar como fizemos a nossa no bloco a seguir. Cole no OpacUserCSS.

/*ABNT */

/* Modal de citações - Melhorias visuais */
#citeModal .modal-body {
    padding: 20px 25px;
    max-height: 500px;
    overflow-y: auto;
}

/* Cada bloco de citação */
#citeModal .citation-block {
    margin-bottom: 20px;
    padding-bottom: 18px;
    border-bottom: 1px solid #e8e8e8;
}

#citeModal .citation-block:last-child {
    border-bottom: none;
    margin-bottom: 0;
}

/* Cabeçalho da citação */
#citeModal .citation-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
}

#citeModal .modal-body h4 {
    color: #2c3e50;
    font-size: 15px;
    font-weight: 600;
    margin: 0;
    padding: 0;
    border: none;
}

/* Texto da citação */
#citeModal .citation-text {
    font-size: 14px;
    line-height: 1.7;
    color: #444;
    background: #f8f9fa;
    padding: 12px 15px;
    border-radius: 6px;
    border-left: 3px solid #007bff;
    margin: 0;
}

/* Botão copiar */
.btn-copy-citation {
    background: #007bff;
    color: white;
    border: none;
    padding: 4px 12px;
    font-size: 12px;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.2s;
    font-weight: 500;
}

.btn-copy-citation:hover {
    background: #0056b3;
    transform: translateY(-1px);
}

.btn-copy-citation:active {
    transform: translateY(0);
}

.btn-copy-citation.copied {
    background: #28a745;
}

/* Destaque para ABNT */
#citeModal .citation-block.abnt .citation-text {
    border-left-color: #28a745;
    background: #f0f8f4;
}

#citeModal .citation-block.abnt h4 {
    color: #28a745;
}

/* Badge com nome da norma */
.citation-badge {
    display: inline-block;
    background: #007bff;
    color: white;
    padding: 2px 8px;
    border-radius: 3px;
    font-size: 11px;
    font-weight: 600;
    margin-left: 8px;
    text-transform: uppercase;
}

.citation-block.abnt .citation-badge {
    background: #28a745;
}

/* Scrollbar customizada */
#citeModal .modal-body::-webkit-scrollbar {
    width: 8px;
}

#citeModal .modal-body::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 10px;
}

#citeModal .modal-body::-webkit-scrollbar-thumb {
    background: #888;
    border-radius: 10px;
}

#citeModal .modal-body::-webkit-scrollbar-thumb:hover {
    background: #555;
}

/* Responsivo */
@media (max-width: 576px) {
    #citeModal .citation-text {
        font-size: 13px;
        padding: 10px 12px;
    }
    
    #citeModal .citation-header {
        flex-direction: column;
        align-items: flex-start;
    }
    
    .btn-copy-citation {
        margin-top: 8px;
    }
}

Deve fornecer uma alteração visual assim:

Recorte de tela com alterações visuais e opção de copiar e colar.
Recorte dando enfoque à ABNT;

Boa sorte por aí.

Atualizado em fevereiro 9, 2026

Quais são seus sentimentos

  • Feliz
  • Normal
  • Triste

Compartilhe este artigo :

  • Facebook
  • X
  • LinkedIn
  • Pinterest
Snippets CSSInserindo menus de redes sociais no topo da OPAC
Tabela de conteúdos (TOC)
  • ABNT NBR 6023:2018
  • APA 7ª edição
  • Chicago 17ª edição
  • Harvard
  • MLA 9ª edição
© 2026 PandaDev | Powered by Minimalist Blog WordPress Theme