Marcador MarkIt
Este é um link de extensão do Chrome que permite destacar textos importantes em qualquer página da web. Revisite a página em 1 minuto, 1 semana ou 1 ano – seus dados estarão sempre lá.
Tecnologias
- (Baunilha) JavaScript
- API do Google
Características
- Destaque qualquer texto e pressione Command+K para salvá-lo automaticamente
- O usuário pode limpar os destaques armazenados para qualquer URL com um comando simples, Command+Shift+A
- Sincroniza em todos os dispositivos - se você destacar o texto de um laptop e olhar a mesma página da web em seu telefone, seus destaques estarão lá (se você estiver conectado ao Chrome em ambos).
Minha estrutura de dados armazenada (objeto)
highlights = {
google.com: {
text1: ["query selector", index, note, color]
text2: ["query selector", index, note, color]
},
yahoo.com: {
text3: ["query selector", index, note, color],
text4: ["query selector", index, note, color]
},
https://developer.mozilla.org/en-US/docs/Web/API/document/execCommand: {
"When an HTML document has been switched to designMode, its document object exposes an execCommand": ["p.summary", 20],
"A DOMString specifying the name of the command to execute. See Commands for a list of possible commands.": ["p", 0, "example note", #CFFFDF]
}
}
Como funciona
Tenho dois scripts que carregam em cada página. O primeiro é background.js, que escuta um evento específico. O evento Command+K aciona uma função que injeta um script no navegador (injection_script.js), que destaca o texto selecionado.
Para destacar, arraste o mouse sobre algum texto e pressione Command+K. Isso aciona uma função que chama várias outras. Sequência de eventos:
- Captura o texto selecionado
- Ativa o Modo Design, permitindo-nos fazer alterações temporárias no DOM
- Se o fundo já estiver destacado, precisamos remover o destaque:
- Seleciona a tag < span > ao redor do texto e define style.backgroundColor = transparente (remova o destaque)
- Obtém o objeto 'destaques' do armazenamento -
chrome.storage.get()
- Percorre todas as teclas (que são os destaques salvos) para procurar uma correspondência e a exclui do armazenamento
- Caso contrário, envolva o texto em um <span> e aplique a cor de fundo
- Atualização na página: recuperar 'destaques' do armazenamento
- Se não houver dados para o URL ativo, defina a chave para o URL atual e o valor para um objeto vazio (aol.com: {})
- Se houver, pegue a estrutura de dados de destaques do armazenamento (chrome.storage.get())
- Recuperar e atribuir um valor de seletor de consulta válido para o texto selecionado (isso será usado para consultar o DOM e aplicar os destaques posteriormente. Consulte a estrutura do objeto acima para esclarecimentos)
- Se o elemento pai do texto destacado tiver um nome de classe, armazene uma string "element.className" ("p.firstParagraph", "h2.sectionHeader", etc)
- Se não houver nome de classe, armazene a string "element" ("p", "h2", "li", etc)
- Dê um valor à chave (texto destacado) (uma matriz contendo 2 valores - primeiro, o seletor de consulta e segundo, o índice de onde o texto selecionado ocorreu no elemento pai)
- Eu armazeno o índice da string porque se eu armazenasse apenas o texto e o seletor de consulta, digamos que você destacou "o" sob uma tag "p", ao aplicar os destaques se você atualizar a página, cada ocorrência de "o" em um A tag "p" ficará destacada. Adicionar o valor indexOf me permite verificar se os índices correspondem ao DOM e só então aplicar o destaque, então estou aplicando o destaque à palavra correta.
- Armazene a variável de destaques atualizada contendo o novo texto destacado usando chrome.storage.set()
- Desligue o modo de design
O segundo arquivo JavaScript executado em cada página é content_script.js. Ele verifica se existe um objeto armazenado chamado 'destaques'. Se não houver, significa que o usuário nunca destacou nada. Em seguida, ele criou um objeto vazio e o armazenou no Chrome.
Se encontrar um objeto 'destaques', verifica se há dados armazenados para a URL ativa. Se não houver, o script retorna.
Se houver destaques armazenados para o URL:
- A função applyHighlights() é executada
- São necessários dois parâmetros, o objeto 'destaques' e o URL ativo
- Faz um loop pelas chaves do objeto armazenado (as chaves são os destaques armazenados, enquanto os valores dessas chaves são uma matriz contendo os valores querySelector e indexOf)
- Executa document.body.querySelectorAll() para obter uma matriz de todos os nós correspondentes
- Faz um loop através de cada nó retornado e se o innerHTML contiver uma "string" correspondente à chave do objeto (texto destacado) E no mesmo valor indexOf: 1. Executa uma função .replace() envolvendo o texto correspondente em uma tag < span > com um atributo de estilo embutido para a cor de fundo
- observação lateral: originalmente passei por cada nó DOM recursivamente para verificar se há correspondências, mas armazenar o valor querySelector e comparar os valores HTML apenas dos nós correspondentes com meus valores armazenados é significativamente mais rápido.
Atualizações para a próxima versão
- Armazene a string específica que você destacou
- "Baixe a biblioteca jQuery em jQuery.com".
- Se você destacar o segundo “jQuery”, o valor armazenado será da primeira instância.
- Isso ocorre porque o valor indexOf que armazeno retorna após a primeira correspondência
- PLAN - inicia a contagem do índice após a tag span
- não é possível destacar os elementos do bloco (se você arrastar o destaque de um h2 para a tag ap, apenas o h2 será registrado)
- EM ANDAMENTO: permitir que os usuários escolham a cor de destaque
- Faça com que o número de destaques e destaques reais de uma página apareça na extensão popup.html
- Limitações/casos extremos: e-mail, PDFs
- Solicito permissões para todos os sites. para o qual alguns sites bloqueiam o acesso '*' (cnn.com)
- Se você destacar "jQuery" em um elemento e realçá-lo novamente em outro, o segundo substitui o primeiro (porque a chave é a mesma)
- Se o elemento pai for uma tag inline o innertext/html indexOf não registra (-1) ou termina o destaque no final da tag inline Encontre o índice da tag span e inicie o indexOf lá
- Modo de recolhimento - recolhe o documento apenas para os elementos pais dos destaques armazenados
Problemas resolvidos
- Armazenar destaques abrangendo tags de elementos embutidos (a, em, st, etc.)
- Antes, apenas o texto antes da tag inline era salvo, pois eu armazenava o innerText
- Eu resolvi isso armazenando o innerHTML
- O problema que surgiu com essa mudança foi que eu estava armazenando o indexOf do innerText, que reaplicaria os realces ao texto padrão dentro de um elemento de texto, como uma tag "p". Mas o indexOf é diferente para itens em elementos inline porque o indexOf conta cada caractere nas tags.
- Para resolver isso, comparo os valores innerText.indexOf E innerHTML.indexOf e comparo cada um com os nós correspondentes ao aplicar destaques às páginas que um usuário está visitando novamente.
- Se você clicasse duas vezes para destacar uma seção, os valores indexOf não seriam registrados e, portanto, meu aplicativo não poderia reaplicar os destaques
- Para resolver adicionei os métodos .toString() e .trim() ao indexOf(...)
- Destacar uma tag <a> removeria o link no carregamento da página.
Atualizações futuras
## Imagem de exemplo
Casos extremos
- Se os nomes das classes mudarem
- Solução: se o nome da classe não existir no DOM, retire o nome da classe do seletor de consulta e apenas pesquise os nós da tag do elemento
- Se o conteúdo estiver oculto por um botão, meus destaques não serão registrados porque pesquisa on_load e o conteúdo só é revelado após um evento do navegador (por isso não funciona no email)
Permitir que alguém acesse todos os destaques no popup.html Permitir que os usuários alterem a cor do marcador Corrigir bug de destaque de elemento embutido