Uma chamada para a função looker.plugins.visualizations.add é o ponto de entrada na API Visualization. Essa função aceita um objeto de visualização que define totalmente a visualização personalizada.
Confira um exemplo de visualização:
looker.plugins.visualizations.add({
create: function(element, config){
element.innerHTML = "<h1>Ready to render!</h1>";
},
updateAsync: function(data, element, config, queryResponse, details, doneRendering){
var html = "";
for(var row of data) {
var cell = row[queryResponse.fields.dimensions[0].name];
html += LookerCharts.Utils.htmlForCell(cell);
}
element.innerHTML = html;
doneRendering()
}
});
Ambiente
Como a API Visualization é JavaScript simples, você pode usar qualquer biblioteca JavaScript para visualizar seus dados.
O código JavaScript será executado em um iframe em sandbox, separado da instância do Looker. Mesmo assim, os autores de visualizações personalizadas são responsáveis por garantir que o código escrito seja seguro.
Assim como todo desenvolvimento da Web, o suporte a diferentes navegadores da Web (Chrome, Edge, Firefox) pode ser um problema ocasionalmente. A API Visualization funciona em todos os navegadores compatíveis com o Looker, mas é sua responsabilidade garantir o suporte do navegador para o código personalizado. Por exemplo, usos do ES6, como let ou ()=>, funcionarão na maioria dos navegadores, mas poderão causar falhas no IE11 ou ao renderizar PDFs usando o PhantomJS.
Instalação
Você instala visualizações personalizadas definindo um manifesto com o formulário Admin > Platform > Visualizations. Um manifesto consiste em um ID de string exclusivo, um rótulo legível por humanos, o URI da visualização e links para todas as dependências necessárias (por exemplo, d3, jQuery, underscore).
As visualizações personalizadas precisam ser veiculadas como conteúdo HTTPS externamente ao Looker. Se você estiver migrando da primeira versão da API de visualização personalizada, talvez tenha arquivos no diretório looker/plugins/visualizations. Esse local ainda está acessível, e um caminho relativo para a visualização pode ser fornecido, mas recomendamos que você migre o conteúdo para um local diferente. Como o diretório /plugins não está no sistema de arquivos compartilhados, os ambientes clusterizados não terão acesso aos arquivos de visualização em todos os nós.
O objeto de visualização
O objeto de visualização usa as seguintes propriedades obrigatórias, opcionais e adicionadas.
Propriedades obrigatórias
createfunçãoEssa função é chamada uma vez, quando a visualização é desenhada pela primeira vez na página. Espera-se que ela configure tudo o que você quer que a visualização sempre tenha disponível. Você pode carregar uma biblioteca ou criar um conjunto de elementos e controles que serão usados mais tarde.
updateAsync/updatefunçãoEssa função é chamada sempre que o estado da visualização precisa mudar. Ela sempre será chamada após
createe poderá ser chamada muitas vezes. Portanto, ela precisa ser o mais rápida possível.Essa função pode ser chamada por muitos motivos, mas geralmente é quando a consulta a ser visualizada foi alterada, uma opção de configuração foi alterada ou a visualização foi redimensionada.
Essa função tem uma versão síncrona e assíncrona :emdash; você só precisa especificar uma. É um erro definir as duas. O método assíncrono é mais confiável para renderização de PDF devido à natureza dos iframes.
Propriedades opcionais
optionsobjetoUm objeto que detalha as opções que os usuários podem definir na visualização.
destroyfunção Ainda não implementada na API V2Uma função que é chamada pouco antes de a visualização ser removida da página. Use essa função para limpar listeners de eventos ou outros estados. Ela nunca poderá ser chamada se, por exemplo, o usuário fechar a janela.
Propriedades do anúncio adicionadas
O Looker adiciona as seguintes propriedades ao objeto automaticamente depois que a visualização é transmitida para looker.plugins.visualizations.add. É possível fazer referência a elas usando this no contexto das funções create, update, updateAsync e destroy.
addErrorfunçãoUma função que o código de visualização pode chamar para informar à UI que mostre uma mensagem de erro em vez da visualização. Ela usa um objeto
error.Depois que um erro é adicionado, ele permanece visível até que
clearErrorsseja chamado.Exemplo:
this.addError({ title: "Two Dimensions Required", message: "This really great visualization requires two dimensions." });clearErrorsfunçãoUma função que o código de visualização pode chamar para limpar todos os erros adicionados usando
addError.Exemplo:
this.clearErrors();triggerfunçãoUma função que pode ser chamada para acionar um evento fora da visualização.
Confira detalhes sobre eventos →
Exemplo:
this.trigger("limit", [20]);
A função create
A função create vai receber dois parâmetros, element e config.
create: function(element, config){
// Your update code here.
},
Parâmetros
elementDOMElementUm elemento DOM que representa um contêiner para renderizar a visualização.
configobjetoUm objeto que representa os valores de todas as opções de configuração options definidas pelo usuário para esse gráfico.
Exemplo:
{my_configuration_option: "User Value"}
As funções updateAsync e update
O método preferencial de atualização da visualização é o updateAsync. Esse método permite que a visualização execute uma ação assíncrona, como carregar um arquivo ou enviar uma solicitação da Web.
Essa versão da função tem um parâmetro adicional, que é um callback a ser chamado quando a renderização for concluída:
updateAsync: function(data, element, config, queryResponse, details, done){
// An example of an asynchronous update, fetching a file.
d3.request("https://example.com/fun-file.docx").response(function(xhr) {
// Your update code here that uses this file.
done();
});
}
Alertar o Looker quando a visualização terminar a renderização permite que o Looker otimize a renderização de PDF e garante que as imagens das visualizações sejam capturadas corretamente.
Algumas visualizações mais antigas usam a função update. Essa função ainda funciona, mas não é o método preferencial, já que o uso dela significa que o Looker não será alertado quando uma visualização for totalmente renderizada. A função update vai receber cinco parâmetros:
update: function(data, element, config, queryResponse, details){
// Your update code here.
}
Parâmetros
dataarrayUma matriz de linhas que representam os dados atuais na consulta. Pode ser
null.Cada linha é um objeto com as chaves que representam nomes de campos e o valor que representa um objeto "célula". Confira detalhes sobre como lidar com o objeto de célula.
elementDOMElementUm elemento DOM que representa um contêiner para renderizar a visualização.
configobjetoUm objeto que representa os valores de todas as opções de configuração options definidas pelo usuário para esse gráfico.
Exemplo:
{my_configuration_option: "User Value"}queryResponseobjetoUm objeto que representa metadados sobre a consulta atual, como metadados sobre campos. Pode ser
null.detailsobjetoDetalhes sobre o contexto de renderização atual. Contém informações sobre por que o gráfico está sendo renderizado e o que mudou. Normalmente, essas informações são usadas apenas em casos avançados.
Referente aos filtros cruzados nos painéis do Looker que usam a nova experiência de painel, os atributos permitidos incluem
crossfilterEnabledecrossfilters.O atributo
printpode ser usado em conjunto com a funçãodonepara melhorar a renderização de PDF para visualizações personalizadas, especialmente aquelas que incluem animação. Por exemplo:if (details.print) { done(); }donefunçãoUm callback para indicar que a visualização está totalmente renderizada. Essa função é especialmente importante para chamar se a visualização precisar executar chamadas assíncronas ou precisar ser renderizada como um PDF.
Renderização de dados
O Looker tem um conjunto avançado de ferramentas de formatação de dados no LookML que podem ser usadas para personalizar a aparência e o comportamento dos pontos de dados. Essas ferramentas incluem configurações do LookML no nível do campo, como formatos de valores personalizados, HTML, links de detalhamento e ações de dados.
As células têm uma propriedade value, que é a única propriedade que existe em todos os casos. Essa propriedade é um tipo JavaScript que corresponde ao tipo de campo a que a célula pertence. No entanto, não é seguro inserir uma propriedade value diretamente em HTML ou SVG, já que nenhum escape HTML foi realizado, e alguns valores de campo são objetos JavaScript ou matrizes complexos que serão renderizados de maneiras indesejáveis ou confusas.
Para garantir que todas as visualizações renderizem esses itens de forma consistente e segura, há várias funções utilitárias para transformar os metadados da célula transmitidos ao gráfico em data em representações diferentes para fins diferentes. Os metadados da célula podem compactar ou omitir determinados campos em alguns casos, e essas funções auxiliares permitem oferecer uma experiência consistente.
Essas funções auxiliares estão disponíveis no objeto global LookerCharts.Utils.
LookerCharts.Utils.textForCell(cell)Essa função aceita uma célula e retorna uma representação de string dela adequada para exibição. Ela sempre será uma string. Essa função nunca retorna
nullou qualquer outro tipo.LookerCharts.Utils.htmlForCell(cell)Essa função aceita uma célula e retorna uma string que contém HTML. Ela sempre será uma string. Essa função nunca retorna
nullou qualquer outro tipo.A saída dessa função é escapada corretamente e adequada para inserção direta no HTML do elemento. O HTML de saída também vai mostrar corretamente o menu de detalhamento ao clicar quando for apropriado para os dados.
LookerCharts.Utils.filterableValueForCell(cell)Essa função aceita uma célula e retorna uma string de sintaxe de filtro avançado do Looker que corresponderia ao valor dessa célula.
LookerCharts.Utils.toggleCrossfilter({row, pivot, event})Essa função aceita uma linha, uma tabela dinâmica ou um evento e é usada para verificar se a filtragem cruzada está ativada para uma visualização. O exemplo a seguir mostra como adicionar um listener de eventos a um elemento que verifica se a filtragem cruzada está ativada quando o evento ocorre:
d3.select("#myElement") .on("click", function (d) { if (details.crossfilterEnabled) { LookerCharts.Utils.toggleCrossfilter({ row: d.row, event: d3.event, }); } else { // ... handle click when cross-filtering is not enabled } });LookerCharts.Utils.getCrossfilterSelection(row, pivot?)Essa função aceita uma linha ou tabela dinâmica e é usada para verificar se essa linha ou tabela dinâmica está selecionada em uma visualização personalizada. A função retorna um tipo enumerado para
CrossfilterSelection {NONE, SELECTED, UNSELECTED}de 0 seNONE, 1 seSELECTEDe 2 seUNSELECTED.O exemplo a seguir aplica condicionalmente uma cor de preenchimento a uma linha se ela estiver sendo filtrada cruzada e aplica cores padrão se a filtragem cruzada não estiver ativada para essa linha:
d3.select("#myElement") .attr("fill", function (d) { const crossfilter = LookerCharts.Utils.getCrossfilterSelection(d.row) if (details.crossfilterEnabled && crossfilter === 1) { return d.color } else { return "#DEE1E5" //Hex used for unselected elements in native visualizations ...LookerCharts.Utils.openDrillMenu(options)A saída de
htmlForCellvai mostrar automaticamente o menu de detalhamento, se necessário, mas isso pode não ser apropriado para determinados tipos de renderização. Por exemplo, o SVG não pode renderizar HTML, mas talvez você queira capturar um evento de clique para iniciar um detalhamento.O objeto
optionstem os seguintes parâmetros:linksObrigatório arrayUma matriz dos objetos retornados da propriedade
linksde uma célula. Se você quiser mostrar links para várias células de uma só vez, primeiro concatene essas matrizes. Para links personalizados, forneça uma matriz de objetos com o seguinte formato:{ label: string, type: 'drill', type_label: string, url: url }eventEvento HTML DOMO evento de clique (ou outro) que causou o evento de detalhamento. O Looker vai usar isso para determinar onde colocar o menu de detalhamento. Se você não tiver um, tente transmitir um objeto com as coordenadas pageX e pageY.
Exemplo:
for (var row of data) { var cell = row[queryResponse.fields.dimensions[0].name]; var cellElement = myBuildElementFunction(cell); cellElement.onclick = function(event) { LookerCharts.Utils.openDrillMenu({ links: cell.links, event: event }); }; // ... more visualization stuff... }
Apresentação da UI de configuração
O parâmetro options é um objeto em que as chaves são um identificador arbitrário para um nome de opção, e o valor é um objeto que descreve informações sobre a opção.
Exemplo:
options: {
color_range: {
type: "array",
label: "Color Range",
display: "colors"
},
top_label: {
type: "string",
label: "Label (for top)",
placeholder: "My Great Chart"
},
transport_mode: {
type: "string",
label: "Mode of Transport",
display: "select",
values: [
{"Airplane": "airplane"},
{"Car": "car"},
{"Unicycle": "unicycle"}
],
default: "unicycle"
}
}
Parâmetros do objeto de opção
O objeto option tem os seguintes parâmetros básicos, propriedades específicas de exibição e opções de organização.
Parâmetros básicos
typestringO tipo de dados da opção.
Valores permitidos:
string(padrão),number,boolean,arraylabelstringO rótulo legível por humanos da opção que será mostrado ao usuário.
defaultO valor padrão da opção. Quando não especificado, o valor da opção é
null. Esse precisa ser um valor do mesmo tipo quetype.displaystringDeterminados valores
typepodem ser apresentados na UI de maneiras diferentes.quando
typeéstring:Valores permitidos:
text(padrão),select,radioquando
typeénumber:Valores permitidos:
number(padrão),rangequando
typeéarray:Valores permitidos:
text(padrão),color,colors
placeholderstringPara valores
displaycompatíveis, um valor de exemplo ou explicação para dar ao usuário uma dica sobre o que digitar.
Propriedades específicas de exibição
valuesarray de objetosQuando
displayéradioouselect, uma matriz que contém rótulos e valores que serão listados na interface.Cada item na matriz precisa ser um objeto com um único par de chave-valor, que representa o rótulo e o valor da opção. O rótulo será apresentado apenas na UI. No tempo de renderização, você receberá apenas o valor.
Exemplo:
values: [ {"Center": "c"}, {"Left": "l"}, {"Right": "r"} ]Se
displayforradio, cada opção também poderá receber umadescription:values: [ {"Cool": "c"}, {"Uncool": { value: "unc", description: "Only choose this if the data is very uncool." } } ]maxnumberQuando
displayérange, o número máximo permitido para ser selecionado pelo controle deslizante de intervalo.minnumberQuando
displayérange, o número mínimo permitido para ser selecionado pelo controle deslizante de intervalo.stepnumberQuando
displayérange, o valor que cada marca do controle deslizante de intervalo representa.
Opções de organização
sectionstringPara gráficos com muitas opções, um rótulo para a seção em que uma opção deve aparecer. A interface vai agrupar as opções pelos valores
section. Se houver apenas uma seção, a UI da seção não será mostrada.Se você estiver usando
section, ela precisará ser definida em todas as opções.ordernumberUm número que representa a ordem das opções para apresentação na UI. Se especificado, as opções serão classificadas de acordo com essa ordem.
display_sizestringUma classe de tamanho que representa a largura da opção na UI. Por exemplo, se você quiser mostrar uma opção "Mínimo" e uma "Máximo" lado a lado, defina cada um dos tamanhos de exibição como
half.Valores permitidos:
normal(padrão),half,third
Eventos
Os eventos podem ser acionados pelo gráfico (geralmente em resposta à interação do usuário) que podem atualizar as propriedades da visualização ou consulta.
Eles podem ser acionados chamando a função trigger no objeto de visualização. O primeiro parâmetro é sempre o nome do evento e o segundo é uma matriz de argumentos.
this.trigger("limit", [20]);
Eventos disponíveis
updateConfigAtualize as configurações atuais do gráfico.
Argumento:um objeto que contém chaves de configuração a serem atualizadas. As chaves não especificadas não são alteradas.
Exemplo:
var vis = this; $(element).find(".axis").click(function(){ vis.trigger("updateConfig", [{axis_hidden: true}]); });limitAtualize o limite da consulta subjacente:
Argumento:um número inteiro que representa um novo limite para a consulta.
var vis = this; $(element).find(".show-all").click(function(){ vis.trigger("limit", [500]); });filterAtualize o valor de um filtro na consulta subjacente:
var vis = this; $(element).find(".show-all-tommys").click(function(){ vis.trigger("filter", [{ field: "users.name", // the name of the field to filter value: "%tommy%", // the "advanced syntax" for the filter run: true, // whether to re-run the query with the new filter }]); });loadingStartMarque a visualização como carregando. Na maioria das vezes, isso não é necessário, mas, se a visualização carregar um objeto de um local remoto ou realizar um cálculo longo, você poderá usar essa opção para continuar mostrando o indicador de carregamento.
Ele vai aparecer carregando até que
loadingEndseja acionado.loadingEndMarque a visualização como não carregando mais.
printSize(Looker 26.0 ou mais recente)Permite que as visualizações aproveitem a opção "Abrir tabelas para mostrar todas as linhas" ao renderizar painéis de dados em PDF. O uso desse evento permite que o aplicativo saiba a altura do conteúdo renderizado e possa expandir o bloco do painel de dados adequadamente para que todas as informações fiquem visíveis para impressão.
this.trigger('printSize', { heightExpanded: FULL_HEIGHT_IN_PIXELS });registerOptions(Looker 5.24 ou mais recente)Permite que as visualizações registrem outras opções depois que a visualização for registrada:
update: function(data, element, config, queryResponse, details){ options = {} // Create an option for each measure in your query queryResponse.fields.measure_like.forEach(function(field) { id = "color_" + field.name options[id] = { label: field.label_short + " Color", default: "#8B7DA8", section: "Style", type: "string", display: "color" } }) this.trigger('registerOptions', options) // register options with parent page to update visConfig ... } });