segunda-feira, 26 de maio de 2008

Domino App com DojoX

Em continuação sobre a utilização do Dojo junto com aplicações Lotus Domino, nesse post vou falar um pouco sobre DojoX. Quando estamos trabalhando com a biblioteca Dojo, ela pode ser divida em três partes:

  • Dojo Base: É a parte mais básica do Dojo, que trabalhar com dados, drag-and-drop, etc.
  • Dijit: É a parte que trabalha com interfaces, campos, etc. O Dijit foi utilizando no meu post anterior
  • DojoX: É a parte que trabalha com gráficos, como imagens, gráficos, layout, etc.

O objetivo deste post é explorar um pouco mais sobre o DojoX, ou seja, uma parte mais visual do Dojo. Aqui vou estar fazendo uma visualização de fotos utilizando o componente SlideShow do DojoX. Abaixo você poderá ver a criação desta aplicação.

A aplicação

A aplicação é muito simples, existem dois formulários, um para fazer a criação dos documentos de imagens e outro para a apresentação das imagens no formato SlideShow. Também foram criadas duas visualizações e um agente para trazer os dados das fotos.

O primeiro formulário que criei serve para fazer o upload das fotos, neste formulário eu colocquei os seguintes campos:

Campo Tipo   Fórmula
Nome Text Editável  
Descricao Text Editável  
Foto RichText Editável  
NomeFoto Text Computado @AttachmentNames

figura01[5]

Figura 01 - Formulário para upload das fotos

JSON

O componente que iremos utilizar para mostrar as fotos, recebe os dados através de JSON (JavaScript Object Notation), que é um formato leve para intercâmbio de dados. O Lotus Domino gera as visões (views) no formato JSON, bastando chamar a visão da seguinte forma:

http://<servidor>/<database.nsf>/<visão>?ReadViewEntries&outputformat=JSON

Apesar do Lotus Domino já ter essa facilidade, o código é gerado genericamente para atender qualquer aplicação e para trabalhar com as informações seria necessário criar um código JavaScript para separar todos os campos.

Quando comecei a mexer com o DojoX, vi que muitos dos dados vindos de JSON para os componentes eram bastantes simples e ao invés de escrever um código JavaScript para separar os elementos, resolvi construir um agente mais simples para montar os dados em JSON.

A estrutura utilizada pelo componente SlideShow para pegar as fotos é a seguinte:

{ items: [ {

"thumb":"http://<endereço>/<foto>",

"large":"http://<endereço>/<foto>",

"title":"<Descrição>",

"link":""http://<endereço>/<documento ou página da foto>"

} ]}

Para facilitar a criação desta estrutura eu montei uma visão bem simples com todos os campos necessários e depois criei um agente que lê esta visão e monta a saída no formato correto. Essa visão é composta pelas seguintes colunas:
Título Fórmula
Nome Nome
title Descricao
thumb "/bases/dojo.nsf/ViewSlideShow/" + @Text(@DocumentUniqueID) + "/$File/" + NomeFoto + "?OpenElement"
large "/bases/dojo.nsf/ViewSlideShow/" + @Text(@DocumentUniqueID) + "/$File/" + NomeFoto + "?OpenElement"
link "/bases/dojo.nsf/ViewSlideShow/" + @Text(@DocumentUniqueID) + "?OpenDocument"

 

figura02

Figura 02 - View com os dados das fotos

A apresentação

O objetivo da apresentação é criar uma forma de escolher o nome (categoria) e mostrar todas as fotos no formato SlideShow. Para isso eu criei um formulário para a apresentação. Abaixo você pode ver o formulário pronto:

figura03

Figura 03 - Formulário de apresentação do SlideShow.

No formulário eu coloquei dois campos:

Campo Tipo   Fórmula
nome_selecao Combobox Editável @Subset(@DbColumn( "Notes" : "ReCache" ; @DbName ; "ViewSlide" ; 1 );1)
fotoID Text Computado @DbLookup( "Notes" : "ReCache" ; @DbName ; "ViewSlide" ; nome_selecao ; 1; [ReturnDocumentUniqueID])

O primeiro campo (nome_selecao) lê uma visão bem simples que criei. O nome desta visões é ViewSlide e abaixo você pode ver as definições das colunas:

Título Fórmula
Nome Nome
Descrição Descricao

A coluna Nome está categoriazada. Abaixo você pode ver a visão:

figura04

Figura 04 - Visão ViewSlide.

O segundo campo eu utilizo para pegar o ID do primeiro documento selecionado no campo nome_selecao. Quando eu chamar o agente para montar a estrutura JSON, eu passo esse ID como parâmetro, assim ele irá pegar todos os documento com o nome "SLIDESHOW", por exemplo.

Continuando no formulário, eu coloquei a chamada para os componentes do Dojo no campo HTML Head Content:

"<style type='text/css'>" +
"@import '/js/dijit/themes/tundra/tundra.css';" +
"@import '/js/dijit/themes/soria/soria.css';" +
"@import '/js/dijit/themes/nihilo/nihilo.css';" +
"@import '/js/dojox/image/resources/image.css';" +
"@import '/js/dojo/resources/dojo.css'" +
"</style>" +
"<script type='text/javascript' src='/js/dojo/dojo.js' djConfig='parseOnLoad: true'></script>"+

"<script type='text/javascript'>"+
"dojo.require('dojo.parser');"+
"dojo.require('dojo.data.ItemFileReadStore');"+
"dojo.require('dojox.image.SlideShow');"+

"</script>"

As linhas que deixei em negrito são as referências para o SlideShow e para o componente que lê os dados do JSON.

Na apresentação o código para criar o SlideShow é o seguinte:

<div jsId="imageItemStore" dojoType="dojo.data.ItemFileReadStore"
  url="/bases/dojo.nsf/slide-show-dojo?openagent&key=<Computed Value>"></div>

<div id="slideshow1" dojoType="dojox.image.SlideShow" imageWidth="600" imageHeight="600">
  <script type="dojo/connect">
    //This function runs when the widget has finished constructing
    //It sets the data store to use
    this.setDataStore(
      //The data store
      imageItemStore,
      //The request object
      { query: {}, count:200 },
      //The names of the attributes to get
      {
        imageThumbAttr: "thumb",
        imageLargeAttr: "large",
      }
    );
  </script>
</div>

A linha que deixei em negrito é referente a chamada do agente que irá montar o código JSON. No campo Computed Value, ele passa o ID do documento da foto. O resto do código eu peguei em um exemplo, e como vocês podem ver é bastante simples o entendimento.

A última parte deste exemplo é a construção do agente slide-show-dojo. Esse agente é responsável por montar a estrutura JSON para a apresentação das fotos. Abaixo segue o código:

Sub Initialize
    Dim session As New NotesSession
    Dim db As NotesDatabase
    Dim view As NotesView
    Dim vc As NotesViewEntryCollection
    Dim entry As NotesViewEntry
    Dim doc As NotesDocument   
    Dim doc_selecao As NotesDocument
    Dim saida As String
    Dim pkey As String
    Dim QueryString As String

    //Pega a base e documento corrente criado na chamada
    Set db = session.CurrentDatabase
    Set doc = session.DocumentContext

    //Pega o parâmetro passado na URL (QueryString). Esse parâmetro é o ID do primeiro documento de fotos
    QueryString =doc.Query_String(0)
    pkey =  ExtractParameter (QueryString, "key" )

    //Abre o documento de foto
    Set doc_selecao = db.GetDocumentByUNID(pkey)

    //Pega todos os documentos com o mesmo nome (categoria)
    Set view = db.GetView("ViewSlideShow")
    Set vc = view.GetAllEntriesByKey(doc_selecao.Nome(0))

    //Inicia um loop para a criação da saída JSON. Um ponto importante é a criação da saída. Quando você manda uma saída pelo HTTP do documento utilizando o comando print, o Domino monta uma página HTML por padrão, só que utilizarmos uma página HTML, a função ItemFileReadStore do Dojo não consegue entender os dados passados. Para evitar isso você precisa mandar um primeiro print falando que a saída é um documento do tipo texto e não HTML. Abaixo você pode ver esse print.
    Print |Content-type: text/plain|   
    saida = "{ items: ["
    For i = 1 To vc.Count
        saida = saida + "{"
        Set entry = vc.GetNthEntry(i)
        saida = saida + "'thumb':" + "'" + entry.ColumnValues(2) + "',"
        saida = saida + "'large':" + "'" + entry.ColumnValues(3) + "',"
        saida = saida + "'title':" + "'" + entry.ColumnValues(1) + "',"
        saida = saida + "'link':" + "'" + entry.ColumnValues(4) + "'"
        If i = vc.Count Then
            saida = saida + "}"
        Else
            saida = saida + "},"
        End If
    Next
    saida = saida + "]}"

    //Manda a saída para o HTTP do Domino
    Print saida
End Sub

Essa função eu peguei no site OpenNTF e seu objetivo é separar os valores dentro da QueryString.

Function ExtractParameter ( QueryString As String, ParamName As String ) As String
    Dim ParameterName As String
    ParameterName = ParamName & "="
    Dim startPosition, endPosition, queryStringLength, parameterLength As Integer
    Dim parameterValue As String
    queryStringLength = Len ( QueryString )
    parameterLength = Len ( ParameterName )
    startPosition = Instr ( 1, QueryString, ParameterName, 5 )
    If startPosition = 0 Then ' can be used to flag that no match param was sent
        parameterValue = ""
    Else
        startPosition = startPosition + parameterLength
        endPosition= Instr ( startPosition, QueryString, "&" )
        If ( endPosition = 0 ) Then
            endPosition = queryStringLength + 1
            parameterLength = endPosition - startPosition
            parameterValue = Mid ( QueryString, startPosition,parameterLength )
        Elseif ( endPosition <> 0 ) Then
            parameterLength = endPosition - startPosition
            parameterValue = Mid ( QueryString, startPosition,parameterLength )
        End If
    End If
    ExtractParameter = Replace(parameterValue,"_"," ")
End Function

Resultado

O resultado final desta aplicação é o seguinte:

DojoX

Figura 05 - Resultado final da aplicação de Slide Show.

O que foi criando aqui não está baseado nas melhores práticas de programação, isto é um simples exemplo de como utilizar o DojoX dentro de uma aplicação Lotus Notes/Domino. Esse código pode ser melhorado com outras técnicas mais apuradas de desenvolvimento.

As referências que utilizei para fazer esse exemplo são:

DojoCampus.org - Deste site que tirei o exemplo acima, é uma ótima referência para começar a trabalhar com Dojo.

Dojotoolkit - Site com o código do Dojo e Documentação.

2 comentários:

Unknown disse...

Olá Edson!

Parabéns pela materia, ficou muito bom e bem explicado. Consegui simular e com esse conceito consegui fazer outras coisas no Domino que não conseguia sem a versão R8 que roda JSON. Esse seu agente, muito simples e bem feito irá resolver muitas coisas que estava querendo utilizar com o JSON.

Mas tenho uma duvida, esse solução funcionou muito bem com o Mozilla FireFox, mas não está funcionando com o Intenet Explorer 7. Sabe me explicar o que pode ser?

Abraços e mais uma vez parabéns.

Edson Oliveira disse...

Oi Ailton,

eu tb tive problemas com o IE, mas não fui ver o que era, pois uso o Firefox como padrão. Acho que vale a pena dar uma olhada no site do Dojo.

Até +,