ダイアログを動的に作成する

DojoのサンプルでHTML側にテンプレートを用意してダイアログを開く方法は説明されてるんだけど、テンプレートも含めてJavaScriptから動的にダイアログを作成する方法がよく分からなかったので調べてみた。

ダイアログ作成時のオプションに toggle:"fade" が入ってるとなぜかダイアログが表示されなくて小一時間はまった。

var dialog = dojo.widget.createWidget('dialog', {
  id: "new_dialog",
  bgcolor: "white",
  bgOpacity: "0.5"
});
dialog.domNode.innerHTML = "<button id='ok'>OK</button>";
document.body.appendChild(dialog.domNode);

var okButton = $('ok');
dialog.setCloseControl(okButton);
Event.observe(okButton, 'click', doSomethingFuncion);

dialog.show();

コマンドテンプレート

optparseが面倒くさいので今後はここからコピペする。
元は瀧内さんのコードだけど、どれからパクったか忘れた。

require 'optparse'
COMMAND_LINE = "#{$0} #{ARGV.join(' ')}"
OPT = {}
opts = OptionParser.new
opts.on('-a <abc>'){|v| OPT[:abc] = v}
opts.on('-x', '--xyz <xyz>'){|v| OPT[:xyz] = v}
opts.on_tail('-v', '--version', 'Show version.'){puts(opts.ver); exit}
opts.on_tail('-h', '--help', 'Show this message.'){puts(opts.help); exit}

::Version = MyApp::VERSION
opts.order! ARGV
CMD = ARGV.shift

MyApp.new.start CMD, OPT

現在位置で可能な最大のズームレベルを取得する

// map:GMap2
map.getCurrentMapType().getMaximumResolution(map.getCenter())

[追記] これでは駄目みたいでした。
Google Groupes

getMaximumResolution was never related to what map tiles were available
on the server, it only ever returned the max zoom number that the
mapType would handle

getMaximumResolutionはマップタイプごとに固定値を返すだけみたい。
なんで引数取るんだ?

ゆきひろ認証プラグイン(acts_as_yukihiro_ninshoable)

Ruby会議2007、もとい、Reject会議2007で発表されたベーパーウェアのアイデアに感銘を受け、いきおいまかせに実装してしまいました。反省はしていない。


このRailsプラグインをインストールすると素人がまつもとゆきひろさんの名前をよく「ひろゆき」と間違えることを利用してユーザーを認証できるようになります。まぁ認証失敗してももう一度聞かれるだけなので、最大二回で確実にログインできますけど。「なんに使うんだ?」とかそういうことは聞いちゃ駄目。

インストール

1. 下記コマンドを実行してゆきひろ認証プラグインをインストールする

./script/plugin install svn://rubyforge.org/var/svn/yukihiro-ninsho/vendor/plugins/yukihiro_ninsho

2. コントローラーでこんな感じに宣言する

class ApplicationController < ActionController::Base
  acts_as_yukihiro_ninshoable

3. 認証されてない状態でページを表示しようとしてこうなると成功

ソースコード

ソースをTxDに上げてみたんだけど、なんだかクソ重い上にすぐ落ちるのでRubyForgeに申請中。待ちきれない場合は自分で作ってみるといいと思うよ。
必要なファイルはたった二つだけ。

RubyForgeに登録したけど、一応コードは残しておきます)

# vendor/plugins/yukihiro_ninsho/init.rb
require 'yukihiro_ninsho'
# vendor/plugins/yukihiro_ninsho/lib/yukihiro_ninsho.rb
class ActionController::Base
  def self.acts_as_yukihiro_ninsho(*args)
    define_method :yukihiro_check do
      if params[:action] == 'yukihiro_login'
        yukihiro_login
      elsif params[:action] == 'yukihiro_check'
        yukihiro_render_check
      elsif session[:i_love_ruby] == :ofcourse
        true
      else
        yukihiro_render_check
      end
    end

    define_method :yukihiro_render_check do
      params[:action] = 'yukihiro_welcome' if params[:action] == 'yukihiro_login'
      params[:only_path] = false
      render :inline => <<-end_of_template
<% form_tag :action => 'yukihiro_login', :from => url_for(params) do %>
 <h4>Rubyを開発したのは次のうちどちら?</h4>
 <%= select_tag :matz,
                options_for_select(
                  [['まつもとゆきひろ', 'yukihiro'],
                   ['まつもとひろゆき', 'hiroyuki']]),
                :size => 2, :style => 'border:1px solid gray' %>
 <br/>
 <%= submit_tag 'ログイン' %>
<% end %>
      end_of_template
      false
    end

    define_method :yukihiro_login do
      if params[:matz] == 'yukihiro'
        session[:i_love_ruby] = :ofcourse
        redirect_to params[:from] and return false
      else
        yukihiro_render_check
      end
    end

    define_method :yukihiro_logout do
      session[:i_love_ruby] = nil
      redirect_to :action => 'yuhikiro_check'
    end

    define_method :yukihiro_welcome do
      render :inline => <<-end_of_template
<h4>無事に認証されました</h4>
<%= link_to 'ログアウト', :action => 'yukihiro_logout' %>
      end_of_template
    end

    before_filter *(args.unshift(:yukihiro_check))
  end
end

※ 注意

まともなテストはしてません。ご利用は自己責任で。っていうか、ネタ以外のなにものでもないので、(そんな人いないと思うけど)これで何かを認証できたりすることは期待しないでください。

※ さらに注意

「ゆきひろ認証」でググって来た人がいたら、「http://www.coins.tsukuba.ac.jp/~i021179/blog/20070613」がReject会議での元ネタなので注意してくださいね

ユーザーエージェントでアクセスを制限

application.rb に追加。

def refuse_ua(condition=nil, &block)
  ret =
    if block
      block.call request.user_agent
    else
      case condition
      when String
        refuse_ua /#{condition}/
      when Regexp
         !condition.match(request.user_agent)
      when Array
        condition.inject true do |ret, cond|
          ret && refuse_ua(cond)
        end
      else
        raise ArgumentError
      end
    end
  unless ret
    erase_redirect_results
    redirect_to :back rescue redirect_to :controller => 'top'
  end
  ret
end

def self.refuse_ua(*args, &block)
  if block
    self.append_before_filter *args do |controller|
      controller.__send__ :refuse_ua, nil, &block
    end
  else
    condition = args.shift
    self.append_before_filter *args do |controller|
      controller.__send__ :refuse_ua, condition
    end
  end
end

使い方

refuse_ua 'MSIE'              # IEにアクセスさせない
refuse_ua ['MSIE', 'Firefix'] # IEとFirefoxにアクセスさせない
refuse_ua {|ua| なんか特殊な条件 }

ちゃんと動いてる気がする。