среда, сентября 13, 2006

Rails javascript generation and conditions

I've recently faced the problem: I need to generate javascript that would insert some HTML block unless it is already there. So, the code should be something like this:

if( !($('block_id')) ) {
// insert block
}

All that should go to RJS template.

First revision:

page << "if( !($('block_id')) ) {"
page.insert_html :before, 'container_id', 'my html'
page << "}"

Next, it would be nice to make use of JavaScriptProxy objects (that are spawn, e.g., by page#[] method). The problem is that HTML is emited when those proxy created or evaluated, thus it's not possible to wrap that javascript code into e.g. "if( ... )"..
Solution, first try:

class << page
def if(expr)
self << "if( #{expr} ) {"
yield if block_given?
self << "}"
end
end

page.if "$('#{element_id}').visible()" do
page[element_id].hide
end

This is better then the first one, but too ugly though. A better solution would include some black magick:

module AcitiveView
module Helpers
class JavaScriptProxy
def respond_to?(name)
return true if name.to_sym == :to_script
super
end

def to_script
@generator.instance_variable_get('@lines').pop.chomp(';')
end
end
end
end

Then:

class << page
def if(expr)
self << "if( #{expr.respond_to?(:to_script) ? expr.to_script : expr} ) {"
yield if block_given?
self << "}"
end
end

page.if(page[element_id].visible) do
...
end

And finally, the more peaceful variant:

module ApplicationHelper
def if_exists(page, element_id)
page << "if( !($('#{element_id}')) ) {"
yield if block_given?
page << "}"
end
end

if_exists page, 'block_id' do
page.insert_html .....
end

Комментариев нет: