O "MakeNode" Extensão Widget

8 de julho de 2011 em 02:11 por Satyam | Em Desenvolvimento | 6 Comentários

Nota do Editor: Desde que este artigo foi originalmente publicado, o módulo MakeNode tenha sido publicada para a Galeria de YUI e recebeu algumas melhorias. Por favor, consulte o artigo atualizado, Atualizado: O "MakeNode" Extensão Widget .

Em meu artigo anterior, uma receita para um 3 YUI Aplicação , mostrei uma maneira de usar Y.substitute como um processador de modelo muito básico. A idéia tomou a vida de lá, com sugestões de o pessoal do yui # canal de IRC, e eu fiz uma extensão de Widget que está disponível no meu site, chamado MakeNode . MakeNode não é um processador de modelo genérico e não se entende como um só. Por outro lado, é totalmente integrado com o YUI Widget classe fundação, incluindo className e eventos ajudantes e internacionalização. Neste artigo, vou tomar a Spinner exemplo e modificá-lo para seguir as orientações do meu artigo anterior e usar MakeNode. O componente Spinner modificados ( JS , CSS , sprites ), bem como um exemplo estão disponíveis no meu site. Links para recursos adicionais podem ser encontradas no final deste artigo.

Estendendo seu componente

Uma vez MakeNode é carregado, você precisa incluir o módulo na sua YUI().use() declaração usando o nome 'makenode' . Então, para estender seu widget, você listá-lo no terceiro argumento para Y.Base.create() , assim:

  Y. Spinner Y.Base.create = (
      "Spinner",
      Y. Widget,
      [Y. MakeNode],
      {
         / Members / exemplo ...
      },
      {
          / / Membros estáticos
      }
 ); 

Você pode adicionar MakeNode ao longo de qualquer número de extensões adequado para Widget, como WidgetParent, WidgetChild, WidgetStdMode, etc MakeNode adiciona dois métodos protegidos, _makeNode e _locateNodes, e ele irá ler a partir de várias propriedades estáticas, se encontrado.

Todos os membros desta extensão são ou protegidos ou privados já que são feitos para serem usados ​​pelo desenvolvedor do componente e não pelo implementador usando esses componentes, que não deve ser incomodado com eles.

Definindo o Modelo

A primeira coisa que normalmente você vai fazer é definir o modelo para seu componente. Para a Spinner, o nosso modelo será:

  _template: [
     "<input Type="text" title="{s input}" class="{c input}"> ',
     "<button Type="button" title="{s up}" class="{c up}"> botão </> ',
     "<button Type="button" title="{s down}" class="{c down}"> botão </> '
 ]. Join ('\ n'), 

O modelo padrão será normalmente chamado _TEMPLATE e declarou ao longo da outras propriedades estáticas da classe, como ATTRS . MakeNode vai usar este modelo, se nenhum outro é expressamente previsto. O modelo é feito de HTML simples mais uma série de espaços reservados entre chaves, cada um feito de um único personagem (o código de processamento) e seguido por um ou mais argumentos. Os espaços reservados e que eles produzem são:

  • {@ attributeName} valor de atributo de configuração

  • {p propertyName} valor propriedade de instância

  • {m methodName arg1 arg2 ….} valor de retorno de um método. O código de processamento é seguido pelo nome do método e qualquer número de argumentos separados por espaço em branco. Cadeias devem ser colocados entre aspas duplas. Números, booleanos e null serão convertidos de string para os seus tipos de dados adequada

  • {c classNameKey} className CSS gerado a partir do _CLASS_NAMES propriedade estática

  • {s key} da cadeia de strings atributo, utilizando key como o atributo sub-.

  • {? other placeholder } Produz a seqüência checked quando o resultado do processamento do resto do espaço reservado é verdade.

  • {} qualquer outro valor será tratado como Y.substitute faz.

Por exemplo, {@ value} se traduzirá em this.get('value') , enquanto {p value} traduz a this['value'] .

O {m} de espaço reservado é um pouco mais complexa. O primeiro argumento após o m código de processamento é o nome do método eo resto dos argumentos, todos separados por espaços em branco, que será passado para o método indicado. Estes argumentos podem ser números, null , true , false ou strings entre aspas duplas. MakeNode irá analisá-los e convertê-los em seus tipos adequada, assim {m myMethod 123.45 true “this is a string”} resultará em chamar this.myMethod(123.45, true, “this is a string”) para que os dois primeiros argumentos são convertidos para seus tipos de dados corretos ea string pode conter espaços. Para incluir um aspas duplas, use \\" , a barra invertida dupla sendo necessário, porque o JavaScript irá interpretar um único e descarta-lo antes que ele chegue ao MakeNode. Somente aspas são permitidos, MakeNode não usa eval() para que o analisador é limitado mas segura. Qualquer coisa, mas números, null , booleanos e strings de aspas duplas será ignorado.

O {?} espaço reservado é útil para uso com caixas de seleção e botões de rádio. Ele produzirá a string “checked” , dependendo do valor de verdade do código de instrução de processamento que se segue. Assim, <input type=”checkbox” {? m getLength}/> <input type=”checkbox” {? m getLength}/> irá produzir um checkbox marcados se o getLength método retorna nada, mas zero. {?} aceitará qualquer um dos outros espaços reservados, embora ela só faz sentido com os três primeiros.

Para a {c} espaço reservado, nós precisamos ter um _CLASS_NAMES propriedade definida.

Espaços reservados adicional pode ser adicionado ao MakeNode, adicionando-os na _templateHandlers hash.

A propriedade _CLASS_NAMES

Junto com o ATTRS e _TEMPLATE atributos estáticos, podemos definir uma _CLASS_NAMES propriedade que aponta para uma matriz de strings. Cada uma dessas cadeias será usado para gerar um className. Assim _CLASS_NAMES: ['input'] irá produzir o className “yui3-spinner-input” . Os nomes de classes são armazenadas em uma propriedade de instância this._classNames . A {c input} espaço reservado no modelo acima será substituído por “yui3-spinner-input” .

Você pode usar o _CLASS_NAMES propriedade para gerar qualquer número de nomes de classes, se você usá-los no modelo ou não. Você ainda pode alcançar aqueles classnames extra a partir de dentro this._classNames . O className é gerada utilizando o yui3 prefixo seguido pelo valor do NAME propriedade estática virou minúsculas, e então a string dada em _CLASS_NAMES (este último não será transformado em minúsculas), todos separados por hífens. O _classNames de hash irá conter também o classnames para o boundingBox eo contentBox , a primeira sob o "." chave eo segundo sob o “content” chave. Widget atribui ao boundingBox de classnames derivado dos valores do NAME propriedade de cada uma das classes na cadeia de herança, começando com yui3-widget . Lojas MakeNode em this._classNames apenas className o mais alto para o boundingBox .

Se um componente é vários níveis longe de Widget, como SuperSpecialSpinner herdando de SuperSpinner que herda de Spinner que herda de Widget, e se algum ou todos eles têm _CLASS_NAMES propriedades definidas, MakeNode produzirá classnames para todos eles e armazená-los em this._classNames . Você não precisa incluir em cada nível os nomes já declarados nos níveis anteriores. Na verdade, é melhor que você não desde o classnames produzida em cada nível irá usar o valor do NAME propriedade desse nível. Assim, em SuperSpecialSpinner , {c input} ainda vai resultar em “yui3-spinner-input” e não “yui3-superspecialspinner-input” e por isso vai manter o seu arquivo CSS ainda válido.

O espaço reservado {s}

Widget tem uma strings atributo de configuração definida, embora não seja inicializado com qualquer valor. Este atributo é utilizado para armazenar seqüências de caracteres que são visíveis (ou, via leitores de tela, leia a) o usuário. É importante que você nunca incluem cordas visível diretamente no modelo. Esta não é uma exigência de MakeNode - nunca foi uma boa idéia de todo. Todas as seqüências que devem ser vistas por ou ler para o usuário sempre deve ser colocado no strings atributo. O strings atributo contém um hash em que cada texto individual fica por sua chave. O componente Spinner tem o seguinte texto, que você pode ver usados ​​no modelo acima.

  strings: {
     valor: {
         entrada: ". Pressione a seta para cima / baixo teclas para incrementos menores, page up / down para incrementos importantes",
         up: "Incremento",
         para baixo: "Decrement"
     }
 }, 

A melhor parte de fazer isso é que o componente pode ser localizada para outros idiomas com muita facilidade pelos desenvolvedores usando seu componente. Ao criar uma instância de Spinner, você pode fazer:

  var mySpinner = new Spinner ({strings: Y.Intl.get ('giratório')}); 

Definindo o atributo de configuração strings , desta forma substitui o padrão strings com os valores do arquivo de recursos de linguagem utilizando a linguagem previamente definida. O {s} espaço reservado acessa as cordas armazenados no strings atributo, tanto os padrão ou os convertidos, se definido. O {s xxxx} espaço reservado é, na verdade, nada mais do que um atalho para o {@ strings.xxxx} espaço reservado. No entanto, o primeiro só pode acessar strings no nível superior, enquanto, por exemplo, {@ strings.xxxx.yyyy.zzzz} permitiria o acesso a uma série mais baixo.

Usando _makeNode em renderUI

Nós usamos o modelo para criar a marcação para nosso componente. Para isso, podemos chamar de MakeNode _makeNode método, assim:

  renderUI: function () {
     . this.get ('Contentbox') append (this._makeNode ());
 }, 

Isto irá preencher o contentBox do nosso widget com a marcação do processamento do modelo. O _makeNode método retorna uma instância de Y.Node que pode ser acrescentado ou inserido em qualquer lugar ou apenas mantidos para uso posterior. Ele não retorna uma string, ela produz um Node exemplo.

O _makeNode método leva dois argumentos opcionais: uma referência a um modelo e um objeto para preencher espaços reservados, como Y.substitute faz. No nosso exemplo simples Spinner existe um modelo único para o widget todo, mas outros widgets podem requerer pedaços feitos de vários modelos. Nesse caso, você normalmente chamada _makeNode sem argumentos para a parte principal e chamá-lo mais uma vez com diferentes modelos para preencher as partes extra. O exemplo contém este renderUI método:

  renderUI: function () {
     var fieldset = this._makeNode ();
     this.each (function (item) {
         fieldset.appendChild (this._makeNode (MultipleTemplates.RADIO_TEMPLATE, item));
     }, This);
     . this.get ('Contentbox') append (fieldset);
 } 

A primeira chamada para _makeNode retorna um Node instância armazenada na variável fieldset . O componente de exemplo também é estendido com Y.ArrayList para o RADIO_TEMPLATE será preenchido com valores retirados os itens armazenados na lista de matriz e os nós resultantes anexado ao fieldset antes de ser finalmente anexado ao contentBox . Os espaços reservados especiais, tais como {@} ou {p} ainda se referem a atributos ou propriedades no objeto principal. Os itens aninhados serão processadas assim como Y.substitute faria.

O método _locateNodes

MakeNode prevê ainda um _locateNodes método que irá tentar localizar todos os elementos com os nomes de classes declaradas no _CLASS_NAMES . Para localizar os elementos específicos que você pode passar qualquer número de chaves className, caso contrário, _locateNodes tenta todos eles. Para cada elemento encontrado de cada className, _locateNodes produzirá uma propriedade de instância privada usando o prefixo sublinhado seguido pelo nome da chave e da “Node” de sufixos. Assim, no nosso exemplo Spinner, _locateNodes irá gerar as propriedades _inputNode , _upNode e _downNode . Se vários elementos têm a mesma className, _locateNodes retornará uma referência para o primeiro deles. Se um elemento não for encontrado, nenhuma variável será criada.

Na componente Spinner usamos _locateNodes após a criação da marcação:

  renderUI: function () {
     . this.get (CBX) append (this._makeNode ());
     this._locateNodes ();
 }, 

A propriedade estática _EVENTS

Uma propriedade adicional pode ser definido ao longo das linhas de _TEMPLATE e _CLASS_NAMES e que é _EVENTS . _EVENTS irá conter um hash composta de chaves nome da classe, cada uma contendo uma mistura de tipos de eventos e métodos para lidar com eles. É melhor explicada com um exemplo:

  _EVENTS: {
     '.': {
         chave: {
             fn: '_onDirectionKey',
             args: ((Y.UA.opera) "para baixo:":!? "imprensa:") + "38, 40, 33, 34"
         },
         mousedown: '_onMouseDown'
     },
     '..': {
         mouseup: '_onDocMouseUp'
     },
     entrada: {
         mudança: "_onInputChange '
     }
 }, 

_EVENTS é um objeto (um hash), com qualquer número de propriedades. Os nomes das propriedades, ou seja, as chaves do hash, identificar os elementos cujos eventos vamos ouvir. Eles são os mesmos identificadores utilizados em _CLASS_NAMES . Há duas teclas especiais extras "." e ".." . Enquanto as chaves className referem-se a elementos aninhados dentro do contentBox , o "." chave refere-se à boundingBox em si, enquanto ".." refere-se ao documento que contém este widget. Pense neles como fazer um chdir comando quando localizado no boundingBox nível. O _EVENTS propriedade é processado após a renderUI , bindUI e syncUI métodos têm sido chamados assim o widget deverá já estar inserido dentro do corpo do documento, caso contrário o ".." irá falhar.

Cada uma das entradas em _EVENTS é um objeto, ainda, que usa o tipo de evento como sua chave eo nome de um método de instância para lidar com isso. _EVENTS , sendo uma variável estática, não tem acesso a this por isso não pode tirar referências função real, somente o nome do método ouvinte de evento. Alguns tipos de eventos necessitam de argumentos extra, como a key do evento. Nesse caso, em vez de fornecer o nome do manipulador de eventos que você pode fornecer um objeto com propriedades fn e args para manter o nome da função e os argumentos extra, quando necessário.

MakeNode usará Node.delegate para ouvir os eventos dos elementos aninhados, enquanto ele usará Y.on para ouvir a eventos do boundingBox eo corpo do documento. (Nota: ouvir a key evento em qualquer elemento aninhado só funciona com a versão 3.4.0pr1 e acima, uma vez que a delegação da key .. evento não estava disponível antes de Todas as características do outro trabalho com as versões anteriores também)

O _EVENTS declarações são cumulativos quando os componentes herdar um do outro. Cada classe na cadeia de herança terá o seu próprio _EVENTS declaração processada separadamente.

A propriedade estática _ATTRS_2_UI

Eventos em ambos os sentidos, a partir da interface do usuário para o componente e do componente de interface do usuário. Os primeiros são tratados pelo _EVENTS propriedade. Depois, há os eventos disparados por mudanças atributo de valor que precisam ser refletidas na interface do usuário. Como eu mencionei no artigo anterior, quando houver efeitos secundários de alterar um atributo de configuração, eles devem ser manuseados por ouvintes de eventos de alteração, e não pelo opcional setter método do atributo, que só deve lidar com normalizar o valor a ser definido. A interface do usuário deve refletir o estado dos atributos de configuração, primeiro em syncUI , ao ser inicializado e, em seguida, em cada evento de alteração de atributo. Para este último, é preciso anexar um ouvinte de evento, o que fazemos em bindUI . Widget já fornece um mecanismo para fazer esse simples, que descrevi nos comentários ao artigo anterior.

Widget usa o exemplo de propriedade _UI_ATTRS que contém um objeto com duas outras propriedades, SYNC e BIND . Cada um destes é uma matriz listando os nomes dos atributos de configuração para ser inicialmente sincronizado e, em seguida, ouviu a fim de manter a interface do usuário refletindo valores atuais. Widget espera que cada uma dessas entradas de ter um método associados a ela, em homenagem ao nome do atributo prefixado por _uiSet com o primeiro caractere do nome do atributo convertidos em maiúsculas para ter o nome do método no caso de camelo adequada. Assim, se "value" foi listado em qualquer um dos _UI_ATTRS matrizes (em qualquer SYNC ou BIND ), Widget esperaria encontrar uma _uiSetValue método. Este método vai receber dois argumentos, o value a ser definido eo src da mudança. Este é o código para o nosso Spinner _uiSetValue método:

  _uiSetValue: function (valor, src) {
     if (src === UI) {
         retorno;
     }
     this._inputNode.set (VALOR, this.get (FORMATTER) (valor));
 }, 

Todos os identificadores de maiúsculas que você vê nesta parte do código correspondem aos constantes string declarada em outro lugar, para permitir que o compressor YUI para fazer seu trabalho melhor. O método, basicamente, define o value do atributo HTML no <input> caixa para o conjunto novo valor, depois de ser formatado. A referência à caixa de texto foi fornecido pelo _locateNodes . O src argumento é inicialmente marcada para ver se definido para o valor de seqüência 'ui' . Se isto é assim, nenhuma ação será tomada. Isso é para evitar loops infinitos. Se o usuário digita algo na caixa de entrada, o seu valor seria ir para o value atributo de configuração que então iria disparar um valueChange evento, que iria ficar _uiSetValue chamado que, se não for controlada, então vá e altere o valor da caixa de entrada, que desencadearia todo o processo novamente. Assim, em _uiSetValue , se sabemos que a mudança vem da UI, não fazemos nada e assim quebrar o loop. No entanto, isso requer um outro pedaço de código em outros lugares. No ouvinte para o evento DOM, quando vamos definir o atributo de configuração, usamos o terceiro argumento opcional para definir, como este:

  _afterValueChange: function (ev) {
     this.set (VALOR, ev.newVal, {src: UI});
 } 

Cabe a nós garantir que as mudanças provenientes da interface do usuário, portanto, são marcados e depois verificar que mesma bandeira para evitar loops.

Com tudo isso dito, eu ainda não mencionou a propriedade estática _ATTRS_2_UI mencionado no título desta seção. Como os comentários em meu artigo anterior mostra (através da tolices que fiz no-las), certificando-se que todos os atributos que afetam a interface do usuário estão devidamente listados é um pouco confuso. Você nunca deve inicializar _UI_ATTRS a partir do zero desde Widget já lista uma série de atributos e esses seriam perdidos. Você tem que concatenar nomes de atributos novos ao longo dos já existentes, que é um pouco difícil de lembrar como fazer isso direito. Para torná-lo simples, MakeNode vai ler a propriedade estática _ATTRS_2_UI e fazer isso de concatenação para você. Ele irá concatenar todas as listas da classe todos e cada um na cadeia de herança para cada nível de cada classe pode lidar com seus próprios atributos. No Spinner, temos:

  _ATTRS_2_UI: {
     BIND: VALOR,
     SYNC: VALOR
 }, 

MakeNode irá aceitar tanto um array de nomes ou um nome único atributo, como neste caso.

A pergunta surge naturalmente, por duas listas, uma para a outra ligação para sincronizar? Muitas vezes o SYNC matriz tem menos entradas do que o BIND lista e isso é porque o modelo para o componente já poderia ter o valor padrão muito mesmo que o atributo de configuração e não há necessidade de fazer uma sincronização inicial. Assim, se o valor padrão para o value atributo de configuração é uma string vazia ea <input> elemento no modelo não tem value atributo, então não há necessidade de sincronizá-los na inicialização.

MakeNode irá verificar se há entradas duplicadas em qualquer uma dessas matrizes. Se algum aparecer, isso significa que uma classe de componente herda de nosso já lida com esse atributo e qualquer nova declaração seria ultrapassar mais provável que o _uiSetXxxx manipulador para ele. Aliás, MakeNode também verifica entradas duplicadas em _CLASS_NAMES , que também pode causar conflitos em alguns, embora nem todos, as circunstâncias. MakeNode irá escrever uma mensagem para o log por qualquer erro desse tipo.

Conclusão

MakeNode fornece um processador de modelo muito simples, com funcionalidades simples que é altamente integrada com a classe fundação Widget. Ele também fornece métodos auxiliares para criar nomes de classes a serem utilizados no modelo e usar esses nomes para localizar os nós criados. Ele também fornece os meios para ligar para os eventos gerados tanto pela interface do usuário e do próprio componente e associar cada um com um método. Ele faz todas estas coisas, tomando o cuidado de respeitar a cadeia de herança em linha reta até Widget e qualquer nível de classes que você pode definir.

Não prever absolutamente todas as possibilidades, mas abrange uma boa variedade delas. No entanto, não exclui a possibilidade de adicionar funcionalidades extra. Você pode raramente tem que escrever um bindUI ou syncUI método se você usa a cola fornecida pelo MakeNode, mas poderá fazê-lo, já que MakeNode não usá-los.

Como um bônus para aqueles que tiveram a paciência de ler até aqui, tenho também modificou Botão Anthony Pipkin do conjunto de componentes galeria:

A documentação da API pode ser encontrada aqui .

Compartilhar e ampliar: Bookmark com del.icio.us | digg it! | reddit!

6 Comments »

RSS feed para comentários a este post. TrackBack URI

  1. É este compatível com o componente de Visualização de novos Ryan MVC chegando em 3.4.x? Poderia ser usado para processar a marcação de uma forma compatível com esse quadro?

    Comentário por Andrew Wooldridge - 09 de julho de 2011 #

  2. Andrew ,

    Essa extensão é concebida como um auxiliar para construir componentes, como o botão e exemplos Spinner show, para não criar aplicações inteiras, como o framework MVC faz. Esses componentes podem ser usados ​​em qualquer lugar a qualquer outro componente derivado de Widget pode. No framework MVC, seria natural para uso de tais componentes em classes herdando de Y. Ver para construir a interface do usuário, junto HTML simples ou qualquer outro componente derivado do Widget, se ele usa MakeNode ou não.

    Comentário por Satyam - 10 julho de 2011 #

  3. Satyam,

    Isso é muito grande! Tenho experimentado todos os pontos de dor que você está tratando com esta extensão Widget. Parece que usando esta extensão pode remover um monte de código caldeira placa-repetitivo, termina-se por escrito, quando a criação de widgets personalizados, ao padronizar sobre como conectar o código e lógica, com o DOM e renderização, que é emocionante ver!

    Você estará adicionando esta ao 3 YUI Gallery, tornando-o mais acessível para as pessoas. Use ()?

    Como assinalou Andrew haja alguma sobreposição conceitual com Y. Ver para eventos e renderização, embora as APIs dois são diferentes. Pode valer a pena descobrir se há um terreno comum para as APIs dois para ser mais similar (especificamente com o material eventos DOM).

    De uma perspectiva geral API que você fez tudo protegido / privado através da '_' prefixo (underscore), estou curioso para ouvir seus pensamentos sobre isso. Eu sinto que as propriedades estáticas como: `_CLASS_NAMES`, e `` _EVENTS, etc pode muito bem ser: `CLASS_NAMES`, e `` EVENTOS sans o sublinhado prefixo. Pode ser apenas a minha preferência, mas ele se sente excessivamente protetora:)

    Comentário por Eric Ferraiuolo - 12 julho de 2011 #

  4. Eric ,

    Obrigado pelo seu comentário. Na verdade, este nasceu de repetição enfadonha. Eu também gosto da arrumação do componente resultante como muito do que é tratado de forma declarativa e processual do material é reduzido e padronizado, especialmente todos os métodos _uiSetXxxx.

    Eu não quero lidar com GitHub e da Galeria YUI por isso não vou postá-lo lá. Eu não me importo se alguém faz, mas eu não vou fazê-lo ou mantê-lo.

    O DOM coisa eventos saíram direto da Y. View, exceto que eu use as teclas classnames para identificar os elementos, uma vez que toda a extensão faz, assim, o uso extensivo deles. Ele também lida com ligar eventos em todas as classes de hierarquia, assim você não precisa repetir aqueles em que herdar de outras classes.

    Em relação aos membros protegidos / privado, eu comentei isso com Jenny, que pediu a equipe e eu mudei todos os membros da ex-público para os protegidos com base nesse conselho.

    Basicamente, existem dois papéis de desenvolvedores, o criador do componente e do usuário do componente ou "implementador", como Jenny que se refere a eles. É melhor se os membros da classe significou para o desenvolvedor de componentes não atravancar a documentação da API para o desenvolvedor. Neste sentido, muitos membros do Widget, como CONTENT_TEMPLATE, renderUI, HTML_PARSER ou Base.ATTRS nunca deveria ter sido público que o implementador não deve mesmo saber sobre eles.

    Por outro lado, membros como _uiSetTabIndex ou _uiSetDisabled são muito bem declarado como protegido. Assim, no modo de desenvolvedor de componentes, você deve ter sempre em Mostrar Protegido, enquanto como um implementador você não deve. Isto impediria os desenvolvedores de componentes da re-implementar a funcionalidade que já está lá, como o componente Button original na galeria que tinha código de refazer o que esses dois métodos já fazem.

    Acho que desde que Jenny teve que levá-la para a equipe não havia diretrizes a esse respeito e, portanto, teremos de viver com alguma inconsistência nos componentes existentes.

    Comentário por Satyam - 12 julho de 2011 #

  5. Uma atualização:

    Eu adicionei um código de processamento: "1". É útil para lidar com singular / plural de texto, por exemplo: {p qty} {1} {p qty "unidade" "unidades"}. Esta string vai produzir tanto "1 unidade" ou "unidades de 123", dependendo do valor do qty propriedade.

    Como mostrado no exemplo acima, os espaços reservados agora podem ser aninhados um dentro do outro. Assim, um argumento para um espaço reservado pode ser o valor retornado por um outro espaço reservado.

    Também mudei o espaço reservado para agir mais como a {?}: Operador. Em vez de produzir um texto fixo, que permite retornar nada seus argumentos dizer, por exemplo: {? {P qty} {p} qty "none"}.

    Como um exemplo extremo, esse modelo:

    {? {P qty} "{p qty} {1} {p qty" unidade "" unidades "}" "none"}

    vai produzir o texto "none", "1 unidade", "2 unidades", "3 unidades" e assim por diante para os valores sucessivos do qty propriedade.

    O método de processamento do modelo está agora disponível como _substitute método.

    Comentário por Satyam - 13 de agosto de 2011 #

  6. Mais alterações:

    Agora, a propriedade _EVENTS estática, os ouvintes de hash definir para cada evento, leva um par extra de seletores virtual. A estrutura do _EVENTS é:


    _EVENTS: {
    selector: {
    eventType: listener,
    ....
    }
    }

    onde os seletores são as chaves usadas na propriedade _CLASS_NAMES para criar o classnames utilizado nos modelos para os elementos HTML, que ajudam a localizá-los.

    Havia dois seletores especiais: "." indica o BoundingBox e '..' o documento está dentro do widget

    Eu tenho agora adicionados outros dois seletores virtual, ESTE, todas as letras maiúsculas, refere-se ao próprio widget e Y para a instância de Y, por exemplo:


    _EVENTS: {
    THIS: {
    visibleChange: '_afterVisibleChange'
    },
    Y: {
    'broadcastingWidget:somethingChange':'_afterSomethingChange'
    }
    }

    A chave Y, embora seja a intenção de representar a instância Y, será tomada pelo JavaScript como a string "Y". Sempre use Y como a tecla virtual, mesmo que você chamou o seu exemplo YUI algo mais, lembre-se, é apenas a string "Y", e não a instância Y reais.

    MakeNode só irá definir após ouvintes de evento, nunca antes (em) os ouvintes, que é o caso mais freqüente. Se você precisar de ouvir um evento de 'antes', configurá-lo como de costume.

    Comentário por Satyam - agosto 19, 2011 #

Deixe um comentário

Nota: Os comentários são moderados para a primeira temporizadores. Spam excluídos.

XHTML: <a href="" title=""> <abbr title="Avião"> <acronym title="Avião"> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <Q cite=""> <strike> <strong>

Hospedado por Yahoo!

Copyright © 2006-2011 Yahoo! Inc. Todos os direitos reservados. Política de Privacidade - Termos de Serviço

Alimentado por WordPress em Yahoo! Web Hosting .