Rails JsDOMenu

Para quem gosta da similiaridade de páginas web com desktop, aí vai um plugin para Rails com o estilo do Windows XP utilizando o clássico jsMenuBar. Isso me fez lembrar de um usuário que só conseguia operar o sistema por menus, link ficaria em um local obscuro da mente dele :-> .
O conceito é bem simples: cada menu pode ter MenuItens e Menus e uma MenuBar pode ter vários Menus.
Veja um menubar gerado com três menus e submenus.

menu1.png

Anatomia

O Rails JsDOMenu é composto pelos arquivos

/lib/menu_item.rb  # MenuItem
/lib/menu.rb       # Menu
/lib/menu_bar.rb   #MenuBar
/public/images/jsdomenubar/*.png    # imagens para os estilo
/public/stylesheets/jsdomenubar.css # o estilo.
/public/javascripts/jsdomenubar.js  # script da barra
/public/javascripts/jsdomenu.js     # script do menu.

Talvez o estilo da sua aplicações interfira diretamente no esboço do menu.

Instalação

Via svn
Adicione o repositório

script/plugin source svn://rubyforge.org/var/svn/railsmenubar/plugins

Depois instale com

script/plugin install railsmenubar

Via local
Descompacte o arquivo railsmenubar.zip no diretório vendor/plugins do seu Rails. Entre no diretório railsmenubar e execute

ruby install.rb

O jsDOMenuBar funciona em conjunto com os scripts de ajax e javascripts default do rails, portando adicione na sua view ou no seu layout os scripts

  <%= javascript_include_tag 'prototype' %>
  <%= javascript_include_tag 'effects' %>
  <%= javascript_include_tag 'dragdrop' %>
  <%= javascript_include_tag 'controls' %>

e depois o script e o css do railstree

  <%= stylesheet_link_tag 'jsdomenubar' %>
  <%= javascript_include_tag 'jsdomenu' %>
  <%= javascript_include_tag 'jsdomenubar' %>

ficando assim

  <%= stylesheet_link_tag 'jsdomenubar' %>
  <%= javascript_include_tag 'jsdomenu' %>
  <%= javascript_include_tag 'jsdomenubar' %>
  <%= javascript_include_tag 'prototype' %>
  <%= javascript_include_tag 'effects' %>
  <%= javascript_include_tag 'dragdrop' %>
  <%= javascript_include_tag 'controls' %>

Usando

Temos dois tipos de eventos(:event_type) o :code e o :link, sendo
:code => quando necessárioa execução de um script
:link => referência a uma url(default)
Veja abaixo como criar os dois tipos de eventos

m1=MenuItem.new "Mostrar mensagem de Oi!",
                 :event_type => :code,
                  :o nclick => "alert('Oi!')"
m2=MenuItem.new "Ir para hashcode.eti.br",
                 :event_type => :link,
                  :o nclick => "http://www.hashcode.eti.br"
#ou
m2=MenuItem.new "Ir para hashcode.eti.br",
                 :o nclick => "http://www.hashcode.eti.br"

Opções para o MenuItem
:label => A label do menu
:event_type => Tipo do evento :code ou :link
:o nclick => Evento ou url
:enable => Habilita ou Desabilita (true ou false)
:icon => Path do ícone
:icon_hover => Path do ícone quando estiver selecionado

Criando um objeto Menu de tamanho 200px e adicionando o m1 e o m2

menu=Menu.new("Primeiro Teste", 200) #Label e o tamanho em pixel
menu << m1
menu << m2

ou passando um bloco

Menu.new("Primeiro Teste", 200) do |m|
 m << m1
 m << m2
end

Para finalizar esse exemplo vamos criar um MenuBar e adicionar o menu a ele.

mb=MenuBar.new :width => 300
mb << m

Já está pronto para ser utilizado.

Vamos dar nome aos bois

menu2.png

Que esboço maravilhoso esse!! Dá pra ver tanto que sou bom com o Gimp!! O que é aquilo lá em cima do MenuItem.separator ? É uma “quase uma seta”.

Mas dá pra entender um pouco.

Podemos ampliar o desempenho programático utilizando blocos. Exemplo de criação por fechamentos.

@menu=MenuBar.new(:width => 300) do |mb|
  mb << Menu.new("Primeiro Teste", 200) do |m|
    m << MenuItem.new("Ir para hashcode.eti.br", :event_type => :link,  :o nclick => "http://www.hashcode.eti.br")
    m << MenuItem.new("Mostrar mensagem de Oi!", :event_type => :code,  :o nclick => "alert('Oi!')")
  end
end

Observe algo interessante… a sintaxe acima tem uma semelhança com o esboço do menu, que ao meu ver induz ao programador o resultado a ser obtido, pois sabemos que criar menus é uma coisa carinhosamente chata.

Submenus

Como o estilo da linguagem é bem elegante vejamos a criação de submenus para o menu m.

@menu=MenuBar.new(:width => 300) do |mb|
  mb << Menu.new("Primeiro Teste", 200) do |m|
    m << MenuItem.new("Ir para hashcode.eti.br",  :o nclick => "http://www.hashcode.eti.br")
    m << MenuItem.new("Mostrar mensagem de Oi!", :event_type => :code,  :o nclick => "alert('Oi!')")
    m.new("Sub 1") do |s1| #método da instância
      s1 << MenuItem.new("Item 1!", :event_type => :code,  :o nclick => "alert('item 1')")
      s1 << MenuItem.new("Item 2!", :event_type => :code,  :o nclick => "alert('item 2')")
   end
 end
end

pode simplificar mais ainda, utilizando os façade de cada objeto. O mesmo código anterior utilizando façades.

@menu=MenuBar.new(:width => 300) do |mb|
  mb.new("Primeiro Teste") do |m|
    m.new_item("Ir para hashcode.eti.br",  :o nclick => "http://www.hashcode.eti.br")
    m.new_item("Mostrar mensagem de Oi!", :event_type => :code,  :o nclick => "alert('Oi!')")
    m.new("Sub 1") do |s1|
      s1.new_item("Item 1!", :event_type => :code,  :o nclick => "alert('item 1')")
      s1.new_item("Item 2!", :event_type => :code,  :o nclick => "alert('item 2')")
    end
  end
end

E que Deus continue inspirando Yukihiro Matsumoto
Vc escolhe!
Temos também o MenuItem separador.

m=Menu.new("Primeiro Teste", 200)
m <<MenuItem.separator

Um MenuBar com dois menus seria algo assim

@menu=MenuBar.new(:width => 300) do |mb|
  mb.new("Primeiro") do |m|
    m.new_item("Ir para hashcode.eti.br",  :o nclick => "http://www.hashcode.eti.br")
    m.new_item("Mostrar mensagem de Oi!", :event_type => :code,  :o nclick => "alert('Oi!')")
    m.new("Sub 1") do |s1|
      s1.new_item("Item 1!", :event_type => :code,  :o nclick => "alert('item 1')")
      s1.new_item("Item 2!", :event_type => :code,  :o nclick => "alert('item 2')")
    end
  end

  mb.new("Segundo") do |m|
    m.new_item("Faça algo 1",  :o nclick => "http://www.hashcode.eti.br")
    m.new_item("Faça algo 2", :event_type => :code,  :o nclick => "alert('algo 2')")
    m.new("Sub 1 do Segundo") do |s1|
      s1.new_item("Item Sub1 1!",  :o nclick => "http://www.hashcode.eti.br")
      s1.new("Sub 2 do Segundo") do |s2|
        s2.new_item("Sub2 1",  :o nclick => "http://www.hashcode.eti.br")
        s2.new_item("Sub2 2",  :o nclick => "http://www.hashcode.eti.br")
      end
      s1.new_item("Item Sub1 2",  :o nclick => "http://www.hashcode.eti.br")
    end
  end
end

Link for Rails

Tem um esquema legal que é usar a mesmo mecanismo de link do rails o link_to e o link_to_remote.
É necessário a adição da opção :base referenciando a uma instância de qualquer controller(geralmente self ou @controller) para que o mecanismo do método url_for do Rails funcione adequadamente.

link_to

item1=MenuItem.new
item1.link_to "Criar usuário",
              :base => self,
              :controller => "usuarios",
              :action => "adicionar" ,
              :id => 1

m=Menu.new("Usuário")
m << item1

ou

item1=MenuItem.new.link_to "Criar usuário",
              :base => self,
              :controller => "usuarios",
              :action => "adicionar" ,
              :id => 1
m=Menu.new("Usuário")
m << item1

ou tudo junto!!

Menu.new("Usuário").new_item.link_to "Criar usuário",
              :base => self,
              :controller => "usuarios",
              :action => "adicionar" ,
              :id => 1

Dá até gosto de programar nessa linguagem!!

link_to_remote

Utiliza-se ajax da mesma forma que o link_to mas com parametros diferentes(claro né Shairon!).
Exemplo:

item1=MenuItem.newitem1.link_to_remote "Teste Ajax",
                      :base => self,
                      :controller => "usuarios", :update => "id_do_div",
                      :url =>{:action => "adicionar",
                              :c=> 'variavel C',
                              :a => 'variavel A'}

Use e Abuse!!

Posted in

12 comments

  1. Garcia Souza

    Uruuuuuuuuuu, sou o primeiro a comentar.
    Muito bom mesmo cara.
    Realmente um script de responsa

  2. Coelhao

    Na verdade eu queria ver o código do controller e do view desse exemplo, pra mim ver no meu browser como fica. Nas figuras que você colocou eu achei muito bom, mas eu ainda não sou novato no mundo rails e não consegui reproduzir aqui. Se você puder compactar a pasta desse projeto exemplo e colocar aqui seria ótimo :)

  3. Alexandre Campos

    Cara, blz?
    Achei bacana a solução que vc criou, mas não esotu conseguindo testar. Desculpe a minha ignorânica, mas sou aprendiz de estagiário em Rails…

    Eu já coloquei o código no Layout, agora eu crio o Menu no Controller? E onde eu coloco a chamada do Menu na View?

    Seria legal se vc colocasse um exemplo de uma pequena aplicação que só cria o menu bar …

    Abraços.
    Alexandre.

  4. Coelhao

    Maravilha! Minha duvida era a mesma do Alexandre Campos… Agora já substitui a gambiarra que eu usava e to com um menu bonito e com cara profissional no meu app. muito obrigado

  5. Arthur

    Cara, o menu é bem legal, mas no IE6 o menu não aparece, somente a menu bar é visualizado… Já no FireFox o menu aparece de boa…

    Alguma configuração deve ser feita?

  6. Evandro Kumasaka

    Muito legal!,

    teria como alterar a cor da fonte do menu ou item quando
    estiver :enable => false
    ?

    Um abraço,
    Evandro

Post a comment

You may use the following HTML:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>