Proposta
Se você quer criar suas próprias formas dos controles XForm como input
, output
, trigger
, etc., você está no lugar certo. Vamos mostrar tambem como criar controles que funcionam com o modelo XForms e são automaticamente atualizados como os controles XForms. A proposta deste artigo é de fornecer informações suficientes para permitir-lhe um bom início. Para realmente entender as seguintes informações é necessário um bom entendimento de XForms, XBL, JavaScript e CSS. Conhecimentos em XPCOM certamente não farão mal. Mas mesmo que você tenha conhecimentos em sómente algumas destas tecnologias, esperamos que as possibilidades delineadas abaixo o inspirem a aprender mais onde fôr necessário.
Status de implementação
O sistema que usamos no processador Mozilla XForms é muito um "trabalho em andamento". Por favor mantenha em mente que tudo que mencionamos aqui pode mudar de algum maneira assim que continuamos a trabalhar no assunto. O trabalho já começou no W3C XForms Working Group a investigar o assunto de controles customizadas, assim eventualmente (esperamos?)que vai existir um caminho "oficial" e comum de customizar suas máscaras de interface de usuário em todos os processadores XForm.
Porque é necessário
Você provávelmente vai achar que suas necessidades de customização se encaixam numa das seguintes categorias:
- apresentação customizada - controles XForms como as realizadas no processador Mozilla XForms não lhe fornecem a aparência certa.
- tipos de dados customizadas - controles Xforms existentes não estão aptos a trabalhar apropriamente seus tipos de dados
- controles XForms avançados - você necessita que seus controles estejam aptos a fazer mais coisas que os controles XForms tradicionais
- nova linguagem de hospedagem- você quer suportar XForms em linguagems de hospedagem diferentes de XHTML ou XUL
Apresentação customizada
A extensão Mozilla XForms não pode antecipar todas as possibilidades de uso que vão ser envolvidas em aplicações e páginas web quando XForms amadurece e a base de usuários cresce. E com estas novas formas de usar mais e mais flexibilidade vai ser exigida dos controles. Introduzindo controles customizadas ao seu ambiente pode ser a solução que está procurando. Por exemplo, você pode estar querendo render imagens que estão sendo mantidos dentro de um documento de instancia ou querer mostrar um trigger
deshabilitado quando seu nó se torna irrelevante em vez de não mostrá-lo (o atual comportamento padrão).
Toda apresentação de controle XForms possui seu próprio XBL binding. Em muitos casos valores diferentes fornecidos para os atributos appearance
ou mediatype
vão determinar qual XBL binding será usado para um controle XForms particular. Como mencionado na especificação, o atributo appearance
pode ser usado para influenciar a aparência do controle mesmo que todas as outras condições permanecam constantes. Por exemplo, na extensão Mozilla XForms vamos render uma combobox widget ao appearance='minimal'
num controle select1
. Se o autor do formulário escolher um appearance='compact'
neste controle, vamos desenhar uma listbox widget. Aqui é uma forma fragmentada do nosso arquivo .css para mostrar o tipo de regra CSS que usariamos para tal determinação.
xf|select1[appearance="compact"] { -moz-binding: url('chrome://xforms/content/select-xhtml.xml#xformswidget-select1-compact'); }
O atributo mediatype
pode ser usado pelo autor do formulário para alinhar o tipo de apresentação com o tipo de data que o bound instance node contém. Por exemplo, se mediatype='image/*'
então o usuário deve ver a imagen que os bytes representam em vez da sequência de bytes.
xf|output[mediatype^="image"] { -moz-binding: url('chrome://xforms/content/xforms-xhtml.xml#xformswidget-output-mediatype-anyURI'); }
Tipos de dados customizados
Se definir um novo tipo de dado esquemático ou usar tipo de data built-in e achar os controles XForms atuais insuficientes, então deve escrever um novo controle customizado. Por exemplo se tiver um nó de instância do tipo xsd:date
e quiser que os dados sejam visualizados num formato local.
Em Mozilla, cada controle XForms ligado tem um atributo typelist
de mozType
que contém o espaço de nome da cadeia herdada dos tipo de dados que detectamos. O espaço de nome mozType
é introduzido pela implementação de Mozilla XForms e suas URI é https://www.mozilla.org/projects/xforms/2005/type
. Por exemplo, se um controle é ligado a um nó do tipo xsd:integer
e então o atributo typelist
será "https://www.w3.org/2001/XMLSchema#integer https://www.w3.org/2001/XMLSchema#decimal"
. Isto é porque xsd:integer
é herdado do tipo de dado xsd:decimal
. Recomendamos que use este atributo para criar a regra de ligação CSS para seu controle customizado. Isto lhe permite ligar seu controle customizado para o tipo de dado que está desejando e todo tipo derivado deste tipo desejado. Então se quiser um input
ligado a um nó de instância do tipo integer
(e todos os tipos derivados de integer
), você usaria:
@namespace xf url(https://www.w3.org/2002/xforms); @namespace mozType url(https://www.mozilla.org/projects/xforms/2005/type); xf|input[mozType|typelist~="https://www.w3.org/2001/XMLSchema#integer"] { -moz-binding: url('chrome://xforms/content/input-xhtml.xml#xformswidget-input-integer'); }
Controles XForms Avançados
Vão existir momentos em que precisa de um controle muito específico a sua tarefa mas também quer que funcione com modelos XForms e nós de instância como um controle XForms regular. A esspecificação XForms fornece uma bela maneira de realizar isto usando atributos ligados XForms (como ref
, ou nodeset
) no seu elemento de controle customizado. Porém, a implementação de Mozilla XForms atualmente não suporta esta aproximação. Mas existe um caminho para alcançr o mesmo resultado. Você pode pôr os controles dentro da sua ligação XBL. Note que deve assegurar que os controles XForms incorporados funcionam com o tipo de dados do nó de instância ao que seu controle está ligado. Para lhe dar uma ideía sobre o que estamos falando veja a seguir:
<content> <xf:input xbl:inherits="ref=ref1" anonid="ref1"/> <xf:input xbl:inherits="ref=ref2" anonid="ref2"/> </content> <implementation> <method name="refresh"> <body> // Aqui devemos renovar o controle customizado. </body> </method> <constructor> // Devemos redirecionar chamadas do modo de inputs 'refresh' para controles customizados 'refresh'. var control = this; var refreshStub = function() { control.refresh(); } this.ref1.refresh = refreshStub; this.ref2.refresh = refreshStub; </constructor> <property name="ref1" readonly="true" onget="return this.ownerDocument.getAnonymousElementByAttribute(this, 'anonid', 'ref1');"/> <property name="ref2" readonly="true" onget="return this.ownerDocument.getAnonymousElementByAttribute(this, 'anonid', 'ref2');"/> </implementation>
Nova linguagem Host
A implementação Mozilla XForms atualmente somente suporta XForms hospedados em documentos XHTML ou XUL. Se precisar XForms em outros tipos de documentos como SVG, MathML ou alguma outra marca de linguagem que Mozilla suporta, então precisa implementar controles XForms para o formato de documento desejado. A implementação XForms tem ligações básicas XBL para cada controle XForms. Vocè pode escrever ligações de implementação que vão herdar as ligações básicas. Por exemplo, cada implementação de controle output
extende a ligação básica xforms.xml#xformswidget-output-base
. As peças específicas XHTML de nossa implementação de output
é mantido na liagação xforms-xhtml.xml#xformswidget-output
. Se desenvolvedores como você quiserem fazer este tipo de trabalho heróico eão por favor contate os desenvolvedores do Mozilla XForms antes de iniciar. Esperamos poder ajudá-lo em evitar um monte de frustração e desespéro:).
Resumo
Os controles Mozilla XForms são largamente implementados usando XBL e as ligações são aplicados aos tags de controle individuais XForms via CSS. Assim sempre pode referir-scom nossas atuais e ao nosso source code para obter alguns grandes exemplos de como controles XForms são escritos. Isto também lhe permite estar por dentro das nossas atuais atualizações (muitas vezes o resultado de duras lições) e esperamos que o ajude a escrever seus próprios controles mais facilmente. Para iniciar, realmente só precisa saber a linguagem aonde quer usar XForms (como XHTML ou XUL), alguns XBL e JavaScript, e a interface XPCOM que estamos mostrando.
Detalhes
Interfaces
Esta secção descreve interfaces que deve conhecer. Existem dois grupos principais de interfaces -> callback interfaces que precisam ser implementados pelos controles customizados e as interfaces que controles customizados podem usar para acessar a Mozilla XForms engine.
nsIXFormsUIWidget
Todo controle customizado deve implementar a interface nsIXFormsUIWidget
. Esta interface é usada pelo modulo XForms para interagir com o controle básico. De acordo com as regras do XForms, por exemplo, quando o controle precisa ser atualizado, é chamado o método refresh
pelo processador. Abaixo encontra-se a estrutura da interface. Como sempre por favor veja diretamente o source code para estar seguro que está usando a versão mais recente: extensions/xforms/nsIXFormsUIWidget.idl
.
interface nsIXFormsUIWidget : nsIDOMElement { /** * É chamada quando o controle deve ser atualizado para refletir o valor do nó ligado. */ void refresh(); /** * É chamado quando o foco é avançado sobre o elemento XForms. */ boolean focus(); /** * É chamado quando o controle deve ser desabilitado. * Isto realmente só se aplica ao elemento submetido. */ void disable(in boolean disable); /** * É chamado para obter o valor atual do controle. */ string getCurrentValue(); }
Notas:
- getCurrentValue() deve retornar o valor do controle como visto pelo usuário. O valor atual de um controle pode ser diferente do valor do nó ligado em casos onde @incremental='false'.
- disable() é chamado pelo processador XForms para indicar a um elemento submetido que precisa desabilitar/habilitar devido ao começo/fim de um processo de submissão. Atualmente não tem nenhum sentido fora deste contexto.
- focus() é usado pelo processador para comunicar ao controle que ele está recebendo foco através de uma das várias maneiras (p.ex. através de xf:setfocus action) e que o controle precisa assegurar que o widget apropriado está recebendo foco.
Com raras exceções seu controle precisa somente implementar a interface nsIXFormsUIWidget
. Mas certos controles XForms precisam implementar interfaces adicionais. Tais elementos incluem upload
e case
.
nsIXFormsAccessors
A interface nsIXFormsAccessors
permite acessar o valor e o estado do nó de instância ao qual o controle está ligado (veja extensions/xforms/nsIXFormsAccessors.idl
). Interface atual é:
interface nsIXFormsAccessors : nsISupports { /** * Valor de retorno do nó de instância. */ DOMString getValue(); /** * Valor nominal do nó de instância. */ void setValue(in DOMString value); /** * Retorna verdadeiro se o nó de instância é readonly como determinado pelo MDG. */ boolean isReadonly(); /** * Retorna verdadeiro se o nó de instância é relevante como determinado pelo MDG. */ boolean isRelevant(); /** * Retorna verdadeiro se o nó de instância é requerido como determinado pelo MDG. */ boolean isRequired(); /** * Retorna verdadeiro se o nó de instância é válido como determinado pelo MDG. */ boolean isValid(); /** * Retorna verdadeiro se o controle é ligado ao nó de instância. */ boolean hasBoundNode(); /** * Retorna o nó de instância ligado. */ nsIDOMNode getBoundNode(); /** * Setar o conteúdo do nó de instância. Se um ForceUpdate é verdadeiro então o * modelo XForms será reconstruído/recalculado/revalidado/renovado. */ void setContent(in nsIDOMNode aNode, in boolean aForceUpdate); }
note: setContent() pode ser usado para colocar complexContent (mistura de texto e nós elementares) sob o nó ligado ao controle. Favor verificar os comentários no arquivo fonte .idl para maiores informações sobre como usar este método.
Ligações XBL
A maioria dos elementos de controle XForms tem no mínimo duas ligações aplicadas a si mesmas. Uma é a ligação básica que implementa o comportamento do núcleo do controle XForms. A outra é a ligação de impelmentação que adiciona a representação específica da linguagem do host do controle XForms. Um exemplo do mencionado é a ligação que usa um html:input como conteúdo anônimo de um elemento xforms:input quando este é hospedado num documento XHTML.
Nossa extenção XForms usa o seguinte formato para nomes de arquivos. O nome do arquivo onde são localizadas as ligações básicas de um controle é controlfile.xml
. controlfile-xhtml.xml
contém as ligações de implementação XHTML para o controle e controlfile-xul.xml
contém as ligações de implementação quando este controle é hospedado num documento XUL. A seguinte lista mostra onde estão definidas as ligações básicas de nosso controle XForms:
-
xforms.xml
- contém as ligações básicas para controles XFormsoutput
,label
,trigger
,submit
,case
,message
,hint
,help
,alert
,upload
erepeat
. -
input.xml
- contém as ligações básicas para controles XFormsinput
,secret
etextarea
. -
select.xml
- contém as ligações básicas para controles XFormsselect
eselect1
(excetominimal/default select1
que está hospedado no arquivoselect1.xml
) -
range.xml
- contém as ligações básicas para controles XFormsrange
.
xforms.xml
também define as poucas ligações básicas comuns para todos os controles XForms. Estes são:
-
xformswidget-general
- define propriedades utilitárias e métodos comuns para todos os controles XForms. -
xformswidget-accessors
- define os métodos que permitem às ligações de trabalhar com nós de instância ligados e com o próprio elemento XForms. -
xformswidget-base
- implementa interfacesnsIXFormsUIWidgets
.
Você está livre em escolher qual tipo de ligação para seu controle customizado fornecerá à fundação. Normalmente será uma das ligações de implementação ou uma das básicas.
Exemplo
Uma coleção de exemplos de controles customizados pode ser encontrada em XForms:Custom Controls Examples, e você também pode ver os blogs "Compreendendo XForms: Customização".
Aqui está um exemplo completo que define um novo controle de saída que carrega seu valor como uma imagen. Ele está ligado a <xf:output mediatype="image/*"/>
imitando o atual XForms 1.1 draft:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "https://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="https://www.w3.org/1999/xhtml" xmlns:xf="https://www.w3.org/2002/xforms"> <head> <title>Custom Image Control Sample</title> <bindings id="xformsBindings" xmlns="https://www.mozilla.org/xbl" xmlns:html="https://www.w3.org/1999/xhtml"> <binding id="output-image" extends="chrome://xforms/content/xforms.xml#xformswidget-base"> <content> <html:div> <html:img anonid="content"/> </html:div> </content> <implementation implements="nsIXFormsUIWidget"> <method name="refresh"> <body> <!-- set the src attribute on the html:img to be the simpleContent of the instance node bound to this control --> var img = document.getAnonymousElementByAttribute(this, "anonid", "content"); img.setAttribute("src", this.stringValue); return true; </body> </method> </implementation> </binding> </bindings> <xf:model> <xf:instance xmlns=""> <data> <curimg></curimg> <img label="Firefox">https://www.mozilla.com/images/firefox-logo-64x64.png</img> <img label="Thunderbird">https://www.mozilla.com/images/thunderbird-logo-64x64.png</img> <img label="Bugzilla">https://www.mozilla.org/images/p-bugz.gif</img> <img label="Mozilla">https://www.mozilla.org/images/mozhead-80x64.gif</img> </data> </xf:instance> </xf:model> <style type="text/css"> @namespace xf url(https://www.w3.org/2002/xforms); xf|output[mediatype="image/*"] { -moz-binding: url('#output-image'); } </style> </head> <body> <h1>Custom Control Sample</h1> <xf:select1 ref="curimg"> <xf:label>Select image to display: </xf:label> <xf:itemset nodeset="../img"> <xf:label ref="@label"/> <xf:value ref="."/> </xf:itemset> </xf:select1> <xf:output ref="curimg" mediatype="image/*"/> </body> </html>
Categorias
Interwiki links de idiomaspt-br:XForms:Controles Customizados