VDR.cgi/cgi-bin/cgi-extend.rb

428 lines
9.4 KiB
Ruby

require 'cgi'
require 'uri'
class Tagen
def method_missing *p, &e
self.class.method_missing *p, &e
end
class <<self
def out opts, &e
o = {}
opts.each do |k, v|
o[ k.to_s.gsub( /(\s|[:=])+/, '').capitalize] = v
end
content = e.call
o[ 'Content-size'] = content.size
o[ 'Content-type'] ||= 'text/html'
o.collect do |k, v|
"#{k}: #{v}" if k && v
end.join "\n"
end
def method_missing name, opts=nil, &e
t = [ name.to_s.sub( /^[^a-zA-Z_]+/, '').gsub( /[^a-zA-Z0-9_:]+/, '') ]
t += opts.collect do |k, v|
k = k.to_s.sub( /^[^a-zA-Z_]+/, '').gsub( /[^a-zA-Z0-9_:]+/, '')
v = case v
when true then k
when Array then v.join ' '
else v
end
"#{k}=\"#{v}\"" if v
end if opts
#t += %w[/] unless e
#b = "<#{t.join ' '}>"
#b += "\n#{e.call.to_s.gsub /^/m, "\t"}\n</#{name}>" if e
#"#{b}\n"
t += %w[/] unless e
b = "<#{t.join ' '}>"
b += "#{e.call}</#{name}>" if e
b
end
alias tag method_missing
def classes pre, *p
p.collect do |i|
pre = nil if '' == pre
i = nil if '' == i
if pre && i
"#{pre}_#{i}"
else
(pre || i).to_s
end
end.join ' '
end
end
end
class Tagen::ConfTable <Array
attr_accessor :name, :tagen
def initialize name = nil, *paras
super( *paras)
name ||= 'conftable'
@name, @tagen = name.to_s, Tagen.new
end
def gen_line i
x = case i
when 0 then :first
when self.size then :last
else :body
end
@tagen.tr( :class => ["r#{i%2}", x]) do
@tagen.td( :class => :r0) do
self[i][0]
end +
@tagen.td( :class => :r1) do
self[i][1]
end
end
end
def gen
@tagen.table( :class => @name) do
(0...self.size).collect do |i|
self.gen_line i
end.join
end
end
end
class Tagen::Input
def initialize cgi = nil, data = nil
@cgi, @data = cgi || Tagen.new, data || {}
end
def time n, f = '%h:%m'
self.digits( "#{n}_hour", Time.now.hour, 2) + ' : ' +
self.digits( "#{n}_min", Time.now.min, 2)
end
def date n, f= '%h:%m'
self.digits( "#{n}_day", Time.now.day, 2) + ' . ' +
self.digits( "#{n}_month", Time.now.month, 2) + ' . ' +
self.digits( "#{n}_year", Time.now.year, 4)
end
def digits n, v = nil, d = nil, c = nil
n = n.to_s
v ||= ''
d = d ? { :size => d, :length => d } : {}
@cgi.input d.update( :class => [:digits, c], :type => :text, :name => n,
:id => n, :value => @data[ n]||v)
end
end
class Tagen::InputRadio <Array
attr_accessor :name, :checked, :tagen
def initialize name, *paras
super( *paras)
@checked, @name, @tagen = nil, name, Tagen.new
end
def gen
self.collect do |k|
@tagen.span( :style => 'white-space: nowrap') do
@tagen.input( :type => :radio, :name => @name, :value => k[0],
:id => "#{@name}_#{k[0]}", :checked => @checked == k[0]) +
@tagen.label( :for => "#{@name}_#{k[0]}") { k[1] }
end
end.join ' '
end
end
class Tagen::Select <Array
attr_accessor :name, :selected, :tagen, :uri
def initialize name, *paras
super( *paras)
@name, @tagen, @simple = name, Tagen.new, true
end
def gen uri = nil
uri ||= @uri || '.'
uri = URI.parse uri unless uri.kind_of? URI
@tagen.form( :action => uri) do
@tagen.select( :name => @name, :id => @name) do
body = self.collect do |k|
@tagen.option( :value => k[0],
:selected => @selected == k[0]) { k[1] }
end.join
end + @tagen.input( :type => :submit)
end
end
end
class Tagen::SelectMenu <Tagen::Select
attr_accessor :title, :css_class, :cols
def initialize title, *paras
super nil, *paras
@title = title
end
def gen uri = nil, css_class = nil, cols = nil
uri ||= @uri
css_class ||= @css_class
cols ||= @cols || 1
uri = URI.parse uri unless uri.kind_of? URI
@tagen.span( :class => [:select, css_class]) do
@tagen.span( :class => :selector) { @title }+
@tagen.span( :class => :subselect) do
(0...self.length).collect do |i|
k = self[ i]
u = uri.dup
if @name
u.query = "#{u.query && "#{u.query}&"}#{@name}=#{k[0]}"
else
u.path += "/#{k[0]}"
end
@tagen.a( :href => u.to_s) { k[1] }
end.join @tagen.span( :class => %w{spacer hide}) { ' | ' }
end
end
end
end
class Tagen::Table <Array
class Column
attr_reader :title, :class
def initialize opts
if x = opts[:value] || opts[:name]
self.gen_meth :value, x
else
raise "Need Proc to get value (:name => '...' or :value => lambda{...})"
end
@title, @class = opts[:title], opts[:class]
if x = opts[:sort]
self.gen_meth :sort, x
elsif x = opts[:compare] || opts[:name]
if x.kind_of? Proc
self.gen_meth :sort do |i|
i.sort &x
end
else
eval <<-EOS
class <<self
def sort i
i.sort do |a, b|
a.#{x} <=> b.#{x}
end
end
end
EOS
end
end
end
def gen_meth name, call=nil, &e
call = e if e
raise ArgumentError, 'I need something to call.' unless call
o = if call.kind_of? Proc
eval "@#{name} = call"
"@#{name}.call o"
else "o.#{call}"
end
eval <<-EOM
class <<self
def #{name} o
#{o}
end
end
EOM
end
end
attr_reader :name, :tagen, :sort_by, :reverse
def initialize name, tagen = nil
@name, @tagen = name, tagen || Tagen.new
end
def sort_by= value
@sort_by, @reverse = if [ '', nil ].include? value
[ false, false ]
else
value = value.to_i
value < 0 ? [ ~value, true ] : [ value, false ]
end
end
def push value
value = Column.new value unless value.class == Column
super value
end
def []= key, value
value = Column.new value unless value.class == Column
super key, value
end
def gen_abstract a, &p
case a.size
when 0 then ''
when 1 then p.call a, 0, 'first last'
else
p.call( a, 0, 'first') +
(1...a.size-1).collect do |i|
p.call a, i, 'body'
end.join +
p.call( a, a.size-1, 'last')
end
end
alias gen_abstract_td gen_abstract
alias gen_abstract_th gen_abstract
alias gen_abstract_tr gen_abstract
def sort array
array = self[ @sort_by].sort array if @sort_by && self[ @sort_by].respond_to?( :sort)
array.reverse! if @reverse
array
end
def generate array
@tagen.table :id => @name, :class => :table do
@tagen.thead do
@tagen.tr do
self.gen_abstract_th self do |a, i, p|
t = a[i].title
l, d = if @sort_by == i
if @reverse
[ i, 'sorted reverse' ]
else [ ~i, 'sorted' ]
end
else [ i, 'normal' ]
end
@tagen.th :class => [p, d, "r#{i%2}"] do
if a[i].respond_to? :sort
@tagen.a :href => "?#{@name}_sortBy=#{l}" do
t
end
else t
end
end
end
end
end +
@tagen.tbody do
self.gen_abstract_tr self.sort( array) do |a, i, p|
@tagen.tr :class => [p, "row#{i}", "r#{i%2}"] do
self.gen_abstract_td self do |b, j, p|
@tagen.td :class => [p, "c#{j%2}", "col#{j}", @sort_by == j ? 'sorted' : ''] do
b[j].value a[i]
end
end
end
end
end
end
end
end
class Tagen::Directory < Tagen::Table
attr_reader :opened
def initialize *p
super( *p)
@opened = []
end
def opened= value
unless [ '', nil ].include? value
value.split( ',').each &method( 'open=')
end
end
def open value
value = value.split '.' if value.kind_of? String
raise "Unexpected type of value instead Array: #{value.class}" unless value.kind_of? Array
@opened.push value.collect {|x| x.to_i }
end
alias open= open
def close value
value = value.split '.' if value.kind_of? String
raise "Unexpected type of value instead Array: #{value.class}" unless value.kind_of? Array
@opened.delete value.collect {|x| x.to_i }
end
alias close= close
def generate array
@tagen.table :id => @name, :class => :table do
@tagen.thead do
@tagen.tr do
self.gen_abstract self do |a, i, p|
t = a[i].title
l, d = if @sort_by == i
if @reverse
[ i, 'sorted reverse' ]
else [ ~i, 'sorted' ]
end
else [ i, 'normal' ]
end
@tagen.th :class => [p, d, "r#{i%2}"] do
if a[i].respond_to? :sort
@tagen.a :href => "?#{@name}_sortBy=#{l}" do
t
end
else t
end
end
end
end
end +
@tagen.tbody do
self.gen_abstract self.sort( array) do |a, i, p|
@tagen.tr :class => [p, "row#{i}", "r#{i%2}"] do
self.gen_abstract self do |b, j, p|
@tagen.td :class => [p, "c#{j%2}", "col#{j}", @sort_by == j ? 'sorted' : ''] do
b[j].value a[i]
end
end
end
end
end
end
end
end
class Tagen::VerticalLinks <Array
def join
Tagen.span( :class => 'vertical-links') do
super Tagen.span( :class => 'spacer') {' | '}
end
end
alias to_s join
end
class Tagen::WebSearch
attr_accessor :text, :tagen
def icon() '' end
def title() '' end
def initialize text = nil
@text, @tagen = text, Tagen.new
end
def gen text = nil
raise ArgumentError, 'No Title to search' unless text ||= @text
t = self.icon ? @tagen.img( :src => self.icon) : ''
t += self.title || ''
@tagen.a( :href => self.uri( text), :target => :_blank) { t }
end
end
class Tagen::IMDb < Tagen::WebSearch
def uri( t) "http://imdb.com/find?s=all&q=#{CGI.escape t}" end
def icon() 'http://imdb.com/favicon.ico' end
end
class Tagen::Wikipedia < Tagen::WebSearch
def uri( t)
"http://de.wikipedia.org/wiki/Spezial:Suche?go=Artikel&search=#{CGI.escape t}"
end
def icon() 'http://de.wikipedia.org/favicon.ico' end
end