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.

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, :onclick => "alert('Oi!')" m2=MenuItem.new "Ir para hashcode.eti.br", :event_type => :link, :onclick => "http://www.hashcode.eti.br" #ou m2=MenuItem.new "Ir para hashcode.eti.br", :onclick => "http://www.hashcode.eti.br"
Opções para o MenuItem
:label => A label do menu
:event_type => Tipo do evento :code ou :link
:onclick => 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

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, :onclick => "http://www.hashcode.eti.br") m << MenuItem.new("Mostrar mensagem de Oi!", :event_type => :code, :onclick => "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", :onclick => "http://www.hashcode.eti.br") m << MenuItem.new("Mostrar mensagem de Oi!", :event_type => :code, :onclick => "alert('Oi!')") m.new("Sub 1") do |s1| #método da instância s1 << MenuItem.new("Item 1!", :event_type => :code, :onclick => "alert('item 1')") s1 << MenuItem.new("Item 2!", :event_type => :code, :onclick => "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", :onclick => "http://www.hashcode.eti.br") m.new_item("Mostrar mensagem de Oi!", :event_type => :code, :onclick => "alert('Oi!')") m.new("Sub 1") do |s1| s1.new_item("Item 1!", :event_type => :code, :onclick => "alert('item 1')") s1.new_item("Item 2!", :event_type => :code, :onclick => "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", :onclick => "http://www.hashcode.eti.br") m.new_item("Mostrar mensagem de Oi!", :event_type => :code, :onclick => "alert('Oi!')") m.new("Sub 1") do |s1| s1.new_item("Item 1!", :event_type => :code, :onclick => "alert('item 1')") s1.new_item("Item 2!", :event_type => :code, :onclick => "alert('item 2')") end end mb.new("Segundo") do |m| m.new_item("Faça algo 1", :onclick => "http://www.hashcode.eti.br") m.new_item("Faça algo 2", :event_type => :code, :onclick => "alert('algo 2')") m.new("Sub 1 do Segundo") do |s1| s1.new_item("Item Sub1 1!", :onclick => "http://www.hashcode.eti.br") s1.new("Sub 2 do Segundo") do |s2| s2.new_item("Sub2 1", :onclick => "http://www.hashcode.eti.br") s2.new_item("Sub2 2", :onclick => "http://www.hashcode.eti.br") end s1.new_item("Item Sub1 2", :onclick => "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!!