Extensibilidade das anotações
A Browser Annotation API permite que o seu site personalize o que as pessoas selecionam, o contexto que acompanha os seus comentários e os controlos que utilizam para pré-visualizar alterações antes de enviar uma anotação para o ChatGPT.
As anotações do navegador funcionam no seu site sem quaisquer alterações ao código. As pessoas podem selecionar parte de uma página, adicionar um comentário e enviá-lo no Context para o Codex ou o ChatGPT Work.
Enquanto programador, pode utilizar a Browser Annotation API para fornecer contexto ou controlos específicos da sua aplicação. Por exemplo, pode anexar pré-visualizações de variantes de componentes numa pré-visualização de um sistema de design, para que os programadores saibam como atualizar os componentes num site.
Para obter ajuda para compreender a Browser Annotation API ou adicionar suporte a anotações ao seu site, instale o plugin Annotations Extensibility.
Instalar o plugin Annotations Extensibility
Experimente
Veja a Browser Annotation API em ação neste guia.
- Abra esta página no navegador integrado do ChatGPT.
- Experimente abrir o pedido sugerido que aparecerá neste cartão.
- Entre no modo de anotação e, em seguida, selecione a tabela abaixo ou um exemplo de código para alternar entre disposições e temas predefinidos.
- Pode continuar a anotar qualquer item da página e a observar o comportamento predefinido das anotações.
Abra esta página no navegador integrado do ChatGPT para experimentar as anotações.
Escolher o que personalizar
Comece pela integração adequada ao seu site:
| Objetivo | Integração |
|---|---|
| Tornar um cartão ou outro grupo de elementos selecionável como um único objeto | Alvos de seleção |
| Permitir que as pessoas selecionem uma expressão ou frase | Contentores de seleção de texto |
| Incluir contexto adicional numa seleção | Metadados de seleção |
| Abrir uma anotação a partir do seu próprio botão com um comentário sugerido | Pedidos de anotação |
| Pedir comentários sobre uma passagem exata a partir da sua própria interface | Pedidos para intervalos de texto |
| Mostrar controlos avançados quando uma anotação é aberta | Predefinições do editor |
| Pré-visualizar propriedades da aplicação ou recolher escolhas | Controlos personalizados |
| Selecionar objetos individuais desenhados num canvas | Superfícies de anotação |
| Ativar ou desativar o modo de anotação a partir do seu site | Controlos do modo de anotação |
Este guia destina-se à versão DevDay 2026 da aplicação de ambiente de trabalho do ChatGPT e posteriores.
A API JavaScript está disponível através de document.oai.annotation no navegador
integrado da aplicação, em páginas seguras de nível superior, como HTTPS ou localhost. Quando
ativada, o navegador instala-a antes de executar os scripts da página. Detete a disponibilidade de
cada método para suportar navegadores mais antigos ou não compatíveis e, em seguida, inicialize a sua
integração assim que os respetivos elementos DOM existirem. Não é necessário qualquer evento de prontidão nem consulta periódica.
Os métodos da API devolvem resultados de forma síncrona e os identificadores de registo ficam prontos a utilizar
imediatamente. O navegador pode concluir o carregamento do editor de anotações depois disso.
A função de retorno hitTest de uma superfície pode devolver uma promessa.
Personalizar alvos de seleção
Por predefinição, o modo de anotação seleciona elementos do DOM da página, dando preferência a
alvos como texto, imagens e controlos. Para tornar um objeto maior selecionável,
marque a região que o contém com oai-annotation-container e os seus descendentes
selecionáveis com oai-annotatable.
Este exemplo torna um cartão de gráfico selecionável como um único objeto:
<section oai-annotation-container>
<article id="chart-card" oai-annotatable="Q3 Revenue">
<h2>Q3 Revenue</h2>
<p>$120,000 this quarter</p>
<button type="button">More info</button>
</article>
</section>Apontar para qualquer ponto do cartão realça o cartão inteiro. O valor opcional
oai-annotatable atribui ao objeto um nome apresentado ao utilizador e ao modelo.
Escolha nomes que distingam objetos próximos ou omita o valor.
O contentor define onde se aplicam estas regras de seleção. Um atributo
oai-annotatable, por si só, não altera o comportamento da seleção.
Dentro de um contentor, o navegador seleciona o alvo marcado mais próximo que contém
o elemento sob o ponteiro. Os contentores aninhados utilizam o contentor mais próximo.
As áreas não marcadas dentro de um contentor criam uma anotação de página Web; as áreas fora
de todos os contentores mantêm o comportamento predefinido.
Ativar a seleção de texto
Adicione oai-annotation-container-text a uma região para permitir que as pessoas arrastem para selecionar texto
durante o modo de anotação. O atributo não necessita de um valor:
<article oai-annotation-container-text>
<h2>Design guidelines</h2>
<p>Use consistent spacing between related components.</p>
<p>Leave more space between separate groups.</p>
</article>Ao soltar uma seleção não vazia, abre-se o editor de anotações de texto com o intervalo selecionado e o respetivo contexto. Clicar sem selecionar texto não cria uma anotação. Escape ou um gesto cancelado cancela a seleção.
O contentor de seleção de texto ou do DOM mais próximo determina como começa um gesto.
Os contentores de texto não utilizam marcadores oai-annotatable para selecionar elementos. Aninhe
um oai-annotation-container para restaurar a seleção de elementos ou um contentor de texto para
restaurar a seleção de texto. Se ambos os atributos estiverem no mesmo elemento, a seleção de texto
tem precedência.
A seleção de texto segue as regras normais de seleção da página e pode estender-se para além
do contentor inicial. Um contentor não limita o intervalo nem ativa a seleção
dentro de um iframe. Os campos de texto continuam a ser selecionáveis, mas os cliques normais na página e
as ações nativas dos controlos permanecem bloqueados durante o modo de anotação. As chamadas explícitas a
request() mantêm o seu comportamento existente.
Adicionar contexto a uma seleção
Adicione oai-annotation-metadata a um alvo marcado para incluir contexto que pode não
estar visível na página. Por exemplo, uma linha de contacto fictícia pode incluir um
endereço de e-mail para um pedido de redação de um e-mail:
<section oai-annotation-container>
<div
id="contact-row"
oai-annotatable="Alex Morgan"
oai-annotation-metadata='{"email":"alex@example.com"}'
>
<div>Alex Morgan</div>
<div>Project lead</div>
</div>
</section>Selecionar qualquer uma das linhas seleciona a linha de contacto inteira. Os metadados aparecem com a anotação e acompanham-na na conversa. Inclua apenas contexto que pretenda partilhar tanto com o utilizador como com o modelo. O envio de um e-mail continuaria a exigir uma ferramenta de e-mail ligada.
Utilize um objeto JSON pequeno e sem estruturas aninhadas, com estes limites:
- Até seis propriedades, com valores de cadeia de caracteres, número finito, booleano ou
null. - Chaves com até 64 caracteres e valores de cadeia de caracteres com até 256 caracteres.
- Até 2 048 bytes para o objeto serializado.
As chaves têm de começar por uma letra ASCII e conter apenas letras ASCII, algarismos, espaços, sublinhados ou hífenes. Utilize espaços simples entre palavras. Não são suportados objetos aninhados nem matrizes. O navegador ignora metadados inválidos.
Também pode fornecer metadados através de request() ou do resultado hitTest
de uma superfície.
Abrir uma anotação a partir do seu site
Chame document.oai.annotation.request(target, options) diretamente a partir de uma interação
do utilizador, como premir um botão. O alvo pode ser um elemento HTML ligado ao DOM
dentro da área visível do documento atual ou um
Range do DOM. Não necessita de atributos de
anotação. Os IDs de objetos virtuais não são suportados.
Os pedidos iniciados pelo site podem exigir permissão do utilizador; os utilizadores podem reativar funcionalidades de anotação bloqueadas em Ferramentas do site > Funcionalidades de anotação.
Adicione este botão junto ao cartão de gráfico do exemplo de seleção e execute o script depois de ambos os elementos existirem:
<button id="discuss-chart" type="button" hidden>Explain more</button>const card = document.getElementById("chart-card");
const button = document.getElementById("discuss-chart");
button.hidden = typeof document.oai?.annotation?.request !== "function";
button.addEventListener("click", () => {
const annotation = document.oai?.annotation;
if (typeof annotation?.request !== "function") return;
annotation.request(card, {
initialComment: "Explain the latest trend in this graph.",
});
});Selecionar Explicar melhor pede ao navegador que abra uma anotação com o cartão selecionado e um comentário editável. A pessoa pode editá-lo, guardá-lo e enviá-lo com a sua mensagem. Abrir uma anotação não envia uma mensagem para o ChatGPT; apenas o utilizador a pode enviar.
Mantenha a chamada dentro da interação ativa do utilizador. Aguardar primeiro um pedido de rede pode fazer com que essa interação se perca.
O segundo argumento opcional suporta estes campos:
| Opção | Comportamento |
|---|---|
mode |
Utilize "advanced" para abrir controlos avançados para um elemento ou "default" para utilizar o comportamento predefinido do editor. A predefinição é "default". Os controlos personalizados podem continuar a abrir com "default"; consulte Predefinições do editor. Os intervalos de texto suportam apenas "default". |
enterAnnotationMode |
Defina como true para entrar no modo de anotação e permanecer nele após cancelar ou enviar a anotação. |
metadata |
Metadados válidos e não vazios substituem os metadados HTML do alvo neste pedido. Esta opção é ignorada para intervalos de texto e quando o elemento alvo está dentro de um shadow DOM. |
initialComment |
Fornece um comentário editável, com até 240 unidades de código UTF-16. |
request() devolve um objeto com um booleano accepted. Verifique
result.accepted, e não o objeto de resultado, para saber se o navegador recebeu
e validou o pedido. Não confirma que o editor abriu nem que
a pessoa guardou ou enviou uma anotação.
Enquanto o editor carrega, o navegador pode manter um pedido aceite em espera. Pode recusar outro enquanto um pedido estiver pendente, um editor estiver aberto ou o ChatGPT estiver a controlar o navegador.
Pedir uma anotação para um intervalo de texto
Passe um Range do DOM para pedir comentários sobre uma passagem sem alterar a
seleção de texto do navegador. Este exemplo seleciona o conteúdo do parágrafo; não necessita
de um atributo oai-annotation-container-text:
<p id="draft-passage">Leave more space between separate groups.</p>
<button id="discuss-passage" type="button" hidden>Discuss this passage</button>Execute este script depois de ambos os elementos existirem:
const passage = document.getElementById("draft-passage");
const button = document.getElementById("discuss-passage");
button.hidden = typeof document.oai?.annotation?.request !== "function";
button.addEventListener("click", () => {
const annotation = document.oai?.annotation;
if (typeof annotation?.request !== "function") return;
const range = document.createRange();
range.selectNodeContents(passage);
annotation.request(range, {
initialComment: "Suggest a clearer version of this guidance.",
});
});O intervalo tem de conter texto visível não vazio no documento atual, com pelo menos parte da seleção na área visível da página. Pode conter, no máximo, 20 000 unidades de código UTF-16. Não são suportados intervalos recolhidos, texto composto apenas por espaços em branco, texto selecionado oculto nem intervalos em raízes shadow fechadas.
Os pedidos para intervalos de texto utilizam apenas o editor de texto predefinido. Um pedido com
mode: "advanced" é rejeitado e os metadados do pedido são ignorados. Mantenha o texto
alvo disponível enquanto um pedido aceite aguarda pelo editor: o navegador
volta a verificar o intervalo antes de o abrir. Os contentores de seleção de texto permitem, separadamente,
que as pessoas arrastem para selecionar texto durante o modo de anotação.
Escolher o modo predefinido do editor
Para mostrar controlos avançados imediatamente nas anotações abertas através da
interface de seleção do navegador, adicione esta etiqueta ao <head> da sua página:
<meta name="oai-annotation-editor-default-mode" content="advanced" />Para anotações abertas a partir da sua própria interface, passe { mode: "advanced" } a
request(). Utilize mode: "default", ou omita-o, para obter o comportamento predefinido do editor.
A definição meta da página não substitui esta opção do pedido. O modo predefinido
não garante um editor apenas de comentários: os controlos personalizados com valores iniciais
propostos, ou os controlos que omitem currentValue, podem abrir o editor de controlos.
Os controlos manuais Ajustar, de recolher e de Option-clique estão disponíveis apenas no Codex ou em localhost. Nos sites alojados no ChatGPT, os controlos personalizados registados aparecem automaticamente sem um botão Ajustar ou de recolher. O modo avançado pedido pela página continua a funcionar nesses sites.
Adicionar controlos personalizados
Utilize registerControls() para associar controlos de anotação a um ou mais elementos
DOM. Os controlos podem pré-visualizar propriedades da aplicação, como um token de espaçamento,
ou recolher escolhas a incluir num pedido, como o tom de um e-mail.
Pré-visualizar um token de espaçamento partilhado
Ambos os cartões deste exemplo utilizam a mesma propriedade CSS:
<style>
#component-preview {
--card-padding: 16px;
}
.preview-card {
padding: var(--card-padding);
border: 1px solid #d1d5db;
}
</style>
<section id="component-preview" oai-annotation-container>
<article class="preview-card" oai-annotatable="Profile card">
Profile card
</article>
<article class="preview-card" oai-annotatable="Summary card">
Summary card
</article>
</section>Execute este script depois de criar a pré-visualização:
const preview = document.getElementById("component-preview");
const annotation = document.oai?.annotation;
function previewSpacing(event) {
const { callback, value } = event.detail;
if (callback === "setCardPadding") {
preview.style.setProperty("--card-padding", `${value}px`);
}
}
let registration;
if (typeof annotation?.registerControls === "function") {
preview.addEventListener("oaiannotationcontrolchange", previewSpacing);
registration = annotation.registerControls({
targets: preview.querySelectorAll(".preview-card"),
controlsHeading: "Card spacing",
controlsMode: "replace",
controls: [
{
type: "range",
label: "Card padding (pixels)",
callback: "setCardPadding",
reference: "--card-padding",
min: 8,
max: 32,
step: 4,
currentValue: 16,
},
],
});
}
function disposeAnnotationControls() {
preview.style.removeProperty("--card-padding");
registration?.dispose();
preview.removeEventListener("oaiannotationcontrolchange", previewSpacing);
}Anote qualquer um dos cartões e altere Espaçamento interior do cartão (píxeis) de 16 para 24. Nos
sites alojados no ChatGPT, os controlos aparecem automaticamente; no Codex ou em
localhost, selecione Ajustar, se necessário. Ambos os cartões são atualizados. A anotação regista o rótulo, a referência
e os valores antigos e novos. Limpar a pré-visualização restaura o espaçamento interior original.
Chame disposeAnnotationControls() ao remover o componente.
Recolher uma escolha sem pré-visualização
Utilize a linha de contacto do exemplo de metadados para disponibilizar um tom de e-mail:
const contact = document.getElementById("contact-row");
const registration = document.oai?.annotation?.registerControls?.({
targets: contact,
controlsHeading: "Email options",
controlsMode: "replace",
controls: [
{
type: "select",
label: "Email tone",
callback: "emailTone",
options: [
{ label: "Professional", value: "professional" },
{ label: "Friendly", value: "friendly" },
{ label: "Direct", value: "direct" },
],
defaultValue: "professional",
},
],
});Este controlo não necessita de um processador de eventos porque não pré-visualiza uma alteração
na página. Omitir currentValue indica ao navegador que deve incluir o tom selecionado
mesmo que o utilizador mantenha a opção inicial. Chame registration?.dispose() ao
remover a linha.
Para controlos de seleção, as funções de retorno de pré-visualização recebem option.value, como
"professional". O histórico de anotações e o ChatGPT recebem o
option.label visível, como "Professional", tanto para as opções anteriores como para as
selecionadas. Utilize rótulos que expliquem cada escolha; os IDs internos em value não são
enviados como texto da escolha.
Configurar controlos e valores iniciais
Utilize controlsMode: "replace" para mostrar apenas os seus controlos para os alvos
registados ou "extend" para os mostrar juntamente com os controlos integrados. Um
controlsHeading opcional atribui um nome ao painel. O navegador remove os espaços nas extremidades e aceita de um a 80
caracteres. Sem um título, o painel mostra a etiqueta HTML do elemento. O
título não é incluído no contexto enviado para o ChatGPT.
Um registo suporta até 12 controlos. Cada um exige um type, um
label visível e um identificador callback:
| Tipo | Valor | Campos adicionais |
|---|---|---|
color |
Cor hexadecimal, como "#2563eb" |
Nenhum |
range |
Número | min, max e step |
select |
Cadeia de caracteres | options, uma matriz de objetos { label, value } |
toggle |
booleano | Nenhum |
callback é um identificador em forma de cadeia de caracteres, não uma função JavaScript. Torne-o único
dentro do registo, comece-o por uma letra ASCII e utilize letras ASCII,
algarismos, sublinhados ou hífenes. Um reference opcional identifica a propriedade
que está a ser alterada e acompanha o rótulo e o valor na anotação.
Defina currentValue como o valor normal válido da propriedade, incluindo alterações não
guardadas. Não utilize o estado de pré-visualização nem dados de entrada incompletos como referência. O navegador
utiliza-o para alterações de antes e depois e reposições. Quando o estado da aplicação mudar, utilize
registration.update({ controls }) para atualizar os valores currentValue
dos controlos. As atualizações afetam anotações futuras; as anotações existentes mantêm os
valores capturados.
Defina defaultValue para sugerir um valor inicial; tem precedência sobre
currentValue para o estado inicial
do controlo. Se omitir ambos, o controlo começa com branco para uma cor, o mínimo
para um intervalo, a primeira opção para uma seleção ou false para um interruptor.
Mantenha os valores propostos separados dos rascunhos normais. Se uma atualização lançar uma exceção ou um
pedido falhar ou devolver accepted: false, descarte a proposta tentada e
restaure o estado anterior dos controlos e da proposta. Mantenha as propostas quando um pedido
for aceite: o navegador pode colocá-lo em fila antes de capturar os controlos.
Validar controlos e registos
O navegador valida os registos e as atualizações de acordo com estes limites:
| Campo ou recurso | Restrição |
|---|---|
| Controlos | Até 12 por registo, com identificadores callback únicos. Utilize apenas os campos definidos para o tipo de controlo. |
| Rótulos e títulos | Os rótulos dos controlos, os rótulos das opções e controlsHeading têm de ser não vazios após a remoção dos espaços nas extremidades e ter, no máximo, 80 unidades de código UTF-16. O texto dos controlos não pode conter caracteres de controlo nem caracteres que alterem a direção do texto. |
| Identificadores | callback tem, no máximo, 80 unidades de código UTF-16 após a remoção dos espaços nas extremidades, utilizando o formato descrito acima. reference tem de 1 a 80 caracteres e permite letras ASCII, algarismos e _ . / : @ $ # -, sem espaços. |
| Opções de seleção | De 1 a 12 opções com cadeias de caracteres value distintas, com, no máximo, 512 unidades de código UTF-16. Os valores fornecidos de currentValue e defaultValue têm de corresponder ao valor de uma opção. |
| Valores de intervalo | min, max, currentValue e defaultValue têm de ser números finitos entre −10 000 e 10 000. É obrigatório min < max, um step de 0.001 a 10 000 que não seja superior a max - min e valores iniciais dentro do intervalo. Os valores iniciais não têm de estar alinhados com step. |
| Cores e interruptores | As cores têm de utilizar 3, 4, 6 ou 8 algarismos hexadecimais após #. Os valores dos interruptores têm de ser true ou false. |
| Alvos | De 1 a 128 entradas de alvos no momento do registo, todas elementos do documento atual. As atualizações podem passar targets: [] para desassociar. Cada documento suporta até 64 registos de controlos e 1 024 associações entre registos e alvos. |
| Controlos serializados | O conteúdo JSON que contém controls, controlsHeading e controlsMode tem de caber em 16 384 unidades de código UTF-16. Utilize dados que possam ser codificados como JSON, sem funções, símbolos ou inteiros grandes. |
registerControls() e registration.update() podem lançar exceções de forma síncrona devido a
definições ou alvos inválidos, ou a limites excedidos. Uma atualização após dispose()
também lança uma exceção. Uma atualização rejeitada preserva o registo anterior, incluindo
os seus controlos e alvos. Trate as falhas no local da chamada, mantenha a edição
normal utilizável e reutilize ou elimine os registos sob a sua responsabilidade para respeitar os
limites.
Tratar pré-visualizações e reposições
O evento oaiannotationcontrolchange propaga-se a partir do elemento selecionado. O seu
detail contém callback, value e action:
| Ação | Aplicar o valor fornecido para |
|---|---|
preview |
Mostrar a alteração pedida. |
preview-original |
Mostrar temporariamente o estado original para comparação. |
reset |
Restaurar o estado original quando a pré-visualização é limpa. |
Aplique o valor fornecido em todas as ações, como no exemplo de espaçamento. Torne os processadores reversíveis e seguros para chamadas repetidas. Os eventos de pré-visualização não pedem uma alteração permanente; guarde através do fluxo normal de gravação da sua aplicação. Mantenha os rascunhos normais, os dados de entrada incompletos e as pré-visualizações separados, para que alterações não relacionadas não substituam uma pré-visualização. Quando alguém editar a mesma definição, substitua a respetiva pré-visualização e atualize o valor de referência para anotações futuras.
Mantenha o identificador de registo para atualizações e limpeza. update() aceita qualquer
combinação de targets, controls, controlsHeading e controlsMode.
Os campos omitidos mantêm os valores anteriores. Por exemplo, utilize
registration.update({ targets: newElement }) ao substituir o elemento DOM de um
componente. As coleções de alvos capturam elementos existentes e não acompanham futuras
correspondências dos seletores.
Passe targets: [] para desassociar o registo ou controls: [] para limpar os seus
controlos. Chame dispose() e remova os ouvintes de eventos ao remover a
integração. A limpeza também tem de restaurar a apresentação normal: dispose() apenas
remove o registo dos controlos e não anula as alterações da pré-visualização. O exemplo de espaçamento
remove a sua substituição inline para restaurar o valor CSS original. Ambos os métodos
terminam de forma síncrona sem devolver um valor. As atualizações afetam
seleções futuras; as anotações guardadas mantêm os controlos e o alvo capturados.
Os eventos dos controlos têm como alvo o elemento capturado pela anotação. Atualizar os alvos de um registo não redireciona as anotações existentes. Os eventos de reposição podem continuar a ser emitidos num elemento removido, pelo que um ouvinte no seu antigo elemento ascendente não os receberá.
Tornar objetos de canvas selecionáveis
Uma superfície de anotação permite que a sua aplicação identifique objetos individuais desenhados
dentro de um canvas. Registe o elemento anfitrião com registerSurface() e forneça
uma função hitTest que devolva um objeto com um id estável ou null para
espaço vazio.
O anfitrião tem de ser um elemento HTML ligado ao DOM, fora de shadow DOM, num documento seguro de nível superior. O registo de superfícies não é suportado dentro de um iframe.
Este exemplo desenha uma barra de receitas e torna-a selecionável. Coloque o script depois do canvas:
<canvas id="revenue-canvas" width="480" height="240">
Revenue this quarter: $120,000.
</canvas>const canvas = document.getElementById("revenue-canvas");
const context = canvas.getContext("2d");
const bar = { x: 40, y: 60, width: 320, height: 100 };
function drawRevenue(highlighted = false) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "#2563eb";
context.fillRect(bar.x, bar.y, bar.width, bar.height);
if (highlighted) {
context.strokeStyle = "#111827";
context.lineWidth = 3;
context.strokeRect(bar.x, bar.y, bar.width, bar.height);
}
}
drawRevenue();
const surface = document.oai?.annotation?.registerSurface?.({
element: canvas,
hitTest({ clientX, clientY }) {
const bounds = canvas.getBoundingClientRect();
const scaleX = bounds.width / canvas.width;
const scaleY = bounds.height / canvas.height;
const rect = {
x: bounds.left + bar.x * scaleX,
y: bounds.top + bar.y * scaleY,
width: bar.width * scaleX,
height: bar.height * scaleY,
};
if (
clientX < rect.x ||
clientX > rect.x + rect.width ||
clientY < rect.y ||
clientY > rect.y + rect.height
) {
return null;
}
return {
id: "revenue-this-quarter",
name: "Revenue this quarter",
role: "chart-bar",
metadata: { Metric: "Revenue", Value: 120000 },
rect,
};
},
renderSelection({ hoveredId, selectedId }) {
drawRevenue(
hoveredId === "revenue-this-quarter" ||
selectedId === "revenue-this-quarter"
);
},
});Passar o ponteiro sobre a barra no modo de anotação realça-a. Selecioná-la abre uma anotação com o nome do objeto, os metadados e uma captura de ecrã da seleção.
Mantenha os IDs estáveis dentro de uma superfície. O name opcional é visível para o utilizador;
role fornece uma breve descrição semântica. O rect opcional utiliza píxeis CSS
relativos à área visível da página, correspondendo a clientX e clientY. Converta a partir das coordenadas da cena,
incluindo escala, deslocamento e zoom.
hitTest pode devolver uma promessa e recebe um AbortSignal como signal para
cancelar trabalho substituído. O navegador permite 250 milissegundos antes de
recorrer à seleção do DOM. Os erros e os resultados inválidos também levam a esse recurso. Devolva
null explicitamente para um teste de deteção bem-sucedido sem qualquer objeto.
O trabalho cancelado tem, ainda assim, de resolver ou rejeitar a sua promessa. O navegador permite
apenas uma função de retorno hitTest em curso e mantém essa posição ocupada até a promessa
ficar resolvida ou rejeitada, mesmo após um cancelamento ou tempo limite. Se um worker tratar da seleção,
resolva ou rejeite a promessa pendente quando o seu trabalho for interrompido; descartar a resposta de um worker
cancelado pode bloquear seleções subsequentes no canvas.
Utilize a função de retorno opcional renderSelection para fornecer indicações específicas da aplicação.
Limpe as indicações quando ambos os IDs forem null. Chame surface?.invalidate() depois de
mover objetos ou alterar o zoom e surface?.dispose() ao remover a
integração. Ambos terminam de forma síncrona sem devolver um valor.
Adicionar controlos a objetos de canvas
Registe controlos personalizados no elemento DOM da superfície. Os objetos desenhados, designados objetos virtuais na API, utilizam os seus controlos personalizados; os controlos integrados de CSS e texto não se lhes aplicam.
Para vários objetos, utilize renderSelection para atualizar os controlos do anfitrião quando
selectedId mudar, antes de o navegador capturar a anotação. Os eventos dos controlos
incluem detail.virtualTarget: { surfaceId, targetId }. Encaminhe cada evento
utilizando essa identidade capturada e o respetivo callback, em vez da seleção
atual. targetId corresponde ao id de hitTest; surfaceId identifica o
registo da superfície no navegador. Os eventos normais do DOM omitem virtualTarget.
Os eventos de pré-visualização, comparação e reposição mantêm a identidade do objeto original após a seleção de outro objeto. Reabrir uma anotação guardada não volta a executar o teste de deteção para substituir o objeto ou os metadados capturados.
Controlar o modo de anotação
Utilize toggle() para pedir uma alteração de modo, isActive() para ler o estado confirmado
e o evento oaiannotationmodechange do documento para manter a sua interface sincronizada.
Detete a disponibilidade de ambos os métodos para navegadores mais antigos ou não compatíveis. Adicione este botão
e execute o script depois de o botão existir:
<button id="toggle-annotations" type="button" hidden>
Enter annotation mode
</button>const button = document.getElementById("toggle-annotations");
const annotation = document.oai?.annotation;
function renderMode(active) {
button.textContent = active
? "Exit annotation mode"
: "Enter annotation mode";
}
const onModeChange = (event) => renderMode(event.detail.active);
const onClick = () => annotation.toggle(!annotation.isActive());
if (
typeof annotation?.toggle === "function" &&
typeof annotation?.isActive === "function"
) {
document.addEventListener("oaiannotationmodechange", onModeChange);
button.addEventListener("click", onClick);
renderMode(annotation.isActive());
button.hidden = false;
}
function cleanupAnnotationButton() {
document.removeEventListener("oaiannotationmodechange", onModeChange);
button.removeEventListener("click", onClick);
button.hidden = true;
}toggle() inverte o modo. Passe true para garantir que está ativado ou false para garantir
que está desativado. Pedidos repetidos com o mesmo booleano são idempotentes. Passar
true preserva um editor ativo ou uma ativação pendente; false cancela
a ativação pendente e utiliza o fluxo normal de saída.
Chame toggle() a partir de uma interação ativa do utilizador. O seu resultado síncrono { accepted }
confirma a receção do pedido, não uma alteração de modo confirmada. As verificações de elegibilidade do
navegador ainda podem impedir a alteração. Leia o estado a partir de isActive()
e do evento, como no exemplo.
isActive() não necessita de um gesto do utilizador. O navegador atualiza-o antes de emitir
oaiannotationmodechange, cujo event.detail.active é um booleano. O navegador
não envia um evento inicial nem um duplicado para uma operação forçada sem efeito, pelo que deve inicializar a sua interface
a partir do método de leitura. Se o acesso for revogado enquanto estiver ativo, um evento final comunica
active: false e um método de leitura mantido devolve false.
O modo de anotação captura os cliques na página. Mantenha Espaço premido para utilizar os controlos da página,
incluindo o botão de saída, ou saia através da interface de anotações do navegador.
Manter apenas Espaço premido deixa isActive() como verdadeiro. A API não suporta um
oai-annotation-ignore nem outro atributo que permita a passagem dos cliques.
Sair fecha o editor e preserva as anotações guardadas sem as enviar
nem as mover para o compositor. Chame cleanupAnnotationButton() ao
remover o componente. A referência capturada da API permite que a limpeza remova
ouvintes mesmo que o espaço de nomes tenha desaparecido.
Testar a sua integração
Abra o seu site no navegador integrado da aplicação de ambiente de trabalho e teste as funcionalidades que adicionou:
- Entre no modo de anotação e selecione objetos e texto. Verifique se os realces, nomes, intervalos e metadados correspondem aos alvos pretendidos.
- Abra uma anotação a partir do botão do seu site. Verifique o elemento selecionado ou intervalo de texto, o comentário inicial e o modo do editor.
- Altere um controlo personalizado, compare com o original e limpe a pré-visualização. Verifique se a sua aplicação restaura o estado original.
- Para conteúdo de canvas, teste o espaço vazio, o redimensionamento e as alterações da cena. Alterne entre objetos e confirme que os eventos dos controlos continuam a atualizar o alvo capturado. Cancele um teste de deteção assíncrono e confirme que as seleções posteriores continuam a funcionar.
- Guarde, reabra e edite uma anotação a partir da pré-visualização de anexos do compositor. Verifique se mantém os seus controlos e o alvo e se a sua remoção limpa qualquer pré-visualização.
- Envie uma anotação com uma mensagem. Confirme que o ChatGPT recebe o
conteúdo selecionado, os metadados e os valores pedidos, incluindo os rótulos visíveis das opções
de seleção e as escolhas inalteradas nos controlos que omitem
currentValue. - Abra o site num navegador sem a API e verifique se as interações normais continuam a funcionar.
Para disponibilizar ações que o ChatGPT possa executar no seu site, adicione Ferramentas do site (WebMCP). As anotações trazem a seleção da pessoa e os seus comentários para a conversa; as ferramentas do site permitem que o agente atue sobre esse contexto através das capacidades existentes da sua aplicação.