├── meta ├── name ├── version └── loadpath ├── MANIFEST ├── README ├── lib ├── live │ ├── public │ │ ├── favicon.ico │ │ ├── img │ │ │ ├── flag.gif │ │ │ ├── gem.png │ │ │ ├── gem1.png │ │ │ ├── live.jpg │ │ │ ├── live.png │ │ │ ├── logo.png │ │ │ ├── star.gif │ │ │ ├── top.png │ │ │ ├── facets.png │ │ │ ├── live-sm.png │ │ │ ├── ruby-logo.png │ │ │ ├── sinatra.gif │ │ │ ├── ui.stars.gif │ │ │ ├── gradiant-up.jpg │ │ │ ├── gradiant-silver.png │ │ │ └── gradiant-silver-up.png │ │ ├── js │ │ │ ├── jquery.ui.stars │ │ │ │ ├── ui.stars.gif │ │ │ │ ├── ui.stars.min.css │ │ │ │ ├── ui.stars.css │ │ │ │ ├── ui.stars.min.js │ │ │ │ └── ui.stars.js │ │ │ ├── facetslive.js │ │ │ ├── jquery.tabs.min.js │ │ │ └── jquery.js │ │ └── css │ │ │ ├── reset.css │ │ │ ├── screen │ │ │ ├── tabs.css │ │ │ └── buttons.css │ │ │ └── screen.css │ ├── models.rb │ ├── views │ │ ├── login.haml │ │ ├── login.erb │ │ ├── browse.erb │ │ ├── dashboard.erb │ │ ├── profile.erb │ │ ├── register.erb │ │ ├── script.erb │ │ ├── index.erb │ │ ├── edit.erb │ │ └── layout.erb │ ├── db.rb │ ├── app.rb │ ├── auth.rb │ ├── models │ │ ├── track.rb │ │ ├── user.rb │ │ └── script.rb │ └── server.rb └── live.rb ├── config ├── prime │ ├── users.yml │ └── scripts.yml └── database.yml ├── work ├── k.rb └── deprecated │ └── model │ ├── table.rb │ ├── audit.rb │ └── module.rb ├── start.rb ├── spec └── main.rb ├── config.ru └── Rakefile /meta/name: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /meta/version: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /meta/loadpath: -------------------------------------------------------------------------------- 1 | lib -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | README 2 | lib/live.rb 3 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | = Facets Live! 2 | 3 | Facets Live! brings the API to the cloud. 4 | 5 | -------------------------------------------------------------------------------- /lib/live/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/favicon.ico -------------------------------------------------------------------------------- /lib/live/public/img/flag.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/flag.gif -------------------------------------------------------------------------------- /lib/live/public/img/gem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/gem.png -------------------------------------------------------------------------------- /lib/live/public/img/gem1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/gem1.png -------------------------------------------------------------------------------- /lib/live/public/img/live.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/live.jpg -------------------------------------------------------------------------------- /lib/live/public/img/live.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/live.png -------------------------------------------------------------------------------- /lib/live/public/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/logo.png -------------------------------------------------------------------------------- /lib/live/public/img/star.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/star.gif -------------------------------------------------------------------------------- /lib/live/public/img/top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/top.png -------------------------------------------------------------------------------- /config/prime/users.yml: -------------------------------------------------------------------------------- 1 | --- 2 | username: facets 3 | email: ~ 4 | name: Ruby Facets 5 | password: facets1 6 | 7 | -------------------------------------------------------------------------------- /lib/live/public/img/facets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/facets.png -------------------------------------------------------------------------------- /lib/live/public/img/live-sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/live-sm.png -------------------------------------------------------------------------------- /lib/live/public/img/ruby-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/ruby-logo.png -------------------------------------------------------------------------------- /lib/live/public/img/sinatra.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/sinatra.gif -------------------------------------------------------------------------------- /lib/live/public/img/ui.stars.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/ui.stars.gif -------------------------------------------------------------------------------- /lib/live/public/img/gradiant-up.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/gradiant-up.jpg -------------------------------------------------------------------------------- /lib/live/public/img/gradiant-silver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/gradiant-silver.png -------------------------------------------------------------------------------- /lib/live/public/img/gradiant-silver-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/img/gradiant-silver-up.png -------------------------------------------------------------------------------- /lib/live/public/js/jquery.ui.stars/ui.stars.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/live/master/lib/live/public/js/jquery.ui.stars/ui.stars.gif -------------------------------------------------------------------------------- /work/k.rb: -------------------------------------------------------------------------------- 1 | module Kernel 2 | alias :custom_require :require 3 | 4 | def require(path) 5 | p path 6 | custom_require(path) 7 | end 8 | end 9 | 10 | -------------------------------------------------------------------------------- /start.rb: -------------------------------------------------------------------------------- 1 | $:.unshift 'lib' 2 | 3 | require 'rubygems' 4 | require 'live/app' 5 | 6 | file = File.dirname(__FILE__) + '/config/database.yml' 7 | 8 | Live.start(file) 9 | 10 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | --- 2 | development: 3 | adapter : mysql 4 | database: live_development 5 | #username: <%= ENV['LIVE_USERNAME'] %> 6 | #password: <%= ENV['LIVE_PASSWORD'] %> 7 | 8 | -------------------------------------------------------------------------------- /lib/live/models.rb: -------------------------------------------------------------------------------- 1 | # Here goes your database connection and options: 2 | 3 | # Here go your requires for models: 4 | # require 'model/user' 5 | 6 | require 'live/models/user' 7 | require 'live/models/script' 8 | require 'live/models/track' 9 | 10 | -------------------------------------------------------------------------------- /work/deprecated/model/table.rb: -------------------------------------------------------------------------------- 1 | module Quarry 2 | 3 | class Table 4 | 5 | # 6 | def self.setup 7 | dbh = DBI.connect( "DBI:MySQL:databasename", "username", "password" ) 8 | 9 | end 10 | 11 | end 12 | 13 | end 14 | 15 | -------------------------------------------------------------------------------- /work/deprecated/model/audit.rb: -------------------------------------------------------------------------------- 1 | module Quarry 2 | 3 | # Keep an audit trail of all record modifications. 4 | # better name? 5 | class Audit 6 | property :user, User 7 | property :datetime, DateTime 8 | belongs_to :module 9 | end 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /lib/live/views/login.haml: -------------------------------------------------------------------------------- 1 | .buttons.page 2 | %form{:action=>"/login", :method=>"POST"} 3 | %label{:for=>"username"} Username 4 | %input{:type=>"text", :name=>"username"} 5 | %br 6 | %br 7 | %label{:for=>"password"} Password 8 | %input{:type=>"password", :name=>"password"} 9 | %br 10 | %br 11 | %button{:type=>"submit", :value=>"Login"} Sign In 12 | 13 | -------------------------------------------------------------------------------- /lib/live/views/login.erb: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 | 7 |

8 | 9 | 10 | 11 | 12 |

13 | 14 | 15 |
16 | 17 |
18 | -------------------------------------------------------------------------------- /lib/live/public/js/jquery.ui.stars/ui.stars.min.css: -------------------------------------------------------------------------------- 1 | .ui-stars-star,.ui-stars-cancel{float:left;display:block;overflow:hidden;text-indent:-999em;cursor:pointer;}.ui-stars-star a,.ui-stars-cancel a{width:16px;height:15px;display:block;background:url(ui.stars.gif) no-repeat 0 0;}.ui-stars-star a{background-position:0 -32px;}.ui-stars-star-on a{background-position:0 -48px;}.ui-stars-star-hover a{background-position:0 -64px;}.ui-stars-cancel-hover a{background-position:0 -16px;}.ui-stars-star-disabled,.ui-stars-star-disabled a,.ui-stars-cancel-disabled a{cursor:default!important;} -------------------------------------------------------------------------------- /lib/live.rb: -------------------------------------------------------------------------------- 1 | require 'open-uri' 2 | 3 | module Live 4 | # TODO: Use XDG directory standard 5 | CACHE = ENV['LIVE_CACHE'] || File.expand_path('~/.config/live') 6 | URI = "http://facetslive.org/require/" 7 | end 8 | 9 | module Kernel 10 | 11 | def live(path) 12 | local = File.join(Live::CACHE, path) 13 | if File.exist?(local) 14 | require(local) 15 | else 16 | File.open(local, 'wb') do |f| 17 | f << open_uri(File.join(Live::URI, path)).read 18 | end 19 | require(local) 20 | end 21 | end 22 | 23 | end 24 | 25 | -------------------------------------------------------------------------------- /spec/main.rb: -------------------------------------------------------------------------------- 1 | require 'ramaze' 2 | require 'ramaze/spec/bacon' 3 | 4 | require __DIR__('../app') 5 | 6 | describe MainController do 7 | behaves_like :rack_test 8 | 9 | should 'show start page' do 10 | get('/').status.should == 200 11 | last_response['Content-Type'].should == 'text/html' 12 | last_response.should =~ /

Welcome to Ramaze!<\/h1>/ 13 | end 14 | 15 | should 'show /notemplate' do 16 | get('/notemplate').status.should == 200 17 | last_response['Content-Type'].should == 'text/html' 18 | last_response.should =~ /there is no 'notemplate\.xhtml' associated with this action/ 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/live/db.rb: -------------------------------------------------------------------------------- 1 | require 'sequel' 2 | #require 'facets/hash/rekey' 3 | 4 | module Live 5 | 6 | # 7 | def self.connect_database(options={}) 8 | options = options.inject({}){ |h,(k,v)| h[k.to_sym] = v; h } 9 | 10 | adapter = options[:adapter] || 'mysql' 11 | dbname = options[:database] 12 | host = options[:host] || 'localhost' 13 | username = options[:username] || ENV['LIVE_USERNAME'] 14 | password = options[:password] || ENV['LIVE_PASSWORD'] 15 | 16 | $database = Sequel.connect(:adapter=>adapter, :host=>host, :database=>dbname, :user=>username, :password=>password) 17 | end 18 | 19 | # 20 | def database 21 | $database 22 | end 23 | 24 | end 25 | 26 | -------------------------------------------------------------------------------- /lib/live/public/js/facetslive.js: -------------------------------------------------------------------------------- 1 | // Send an ajax request to rate script. 2 | function star(script_id){ 3 | $.get('/star/' + script_id); 4 | }; 5 | 6 | function flag(script_id){ 7 | $.get('/flag/' + script_id); 8 | }; 9 | 10 | function submit_enter(myfield,e) 11 | { 12 | var keycode; 13 | if (window.event) keycode = window.event.keyCode; 14 | else if (e) keycode = e.which; 15 | else return true; 16 | 17 | if (keycode == 13) { 18 | myfield.form.submit(); 19 | return false; 20 | } else { 21 | return true; 22 | } 23 | }; 24 | 25 | function name_copy(id, old_name) { 26 | var n = prompt("Name of copy?", old_name); 27 | if(n != null) { 28 | location.href="/copy/" + id + "/" + n; 29 | }; 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /lib/live/public/css/reset.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | 6 | html { 7 | } 8 | 9 | body { 10 | margin: 0; 11 | padding: 0; 12 | font-family: helvetica; 13 | background: #feff99; 14 | } 15 | 16 | img { 17 | border: none; 18 | } 19 | 20 | th, h1, h2, h3 { 21 | text-align: left; 22 | font-weight: bold; 23 | } 24 | 25 | p { 26 | margin: 1em; 27 | } 28 | 29 | ul, ol { 30 | margin-left: 2em; 31 | } 32 | 33 | li { 34 | line-height: 120%; 35 | } 36 | 37 | a { 38 | text-decoration: none; 39 | } 40 | 41 | a:hover { 42 | text-decoration: underline; 43 | } 44 | 45 | input, textarea { 46 | border: 1px solid #ccc; 47 | padding: 3px; 48 | } 49 | 50 | td { 51 | vertical-align: top; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /lib/live/app.rb: -------------------------------------------------------------------------------- 1 | require 'yaml' 2 | 3 | module Live 4 | 5 | # 6 | def self.start(config) 7 | configure(config) 8 | Live::Server.run! 9 | end 10 | 11 | # 12 | def self.configure(config) 13 | require 'live/db' 14 | 15 | environment = ENV['LIVE_ENV'] || 'development' 16 | 17 | case config 18 | when File 19 | dbconfig = YAML.load(config)[environment] 20 | when String 21 | dbconfig = YAML.load(File.new(config))[environment] 22 | when Hash 23 | dbconfig = config 24 | else 25 | raise "Invalid configuration." 26 | end 27 | 28 | dbconfig['username'] ||= ENV['LIVE_USERNAME'] 29 | dbconfig['password'] ||= ENV['LIVE_PASSWORD'] 30 | 31 | connect_database(dbconfig) 32 | 33 | require 'live/models' 34 | require 'live/server' 35 | end 36 | 37 | end 38 | 39 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rackup 2 | # 3 | # config.ru for ramaze apps 4 | # use thin >= 1.0.0 5 | # thin start -R config.ru 6 | # 7 | # rackup is a useful tool for running Rack applications, which uses the 8 | # Rack::Builder DSL to configure middleware and build up applications easily. 9 | # 10 | # rackup automatically figures out the environment it is run in, and runs your 11 | # application as FastCGI, CGI, or standalone with Mongrel or WEBrick -- all from 12 | # the same configuration. 13 | # 14 | # Do not set the adapter.handler in here, it will be ignored. 15 | # You can choose the adapter like `ramaze start -s mongrel` or set it in the 16 | # 'start.rb' and use `ruby start.rb` instead. 17 | 18 | $: << 'lib' 19 | 20 | require 'rubygems' 21 | 22 | require 'live/db' 23 | 24 | environment = ENV['LIVE_ENV'] || 'development' 25 | dbconfig = YAML.load(File.new('config/database.yml'))[environment] 26 | connect_database(dbconfig) 27 | 28 | require 'live/models' 29 | require 'live/server' 30 | 31 | run Live::Server #.run! 32 | 33 | -------------------------------------------------------------------------------- /lib/live/views/browse.erb: -------------------------------------------------------------------------------- 1 |
2 | 3 |

4 | Scripts 5 | <% if @criteria %> 6 | matching '<%= @criteria %>' 7 | <% else %> 8 | starting with <%= @letter %> 9 | <% end %> 10 |

11 | 12 | <% unless @criteria %> 13 |
14 | <% ('A'..'Z').each do |letter| %> 15 | <%= letter %>   16 | <% end %> 17 |
18 | <% end %> 19 | 20 |
21 | Displaying 1 to <%= @scripts.count %> 22 |
23 | 24 |
25 | 33 |
34 | 35 |
36 | 37 | -------------------------------------------------------------------------------- /lib/live/auth.rb: -------------------------------------------------------------------------------- 1 | module Live 2 | 3 | # Helper methods for authentication. 4 | module Authentication 5 | 6 | # 7 | def user_id 8 | session[:user_id] 9 | end 10 | 11 | # 12 | def user 13 | @_user ||= user_id ? User[:id=>user_id] : nil 14 | end 15 | 16 | # Set the currently logged in user. 17 | # 18 | # self.user = @user 19 | # 20 | def user=(user) 21 | session[:user_id] = user ? user.id : nil 22 | end 23 | 24 | # 25 | def authorized? 26 | return true if user_id 27 | username = params[:username] 28 | password = params[:password] 29 | user = User.authenticate(username, password) 30 | if user 31 | self.user = user 32 | end 33 | return user 34 | end 35 | alias_method :logged_in?, :authorized? 36 | 37 | # Require authorization for an action 38 | def authorize!(failpath=nil) 39 | unless authorized? 40 | redirect(failpath || '/login') 41 | end 42 | end 43 | 44 | end 45 | 46 | end 47 | 48 | -------------------------------------------------------------------------------- /lib/live/public/js/jquery.ui.stars/ui.stars.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery UI Stars v2.1.1 3 | * http://plugins.jquery.com/project/Star_Rating_widget 4 | * 5 | * Copyright (c) 2009 Orkan (orkans@gmail.com) 6 | * Dual licensed under the MIT and GPL licenses. 7 | * http://docs.jquery.com/License 8 | * 9 | * $Rev: 102 $ 10 | * $Date:: 2009-06-07 #$ 11 | * $Build: 32 (2009-06-12) 12 | * 13 | */ 14 | .ui-stars-star, 15 | .ui-stars-cancel { 16 | float: left; 17 | display: block; 18 | overflow: hidden; 19 | text-indent: -999em; 20 | cursor: pointer; 21 | } 22 | .ui-stars-star a, 23 | .ui-stars-cancel a { 24 | width: 16px; 25 | height: 15px; 26 | display: block; 27 | background: url(ui.stars.gif) no-repeat 0 0; 28 | } 29 | .ui-stars-star a { 30 | background-position: 0 -32px; 31 | } 32 | .ui-stars-star-on a { 33 | background-position: 0 -48px; 34 | } 35 | .ui-stars-star-hover a { 36 | background-position: 0 -64px; 37 | } 38 | .ui-stars-cancel-hover a { 39 | background-position: 0 -16px; 40 | } 41 | .ui-stars-star-disabled, 42 | .ui-stars-star-disabled a, 43 | .ui-stars-cancel-disabled a { 44 | cursor: default !important; 45 | } 46 | -------------------------------------------------------------------------------- /lib/live/models/track.rb: -------------------------------------------------------------------------------- 1 | module Live 2 | 3 | # 4 | class Track < Sequel::Model(:tracks) 5 | 6 | # 7 | def self.popular(limit=10) 8 | order(:requires).limit(limit) 9 | end 10 | 11 | # 12 | def self.newest(limit=10) 13 | #order(:created).distinct(:owner, :name).limit(limit) 14 | filter(:archive=>false).order(:modified).limit(limit) 15 | end 16 | 17 | # 18 | def self.latest(limit=10) 19 | #.order(:modified).distinct(:owner, :name).limit(limit) 20 | filter(:archive=>false).order(:modified).limit(limit) 21 | end 22 | 23 | # Create track table. 24 | def self.create_table 25 | database.create_table(table_name) do |t| 26 | t.primary_key :id 27 | t.integer :user_id # 28 | t.varchar :owner # owner of script 29 | t.varchar :name # name of script 30 | t.boolean :watch, :default => false # keep tabs on this scripts changes? 31 | t.boolen :star, :defualt => false # star 'cause I like it 32 | t.boolen :flag, :defualt => false # warning flag! 33 | end 34 | end 35 | 36 | def self.drop_table 37 | database.drop_table(table_name) 38 | end 39 | 40 | end 41 | 42 | end 43 | 44 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | $:.unshift 'lib' 2 | 3 | require 'rubygems' 4 | require 'live/app' 5 | 6 | desc "Start Rack server" 7 | task :start do 8 | sh "rackup config.ru" 9 | end 10 | 11 | namespace :db do 12 | 13 | task :config do 14 | file = File.dirname(__FILE__) + '/config/database.yml' 15 | Live.configure(file) 16 | end 17 | 18 | desc "test connection" 19 | task :connect => [:config] do 20 | connect_database(@dbconfig) 21 | end 22 | 23 | desc "drop tables" 24 | task :drop => [:connect] do 25 | Live::User.drop_table rescue nil 26 | Live::Script.drop_table rescue nil 27 | Live::Track.drop_table rescue nil 28 | end 29 | 30 | desc "create tables" 31 | task :migrate => [:drop] do 32 | Live::User.create_table 33 | Live::Script.create_table 34 | Live::Track.create_table 35 | end 36 | 37 | task :login do 38 | #MainController.user_login(:login=>'-----', :password=>'-----') 39 | end 40 | 41 | desc "prime database with fake records" 42 | task :prime => [:config] do 43 | Live::Script.create(:name=>"hello", :version=>1, :owner=>"trans", :code=>"puts 'Hello, World!'", :modifier=>"trans", :created=>Time.now-1000) 44 | Live::Script.create(:name=>"bye", :version=>1, :owner=>"trans", :code=>"puts 'Bye, World!'", :modifier=>"trans", :created=>Time.now) 45 | end 46 | 47 | end 48 | 49 | -------------------------------------------------------------------------------- /lib/live/views/dashboard.erb: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | new script 5 |
6 | 7 |
8 |   9 | Welcome, <%= user.username %>. 10 |
11 | 12 |
13 | 17 | 18 |
19 |
20 | 27 |
28 |
29 |
    30 | <% @scripts.each do |s| %> 31 |
  • <%= s.name %>.rb
    32 | <%= s.description %> 33 |
  • 34 | <% end %> 35 |
36 |
37 |
38 |
39 | 40 |
41 | 42 | 47 | 48 | -------------------------------------------------------------------------------- /lib/live/views/profile.erb: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 | 7 |
8 | 9 | 10 |

11 | 12 |
13 | 14 | 15 |

16 | 17 |
18 | 19 | 20 |
21 | 22 |
23 | 24 |
25 | 26 | 27 |

28 | 29 |
30 | 31 | 32 |

33 | 34 |
35 | 36 | 37 |
38 | 39 |

40 | 41 |
42 | Cancel 43 | 44 |
45 | 46 |
47 | 48 |
49 | -------------------------------------------------------------------------------- /lib/live/views/register.erb: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |
7 | 8 |
9 | 10 |
11 |
12 | 13 |
14 | 15 |

16 | 17 |
18 |
19 | 20 |
21 | 22 |
23 |
24 | 25 |
26 | 27 |

28 | 29 |
30 |
31 | 32 |
33 | 34 |
35 |
36 | 37 |
38 | 39 |

40 | 41 |
42 | Cancel 43 | 44 |
45 | 46 |
47 | 48 |
49 | -------------------------------------------------------------------------------- /lib/live/public/css/screen/tabs.css: -------------------------------------------------------------------------------- 1 | 2 | /* root element for tabs */ 3 | ul.tabs { 4 | list-style:none; 5 | margin:0 !important; 6 | padding:0; 7 | height:30px; 8 | border-bottom:0px solid #666; 9 | } 10 | 11 | /* single tab */ 12 | ul.tabs li { 13 | float:left; 14 | text-indent:0; 15 | padding:0; 16 | margin:0 !important; 17 | list-style-image:none !important; 18 | } 19 | 20 | /* link inside the tab. uses a background image */ 21 | ul.tabs a { 22 | display:block; 23 | position:relative; 24 | 25 | font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif; 26 | font-size:100%; 27 | text-decoration:none; 28 | line-height:30px; 29 | text-align:center; 30 | color:#565656; 31 | font-weight:bold; 32 | 33 | cursor:pointer; 34 | 35 | height: 30px; 36 | width: 111px; 37 | 38 | padding:0px; 39 | margin:0px; 40 | margin-top: 2px; 41 | 42 | top:1px; 43 | 44 | border: 1px solid #ccc; 45 | background: #eee; 46 | } 47 | 48 | ul.tabs a:active { 49 | outline:none; 50 | background-color:#6299c5; 51 | border:1px solid #6299c5; 52 | border-bottom: none; 53 | } 54 | 55 | /* when mouse enters the tab move the background image */ 56 | ul.tabs a:hover { 57 | background-color:#dff4ff; 58 | border:1px solid #c2e1ef; 59 | color:#336699; 60 | } 61 | 62 | /* active tab uses a class name "current". it's highlight is also done by moving the background image. */ 63 | ul.tabs a.current, ul.tabs a.current:hover, ul.tabs li.current a { 64 | cursor:default !important; 65 | color:#767676; !important; 66 | background: #fff; 67 | margin-top: 0px; 68 | height: 32px; 69 | border-bottom: none; 70 | } 71 | 72 | /* initially all panes are hidden */ 73 | div.panes div.pane { 74 | display:none; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /work/deprecated/model/module.rb: -------------------------------------------------------------------------------- 1 | module Quarry 2 | 3 | # 4 | class Module 5 | include DataMapper::Resource 6 | 7 | #storage_names[:default] = 'frt' # equivalent to set_table_name in AR 8 | 9 | # 10 | property :id, Serial 11 | 12 | ## 13 | # Name of module/class. Must be fullname (eg. 'Fruit::Basket'). 14 | property :name, String 15 | 16 | ## 17 | # Also known as +superclass+. 18 | # If +NULL+ then it is a Ruby module. 19 | property :parent, Module 20 | 21 | ## 22 | # Modules that are included in this module/class. 23 | # This happens before any other applications, but after extensions. 24 | has n, :inclusions, Module, :through => :inclusions 25 | 26 | ## 27 | # Modules that extend this module/class. 28 | # This happens before any other applications. 29 | has n, :extensions, Module, :through => :extensions 30 | 31 | ## 32 | # Collection of methods that make up the class/module. 33 | has n, :methods, Method 34 | 35 | ## 36 | # Dynamic code to run before any methods are defined. 37 | property :dynamic_before, Text 38 | 39 | ## 40 | # Dynamic code to run after all methods are defined. 41 | property :dynamic_after, Text 42 | 43 | ## 44 | # Which User has ultimate jurisdiction over this module. 45 | property :owner, User 46 | 47 | ## 48 | # Keep an audit trail of record edits. 49 | has n, :audit, Audit 50 | end 51 | 52 | # 53 | class Extension 54 | include DataMapper::Resource 55 | property :id, Serial 56 | belongs_to :module, Module 57 | belongs_to :extend, Module 58 | end 59 | 60 | # 61 | class Inclusion 62 | include DataMapper::Resource 63 | property :id, Serial 64 | belongs_to :module, Module 65 | belongs_to :include, Module 66 | end 67 | 68 | end 69 | 70 | -------------------------------------------------------------------------------- /lib/live/models/user.rb: -------------------------------------------------------------------------------- 1 | require 'digest/md5' 2 | require 'digest/sha1' 3 | 4 | # 5 | class User < Sequel::Model(:users) 6 | 7 | #attr_accessor :password 8 | 9 | #def after_create 10 | # self.passcode = encrypt(password) 11 | # @new = false 12 | # save 13 | #end 14 | 15 | # 16 | def password=(pass) 17 | self.passcode = encrypt(pass) 18 | end 19 | 20 | def email=(address) 21 | self.salt ||= Digest::SHA1.hexdigest("--#{Time.now.to_f}--#{address}--") 22 | super(address) 23 | end 24 | 25 | # 26 | def authenticated?(password) 27 | passcode == encrypt(password) 28 | end 29 | 30 | # 31 | def encrypt(password) 32 | self.class.encrypt(password, salt) 33 | end 34 | 35 | # Gravatar URL 36 | def gravatar 37 | hash = Digest::MD5.hexdigest(email) 38 | "http://www.gravatar.com/avatar/#{hash}" 39 | end 40 | 41 | # 42 | def self.encrypt(password, salt) 43 | Digest::SHA1.hexdigest("--#{salt}--#{password}--") 44 | end 45 | 46 | # 47 | def self.authenticate(username, password) 48 | return nil unless username && password 49 | if username =~ /\@/ 50 | user = User[:email => username] 51 | else 52 | user = User[:username => username] 53 | end 54 | if user 55 | return user unless password 56 | return user if user.authenticated?(password) 57 | end 58 | return nil 59 | end 60 | 61 | # Create the 'user' table. 62 | def self.create_table 63 | database.create_table(table_name) do |t| 64 | t.primary_key :id 65 | t.varchar :username, :size => 50 66 | t.varchar :passcode # encryped password 67 | t.text :salt 68 | t.varchar :name, :size => 50 69 | t.varchar :email 70 | t.varchar :website 71 | t.boolean :confirmed, :default=>false 72 | t.timestamp :modified 73 | end 74 | end 75 | 76 | # 77 | def self.drop_table 78 | database.drop_table(table_name) 79 | end 80 | 81 | end 82 | 83 | -------------------------------------------------------------------------------- /lib/live/views/script.erb: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 | checked="true"<% end %> 8 | /> 9 | 10 | checked="true"<% end %> 12 | /> 13 |
14 | <% if @track && @track.watch %> 15 | unwatch 16 | <% else %> 17 | watch 18 | <% end %> 19 | 20 | <% if user.username == @script.owner %> 21 | edit 22 | <% end %> 23 |
24 | 25 |
26 | live/<%= @script.owner %>/<%= @script.name %>.rb (v.<%= @script.version %>) 27 |
28 | 29 |
30 | <%= @script.description || 'No Description...' %> 31 |
32 | 33 |
34 | 38 | 39 |
40 |
<%= @script.code_highlighted %>
41 |
<%= @script.test_highlighted %>
42 |
43 |
44 | 45 |
46 |
47 | Last Editor: <%= @script.modifier %>   Last Edited: <%= @script.modified %> 48 |
49 |
50 |
51 | 52 | 53 | 58 | 59 | -------------------------------------------------------------------------------- /lib/live/public/js/jquery.tabs.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Lucid Tabs 3 | * Easy tabs with minimal markup. 4 | * 5 | * Copyright (c) 2009 PJ Dietz 6 | * Version: 1.00 7 | * Licensed under the MIT license: 8 | * http://www.opensource.org/licenses/mit-license.php 9 | * 10 | * http://pjdietz.com/jquery-plugins/lucid-tabs/ 11 | */ 12 | (function($){var TabSet,Tab,Page;TabSet=function(elem,options){var domTabs,domPage,domTab,tab,i,u;this.options=$.extend({},TabSet.defaultOptions,options);this.selected=this.options.selected;this.tabs=[];elem.data("TabSet",this);domTabs=elem.find("a[href^=#]");for(i=0,u=domTabs.length;ithis.tabs.length){return false;} 15 | if(index===this.selected){return false;} 16 | this.tabs[index].select();this.tabs[this.selected].deselect();this.selected=index;return true;},getIndex:function(tab){var i,u;for(i=0,u=this.tabs.length;i 2 | 3 |
4 | Facets Live! The revolution is application logic delivery. 5 |
6 | 7 |
8 | 1. 9 |
10 |     $ sudo gem install live
11 |     
12 | 2. 13 |
14 |     require 'live'
15 |     require 'live/username/script.rb'
16 |     
17 |
18 | 19 |
20 | We take you now to live action happening in your neighborhood. 21 |
22 | 23 |
24 | 25 | 26 | 27 | 34 | 41 | 48 | 55 | 56 |
New ScriptsRecently UpdatedMost PopularJust Downloaded
28 |
    29 | <% @scripts_newest.each do |s| %> 30 |
  1. <%= s.owner %>/<%= s.name %>
  2. 31 | <% end %> 32 |
33 |
35 |
    36 | <% @scripts_latest.each do |s| %> 37 |
  1. <%= s.owner %>/<%= s.name %>
  2. 38 | <% end %> 39 |
40 |
42 |
    43 | <% @scripts_popular.each do |s| %> 44 |
  1. <%= s.owner %>/<%= s.name %>
  2. 45 | <% end %> 46 |
47 |
49 |
    50 | <% @scripts_popular.each do |s| %> 51 |
  1. <%= s.owner %>/<%= s.name %>
  2. 52 | <% end %> 53 |
54 |
57 |
58 | 59 |
60 | Look deep into my eyes. 61 |
62 | 63 |
64 | 68 | 69 |

70 | Ruby Programming Language   71 | Original Facets   72 | Sinatra Web Framework 73 |

74 |
75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /config/prime/scripts.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - owner: facets 3 | name: instance 4 | code: | 5 | 6 | module Kernel 7 | # Returns an instance of Instance class which provides internal 8 | # access to an object in a very object-oriented fashion. 9 | def instance 10 | Instance.new(self) 11 | end 12 | end 13 | 14 | # = Instance Class 15 | # 16 | # class Friend 17 | # attr_accessor :name, :age, :phone 18 | # def initialize(name, age, phone) 19 | # @name, @age, @phone = name, age, phone 20 | # end 21 | # end 22 | # 23 | # f1 = Friend.new("John", 30, "555-1212") 24 | # p f1.instance 25 | # f1.instance.update({:name=>'Jerry'}) 26 | # p f1.instance 27 | # 28 | class Instance 29 | 30 | include Enumerable 31 | 32 | def initialize(delegate) 33 | @delegate = delegate 34 | end 35 | 36 | def instance_delegate 37 | @delegate 38 | end 39 | 40 | def each 41 | @delegate.instance_variables.each do |name| 42 | yield(name[1..-1].to_sym, @delegate.instance_variable_get(name)) 43 | end 44 | end 45 | 46 | def to_hash 47 | h = {} 48 | each do |name, value| 49 | h[name] = value 50 | end 51 | h 52 | end 53 | 54 | def [](name) 55 | name = atize(name) 56 | @delegate.instance_variable_get(name) 57 | end 58 | 59 | def []=(name, value) 60 | name = atize(name) 61 | @delegate.instance_variable_set(name,value) 62 | end 63 | 64 | def <<(pair) 65 | name, value = *pair 66 | name = atize(name) 67 | @delegate.instance_variable_set(name, value) 68 | end 69 | 70 | # (See also: Kernel#populate, which uses accessor method rather than setting instance variables directly.) 71 | def update(hash) 72 | hash.each do |pair| 73 | self << pair 74 | end 75 | end 76 | 77 | def keys 78 | @delegate.instance_variables.collect do |name| 79 | name[1..-1].to_sym 80 | end 81 | end 82 | 83 | def names 84 | @delegate.instance_variables.collect do |name| 85 | name[1..-1] 86 | end 87 | end 88 | 89 | def values 90 | @delegate.instance_variables.collect do |name| 91 | @delegate.instance_variable_get(name) 92 | end 93 | end 94 | 95 | private 96 | 97 | def atize(name) 98 | name !~ /^@/ ? "@#{name}" : name 99 | end 100 | 101 | end 102 | 103 | -------------------------------------------------------------------------------- /lib/live/public/css/screen/buttons.css: -------------------------------------------------------------------------------- 1 | /* BUTTONS */ 2 | 3 | .buttons a, .buttons button { 4 | display:block; 5 | float:left; 6 | margin:0 7px 0 0; 7 | background-color:#f5f5f5; 8 | border:1px solid #dedede; 9 | border-top:1px solid #eee; 10 | border-left:1px solid #eee; 11 | 12 | font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif; 13 | font-size:100%; 14 | line-height:130%; 15 | text-decoration:none; 16 | font-weight:bold; 17 | color:#565656; 18 | cursor:pointer; 19 | padding:5px 10px 6px 7px; /* Links */ 20 | } 21 | .buttons button{ 22 | width:auto; 23 | overflow:visible; 24 | padding:4px 10px 3px 7px; /* IE6 */ 25 | } 26 | .buttons button[type]{ 27 | padding:5px 10px 5px 7px; /* Firefox */ 28 | line-height:17px; /* Safari */ 29 | } 30 | *:first-child+html button[type]{ 31 | padding:4px 10px 3px 7px; /* IE7 */ 32 | } 33 | .buttons button img, .buttons a img{ 34 | margin:0 3px -3px 0 !important; 35 | padding:0; 36 | border:none; 37 | width:16px; 38 | height:16px; 39 | } 40 | .buttons label { 41 | margin:0 7px 0 0; 42 | background-color:#f5f5f5; 43 | 44 | font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif; 45 | font-size:100%; 46 | line-height:130%; 47 | text-decoration:none; 48 | font-weight:bold; 49 | color:#565656; 50 | padding:5px 10px 6px 7px; /* Links */ 51 | } 52 | /* STANDARD */ 53 | 54 | button:hover, .buttons a:hover{ 55 | background-color:#dff4ff; 56 | border:1px solid #c2e1ef; 57 | color:#336699; 58 | } 59 | .buttons a:active{ 60 | background-color:#6299c5; 61 | border:1px solid #6299c5; 62 | color:#fff; 63 | } 64 | 65 | /* POSITIVE */ 66 | 67 | button.positive, .buttons a.positive{ 68 | color:#529214; 69 | } 70 | .buttons a.positive:hover, button.positive:hover{ 71 | background-color:#E6EFC2; 72 | border:1px solid #C6D880; 73 | color:#529214; 74 | } 75 | .buttons a.positive:active{ 76 | background-color:#529214; 77 | border:1px solid #529214; 78 | color:#fff; 79 | } 80 | 81 | /* NEGATIVE */ 82 | 83 | .buttons a.negative, button.negative{ 84 | color:#d12f19; 85 | } 86 | .buttons a.negative:hover, button.negative:hover{ 87 | background:#fbe3e4; 88 | border:1px solid #fbc2c4; 89 | color:#d12f19; 90 | } 91 | .buttons a.negative:active{ 92 | background-color:#d12f19; 93 | border:1px solid #d12f19; 94 | color:#fff; 95 | } 96 | 97 | input { 98 | font-size: 100%; 99 | font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif; 100 | color:#565656; 101 | } 102 | 103 | -------------------------------------------------------------------------------- /lib/live/views/edit.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | <% if @script.id %> 6 | cancel 7 | <% else %> 8 | cancel 9 | <% end %> 10 | copy 11 |
12 | 13 |
14 | <% if @script.id %> 15 | live/<%= @script.owner %>/<%= @script.name %>.rb 16 | <% else %> 17 | live/<%= @script.owner %>/.rb 18 | <% end %> 19 |
20 | 21 |
22 | 23 |
24 | 25 |
26 | 27 | 31 | 32 |
33 |
34 | 35 |
36 |
37 | 38 | 43 |
44 |
45 | 46 |
47 | 48 |
49 |
50 | Last Editor: <%= @script.modifier %>   Last Edited: <%= @script.modified %> 51 |
52 | 53 |
54 | <% if @script.id %> 55 | Cancel 56 | 57 |
58 | 59 |
60 | <% else %> 61 | Cancel 62 | 63 | <% end %> 64 |
65 |
66 |
67 | 68 | 69 |
70 | 71 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /lib/live/views/layout.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Facets Live! <%= @title %> 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 32 | 33 | 34 | 35 |
36 | 37 | 70 | 71 | <% if flash[:message] %> 72 |
73 |
<%= flash[:message] %>
74 |
75 | <% end %> 76 | 77 | <%= yield %> 78 | 79 |

80 |
81 | 82 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /lib/live/models/script.rb: -------------------------------------------------------------------------------- 1 | require 'coderay' 2 | 3 | module Live 4 | 5 | # 6 | class Script < Sequel::Model(:scripts) 7 | 8 | # 9 | def self.popular(limit=10) 10 | order(:downloads).limit(limit) 11 | end 12 | 13 | # 14 | def self.newest(limit=10) 15 | #order(:created).distinct(:owner, :name).limit(limit) 16 | filter(:archive=>nil).order(:modified).limit(limit) 17 | end 18 | 19 | # 20 | def self.latest(limit=10) 21 | #.order(:modified).distinct(:owner, :name).limit(limit) 22 | filter(:archive=>nil).order(:modified).limit(limit) 23 | end 24 | 25 | # Create the scripts table. 26 | def self.create_table 27 | database.create_table(table_name) do |t| 28 | t.primary_key :id 29 | t.varchar :owner, :size=>50 # owner of script 30 | t.varchar :name, :size=>50 # name of script 31 | t.integer :version, :default=>1 # version number 32 | t.varchar :description # brief description 33 | t.text :code # script's source code 34 | t.text :test # unit test code 35 | t.integer :rating # rating # TODO: keep? 36 | t.integer :downloads # number of times this script has been required/loaded (less cache) 37 | t.timestamp :downloaded, :null=>true # date and time of last require/load 38 | t.varchar :modifier # last person to modify the script 39 | t.timestamp :modified # date and time the script was last modified 40 | t.timestamp :created # date and time the script was created 41 | t.integer :copy # id of script from which this script was copied 42 | t.integer :archive # id of the current script; NULL if this is the current script 43 | end 44 | end 45 | 46 | # Drop table from database. 47 | def self.drop_table 48 | database.drop_table(table_name) 49 | end 50 | 51 | # Script save creates a new record in the table, in order to keep a history. 52 | #-- 53 | # TODO: If nothing has changed there is no need to create a new record. 54 | # 55 | # TODO: compressing +code+ and +test+ would save space, but what about searching? 56 | #++ 57 | def save(bump=false) 58 | now = Time.now 59 | 60 | if exists? 61 | if bump 62 | # archive current version 63 | h = self.values.dup 64 | h.delete(:id) 65 | history = self.class.new(h) 66 | history.archive = id 67 | history.save 68 | end 69 | else 70 | self.created = now 71 | end 72 | 73 | if bump 74 | self.version = version.to_i + 1 75 | end 76 | 77 | self.modified = now 78 | 79 | super() 80 | end 81 | 82 | # 83 | #def owner_name 84 | # "#{owner}/#{name}" 85 | #end 86 | 87 | # 88 | def code_highlighted 89 | CodeRay.scan(code, :ruby).div 90 | end 91 | 92 | # 93 | def test_highlighted 94 | CodeRay.scan(test, :ruby).div 95 | end 96 | 97 | # 98 | def track(user_id) 99 | Track[:user_id=>user_id, :owner=>owner, :name=>name] 100 | end 101 | 102 | end 103 | 104 | end 105 | 106 | -------------------------------------------------------------------------------- /lib/live/public/css/screen.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif; 3 | color: #565656; 4 | } 5 | 6 | h1 { font-size: 150%; } 7 | h2 { font-size: 133%; } 8 | h3 { font-size: 125%; } 9 | 10 | #header { 11 | background: url(/img/top.png) repeat-x white; 12 | height: 130px; 13 | padding: 0; 14 | text-align: left; 15 | margin-bottom: 20px; 16 | } 17 | 18 | #content { 19 | margin: 1em; 20 | padding: 1em; 21 | background: #fff; 22 | -moz-border-radius: 3em; 23 | -webkit-border-radius: 3em; 24 | border-radius: 3em; 25 | } 26 | 27 | #footer { 28 | margin: 0; 29 | padding: 20px; 30 | background: url(/img/gradiant-up.jpg) bottom repeat-x #fff; 31 | min-height: 100px; 32 | } 33 | 34 | .page { 35 | width: 960px; 36 | margin: 0 auto; 37 | position: relative; 38 | } 39 | 40 | .flash { 41 | position: absolute; 42 | top: 100px; 43 | width: 100%; 44 | text-align: center; 45 | z-index: 10; 46 | } 47 | 48 | .flash div { 49 | width: 960px; 50 | margin: 0 auto; 51 | -moz-border-radius: 10px; 52 | -webkit-border-radius: 10px; 53 | border-radius: 10px; 54 | background: #111; 55 | opacity: 0.8; 56 | padding: 20px; 57 | color: white; 58 | font-weight: bold; 59 | } 60 | 61 | .monitor { 62 | background: #ccc; 63 | border: 1px solid #ccc; 64 | -moz-border-radius: 5px; 65 | -webkit-border-radius: 5px; 66 | border-radius: 5px; 67 | margin: 20px 0; padding: 20px; 68 | } 69 | 70 | .instructions { 71 | border: 1px solid #ccc; 72 | padding: 5px; 73 | background: #cfc; 74 | color: black; 75 | border: 1px solid #ccc; 76 | -moz-border-radius: 5px; 77 | -webkit-border-radius: 5px; 78 | border-radius: 5px; 79 | } 80 | 81 | .instructions pre { 82 | color #555; 83 | font-weight: bold; 84 | } 85 | 86 | .copyright { 87 | font-size: 0.8em; 88 | font-weight: normal; 89 | } 90 | 91 | .CodeRay { 92 | min-height: 400px; 93 | border: 1px solid #ccc; 94 | padding: 10px; 95 | } 96 | 97 | 98 | 99 | #sign-form td { 100 | padding: 5px 0; 101 | } 102 | 103 | /* INFO */ 104 | 105 | #info { 106 | position: absolute; 107 | right: 0; 108 | top: 10px; 109 | } 110 | 111 | #info .menu { 112 | margin: 0 0 10px 0; 113 | } 114 | 115 | #info a { 116 | font-size: 14px; 117 | font-weight: bold; 118 | padding: 5px; 119 | text-decoration: none; 120 | color: white; 121 | } 122 | 123 | #info a:hover { 124 | background: red; 125 | opacity: 0.8; 126 | -moz-border-radius: 8px; 127 | -webkit-border-radius: 8px; 128 | border-radius: 8px; 129 | } 130 | 131 | #info input { 132 | width: 280px; 133 | padding: 3px; 134 | -moz-border-radius: 8px; 135 | -webkit-border-radius: 8px; 136 | border-radius: 8px; 137 | } 138 | 139 | /* SCRIPT VIEW & EDIT */ 140 | 141 | #script { 142 | 143 | } 144 | 145 | #script .name { 146 | font-weight: bold; 147 | margin: 5px 0; 148 | } 149 | 150 | #script .name a { 151 | font-size: 0.8em; 152 | text-decoration: none; 153 | } 154 | 155 | #script .ruby { 156 | border: 1px solid #ccc; 157 | width: 100%; 158 | min-height: 300px; 159 | padding: 10px; 160 | } 161 | 162 | /* BROWSE & SEARCH */ 163 | 164 | #script-browse a { 165 | font-weight: bold; 166 | text-decoration: none; 167 | } 168 | 169 | #script-browse-index { 170 | padding: 20px; 171 | border: 1px solid #ccc; 172 | margin: 20px 0; 173 | } 174 | 175 | #script-browse-counts { 176 | margin: 20px 0; 177 | } 178 | 179 | #script-browse-list { 180 | padding: 20px; 181 | border: 1px solid #ccc; 182 | } 183 | 184 | #script-browse-list { 185 | padding: 5px; 186 | } 187 | 188 | #script-browse-list li { 189 | margin: 0; 190 | padding: 10px 0; 191 | } 192 | 193 | .labels { 194 | padding: 5px; 195 | color: #565656; 196 | font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif; 197 | } 198 | 199 | -------------------------------------------------------------------------------- /lib/live/public/js/jquery.ui.stars/ui.stars.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI Stars v2.1.1 3 | * http://plugins.jquery.com/project/Star_Rating_widget 4 | * 5 | * Copyright (c) 2009 Orkan (orkans@gmail.com) 6 | * Dual licensed under the MIT and GPL licenses. 7 | * http://docs.jquery.com/License 8 | * 9 | * $Rev: 114 $ 10 | * $Date:: 2009-06-12 #$ 11 | * $Build: 32 (2009-06-12) 12 | * 13 | * Depends: 14 | * ui.core.js 15 | * 16 | */ 17 | (function(A){A.widget("ui.stars",{_init:function(){var B=this,E=this.options,F=0;E.isSelect=E.inputType=="select";this.$form=A(this.element).closest("form");this.$selec=E.isSelect?A("select",this.element):null;this.$rboxs=E.isSelect?A("option",this.$selec):A(":radio",this.element);this.$stars=this.$rboxs.map(function(I){var J={value:this.value,title:(E.isSelect?this.text:this.title)||this.value,isDefault:(E.isSelect&&this.defaultSelected)||this.defaultChecked};if(I==0){E.split=typeof E.split!="number"?0:E.split;E.val2id=[];E.id2val=[];E.id2title=[];E.name=E.isSelect?B.$selec.get(0).name:this.name;E.disabled=E.disabled||(E.isSelect?A(B.$selec).attr("disabled"):A(this).attr("disabled"))}if(J.value==E.cancelValue){E.cancelTitle=J.title;return null}E.val2id[J.value]=F;E.id2val[F]=J.value;E.id2title[F]=J.title;if(J.isDefault){E.checked=F;E.value=E.defaultValue=J.value;E.title=J.title}var H=A("
").addClass(E.starClass);var K=A("").attr("title",E.showTitles?J.title:"").text(J.value);if(E.split){var G=(F%E.split);var L=Math.floor(E.starWidth/E.split);H.width(L);K.css("margin-left","-"+(G*L)+"px")}F++;return H.append(K).get(0)});E.items=F;E.isSelect?this.$selec.remove():this.$rboxs.remove();this.$cancel=A("
").addClass(E.cancelClass).append(A("").attr("title",E.showTitles?E.cancelTitle:"").text(E.cancelValue));E.cancelShow&=!E.disabled&&!E.oneVoteOnly;E.cancelShow&&this.element.append(this.$cancel);this.element.append(this.$stars);if(E.checked===undefined){E.checked=-1;E.value=E.defaultValue=E.cancelValue;E.title=""}this.$value=A('');this.element.append(this.$value);this.$stars.bind("click.stars",function(H){if(!E.forceSelect&&E.disabled){return false}var G=B.$stars.index(this);E.checked=G;E.value=E.id2val[G];E.title=E.id2title[G];B.$value.attr({disabled:E.disabled?"disabled":"",value:E.value});C(G,false);B._disableCancel();!E.forceSelect&&B.callback(H,"star")}).bind("mouseover.stars",function(){if(E.disabled){return false}var G=B.$stars.index(this);C(G,true)}).bind("mouseout.stars",function(){if(E.disabled){return false}C(B.options.checked,false)});this.$cancel.bind("click.stars",function(G){if(!E.forceSelect&&(E.disabled||E.value==E.cancelValue)){return false}E.checked=-1;E.value=E.cancelValue;E.title="";B.$value.val(E.value).attr({disabled:"disabled"});D();B._disableCancel();!E.forceSelect&&B.callback(G,"cancel")}).bind("mouseover.stars",function(){if(B._disableCancel()){return false}B.$cancel.addClass(E.cancelHoverClass);D();B._showCap(E.cancelTitle)}).bind("mouseout.stars",function(){if(B._disableCancel()){return false}B.$cancel.removeClass(E.cancelHoverClass);B.$stars.triggerHandler("mouseout.stars")});this.$form.bind("reset.stars",function(){!E.disabled&&B.select(E.defaultValue)});A(window).unload(function(){B.$cancel.unbind(".stars");B.$stars.unbind(".stars");B.$form.unbind(".stars");B.$selec=B.$rboxs=B.$stars=B.$value=B.$cancel=B.$form=null});function C(G,I){if(G!=-1){var J=I?E.starHoverClass:E.starOnClass;var H=I?E.starOnClass:E.starHoverClass;B.$stars.eq(G).prevAll("."+E.starClass).andSelf().removeClass(H).addClass(J);B.$stars.eq(G).nextAll("."+E.starClass).removeClass(E.starHoverClass+" "+E.starOnClass);B._showCap(E.id2title[G])}else{D()}}function D(){B.$stars.removeClass(E.starOnClass+" "+E.starHoverClass);B._showCap("")}this.select(E.value);E.disabled&&this.disable()},_disableCancel:function(){var C=this.options,B=C.disabled||C.oneVoteOnly||(C.value==C.cancelValue);if(B){this.$cancel.removeClass(C.cancelHoverClass).addClass(C.cancelDisabledClass)}else{this.$cancel.removeClass(C.cancelDisabledClass)}this.$cancel.css("opacity",B?0.5:1);return B},_disableAll:function(){var B=this.options;this._disableCancel();if(B.disabled){this.$stars.filter("div").addClass(B.starDisabledClass)}else{this.$stars.filter("div").removeClass(B.starDisabledClass)}},_showCap:function(B){var C=this.options;if(C.captionEl){C.captionEl.text(B)}},value:function(){return this.options.value},select:function(D){var C=this.options,B=(D==C.cancelValue)?this.$cancel:this.$stars.eq(C.val2id[D]);C.forceSelect=true;B.triggerHandler("click.stars");C.forceSelect=false},selectID:function(D){var C=this.options,B=(D==-1)?this.$cancel:this.$stars.eq(D);C.forceSelect=true;B.triggerHandler("click.stars");C.forceSelect=false},enable:function(){this.options.disabled=false;this._disableAll()},disable:function(){this.options.disabled=true;this._disableAll()},destroy:function(){this.options.isSelect?this.$selec.appendTo(this.element):this.$rboxs.appendTo(this.element);this.$form.unbind(".stars");this.$cancel.unbind(".stars").remove();this.$stars.unbind(".stars").remove();this.$value.remove();this.element.unbind(".stars").removeData("stars")},callback:function(C,B){var D=this.options;D.callback&&D.callback(this,B,D.value,C);D.oneVoteOnly&&!D.disabled&&this.disable()}});A.extend(A.ui.stars,{version:"2.1.1",getter:"value",defaults:{inputType:"radio",split:0,disabled:false,cancelTitle:"Cancel Rating",cancelValue:0,cancelShow:true,oneVoteOnly:false,showTitles:false,captionEl:null,callback:null,starWidth:16,cancelClass:"ui-stars-cancel",starClass:"ui-stars-star",starOnClass:"ui-stars-star-on",starHoverClass:"ui-stars-star-hover",starDisabledClass:"ui-stars-star-disabled",cancelHoverClass:"ui-stars-cancel-hover",cancelDisabledClass:"ui-stars-cancel-disabled"}})})(jQuery); -------------------------------------------------------------------------------- /lib/live/server.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra/base' 2 | #require 'sinatra_warden' 3 | require 'rack/flash' 4 | require 'live/auth' 5 | 6 | module Live 7 | 8 | # = Facets Live! Sinatra-based Server 9 | # 10 | class Server < Sinatra::Base 11 | enable :sessions #use Rack::Session::Cookie 12 | use Rack::Flash 13 | 14 | include Authentication 15 | 16 | set :root, File.dirname(__FILE__) 17 | set :static, true 18 | 19 | # 20 | get '/' do 21 | @scripts_newest = Script.newest 22 | @scripts_latest = Script.latest 23 | @scripts_popular = Script.popular 24 | erb :index 25 | end 26 | 27 | # Sign up for new account. 28 | get '/register' do 29 | @title = "Sign Up" 30 | erb :register 31 | end 32 | 33 | # Sign up for new account. 34 | post '/register' do 35 | if params[:password] != params[:confirm] 36 | flash[:message] = "Oops! Could not confirm password." 37 | redirect(back) 38 | end 39 | 40 | @user = ::User.new 41 | 42 | @user.username = params[:username] 43 | @user.name = params[:name] 44 | @user.email = params[:email] 45 | @user.website = params[:website] 46 | 47 | @user.salt = Digest::SHA1.hexdigest("--#{Time.now.to_f}--#{@user.email}--") 48 | 49 | @user.password = params[:password] 50 | 51 | if @user.save 52 | flash[:message] = 'Account created. Please sign-in.' 53 | redirect '/' #MainController.r(:index) 54 | end 55 | end 56 | 57 | get '/profile' do 58 | authorize!('/login') 59 | @title = 'Profile' 60 | erb :profile 61 | end 62 | 63 | # 64 | post '/profile' do 65 | authorize!('/login') 66 | 67 | if params[:password] != params[:confirm] 68 | flash[:message] = "Oops! Could not confirm new password." 69 | redirect(back) 70 | end 71 | 72 | user.name = params[:name] 73 | user.email = params[:email] 74 | user.website = params[:website] 75 | 76 | user.username = params[:username] # TODO: remove 77 | user.password = params[:password] if params[:password] && !params[:password].empty? 78 | 79 | if user.save 80 | flash[:message] = 'Profile saved' 81 | redirect "/dashboard" 82 | end 83 | end 84 | 85 | # 86 | get '/login' do 87 | redirect(back) if authorized? 88 | @title = "Sign In" 89 | erb :login 90 | end 91 | 92 | # 93 | post '/login' do 94 | if authorized? 95 | flash[:message] = "Signed In" # TODO: NOT WORKING 96 | redirect '/dashboard' 97 | else 98 | @title = "Sign In" 99 | flash[:message] = "Invalid Credentials" 100 | erb :login 101 | end 102 | end 103 | 104 | # 105 | get '/logout' do 106 | self.user = nil 107 | flash[:message] = "Signed Out" 108 | redirect '/' 109 | end 110 | 111 | # 112 | post '/search' do 113 | @title = "Search" 114 | @criteria = params[:criteria] 115 | if @criteria 116 | @scripts = Script.filter(:archive => nil, :name => /^#{@criteria}/i).order(:name).limit(25) 117 | else 118 | redirect '/browse/A' 119 | end 120 | erb :browse 121 | end 122 | 123 | # 124 | get '/browse/:letter' do 125 | @title = "Browse" 126 | @letter = params[:letter] 127 | if @letter 128 | @scripts = Script.filter(:archive => nil, :name => /^#{@letter}/i).order(:name).limit(25) 129 | else 130 | @scripts = Script.filter(:archive => nil).order(:name).limit(25) 131 | end 132 | erb :browse 133 | end 134 | 135 | # 136 | get '/dashboard' do 137 | authorize!('/login') # must be logged-in 138 | 139 | @title = "Dashboard" 140 | @scripts = Script.filter(:archive => nil, :owner => user.username) 141 | @watchlist = Track.filter(:user_id => user_id, :watch => true) #.limit(20) #paginate? 142 | 143 | erb :dashboard 144 | end 145 | 146 | # 147 | get '/script/:id' do 148 | id = params[:id] 149 | @script = Script[:id=>id] 150 | @track = Track[:user_id=>user_id, :owner=>@script.owner, :name=>@script.name] 151 | erb :script 152 | end 153 | 154 | # 155 | get '/script/:owner/:name' do 156 | owner = params[:owner] 157 | name = params[:name] 158 | @script = Script[:archive=>nil, :owner=>owner, :name=>name] 159 | @track = Track[:user_id=>user_id, :owner=>@script.owner, :name=>@script.name] 160 | erb :script 161 | end 162 | 163 | # 164 | get '/copy/:id/:name' do 165 | authorize!('/login') 166 | 167 | id = params[:id] 168 | name = params[:name] 169 | 170 | script = Script[:name=>name,:owner=>user.username] 171 | if script 172 | flash[:message] = "ERROR! You already have a script named '#{name}'." 173 | redirect(back) 174 | else 175 | orig = Script[:id=>id] 176 | vals = orig.values.dup 177 | vals.delete(:id) 178 | copy = Script.create(vals) 179 | copy.name = name 180 | copy.owner = user.username 181 | copy.version = 1 182 | copy.copy = orig.id 183 | copy.rating = 0 184 | copy.downloads = 0 185 | copy.downloaded = Time.now #nil 186 | copy.created = Time.now 187 | copy.archive = nil 188 | copy.save 189 | @script = copy 190 | erb :edit 191 | end 192 | end 193 | 194 | # Create new script. 195 | get '/edit' do 196 | authorize!('/login') 197 | 198 | @script = Script.new(:owner=>user.username, :modifier=>user.username, :modified=>Time.now) 199 | erb :edit 200 | end 201 | 202 | # Edit script. 203 | get '/edit/:id' do 204 | authorize!('/login') 205 | 206 | id = params[:id] 207 | 208 | @script = Script[:id=>id] 209 | 210 | if user.username != @script.owner 211 | flash[:message] = "Unathorized Access!" 212 | redirect(back) 213 | else 214 | erb :edit 215 | end 216 | end 217 | 218 | # 219 | post '/edit' do 220 | authorize!('/login') 221 | 222 | id = params[:id] 223 | if id.empty? 224 | @script = Script.new(:owner=>user.username, :modifier=>user.username, :modified=>Time.now) 225 | else 226 | @script = Script[:id=>id] 227 | if user.username != @script.owner 228 | flash[:message] = "Unathorized Access!" 229 | redirect(back) 230 | end 231 | end 232 | 233 | @script[:name] = params[:name] if @script.new? 234 | @script[:code] = params[:code] 235 | @script[:test] = params[:test] 236 | @script[:description] = params[:desc] 237 | 238 | @script[:modifier] = user.username 239 | 240 | bump = (params[:bump] == 'true' ? true : false) 241 | 242 | if @script.save(bump) 243 | flash[:message] = 'Script saved' 244 | redirect "/script/#{@script.id}" 245 | else 246 | flash[:message] = 'Script error!' 247 | redirect "/edit" 248 | end 249 | end 250 | 251 | # 252 | get '/watch/:owner/:name' do 253 | authorize!('/login') 254 | 255 | owner = params[:owner] 256 | name = params[:name] 257 | track = Track[:user_id=>user_id, :owner=>owner, :name=>name] 258 | unless track 259 | track = Track.new(:user_id=>user_id, :owner=>owner, :name=>name) 260 | end 261 | track.watch = true 262 | track.save 263 | redirect(back) 264 | end 265 | 266 | # 267 | get '/unwatch/:owner/:name' do 268 | authorize!('/login') 269 | 270 | owner = params[:owner] 271 | name = params[:name] 272 | track = Track[:user_id=>user_id, :owner=>owner, :name=>name] 273 | unless track 274 | track = Track.new(:user_id=>user_id, :owner=>owner, :name=>name) 275 | end 276 | track.watch = false 277 | track.save 278 | redirect(back) 279 | end 280 | 281 | # 282 | get '/star/:id' do 283 | authorize!('/login') 284 | 285 | id = params[:id] 286 | 287 | script = Script[:id=>id] 288 | track = script.track(user_id) 289 | #track = Track[:user_id=>user_id, :owner=>script.owner, :name=>script.name] 290 | unless track 291 | track = Track.new(:user_id=>user_id, :owner=>script.owner, :name=>script.name) 292 | end 293 | 294 | track.star = !track.star 295 | track.save 296 | 297 | 'Starred!' 298 | end 299 | 300 | # 301 | get '/flag/:id' do 302 | authorize!('/login') 303 | 304 | id = params[:id] 305 | 306 | script = Script[:id=>id] 307 | track = script.track(user_id) 308 | #track = Track[:user_id=>user_id, :owner=>script.owner, :name=>script.name] 309 | unless track 310 | track = Track.new(:user_id=>user_id, :owner=>script.owner, :name=>script.name) 311 | end 312 | 313 | track.flag = !track.flag 314 | track.save 315 | 316 | 'Flagged!' 317 | end 318 | 319 | # 320 | get '/require/:user/:name' do 321 | user = params[:user] 322 | name = params[:name] 323 | Script[:user=>user, :name=>name, :archive=>nil].code 324 | end 325 | 326 | # 327 | get '/require/:user/:name/:vers' do 328 | user = params[:user] 329 | name = params[:name] 330 | vers = params[:vers] 331 | Script[:user=>user, :name=>name, :vers=>vers].code 332 | end 333 | 334 | #post '/set-flash' do 335 | # # Set a flash entry 336 | # flash[:notice] = "Thanks for signing up!" 337 | # 338 | # # Get a flash entry 339 | # flash[:notice] # => "Thanks for signing up!" 340 | # 341 | # # Set a flash entry for only the current request 342 | # flash.now[:notice] = "Thanks for signing up!" 343 | #end 344 | end 345 | 346 | end 347 | 348 | -------------------------------------------------------------------------------- /lib/live/public/js/jquery.ui.stars/ui.stars.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery UI Stars v2.1.1 3 | * http://plugins.jquery.com/project/Star_Rating_widget 4 | * 5 | * Copyright (c) 2009 Orkan (orkans@gmail.com) 6 | * Dual licensed under the MIT and GPL licenses. 7 | * http://docs.jquery.com/License 8 | * 9 | * $Rev: 114 $ 10 | * $Date:: 2009-06-12 #$ 11 | * $Build: 32 (2009-06-12) 12 | * 13 | * Depends: 14 | * ui.core.js 15 | * 16 | */ 17 | (function($) { 18 | 19 | $.widget("ui.stars", 20 | { 21 | _init: function() { 22 | var self = this, o = this.options, id = 0; 23 | 24 | o.isSelect = o.inputType == "select"; 25 | this.$form = $(this.element).closest("form"); 26 | this.$selec = o.isSelect ? $("select", this.element) : null; 27 | this.$rboxs = o.isSelect ? $("option", this.$selec) : $(":radio", this.element); 28 | 29 | /* 30 | * Map all inputs from $rboxs array to Stars elements 31 | */ 32 | this.$stars = this.$rboxs.map(function(i) 33 | { 34 | var el = { 35 | value: this.value, 36 | title: (o.isSelect ? this.text : this.title) || this.value, 37 | isDefault: (o.isSelect && this.defaultSelected) || this.defaultChecked 38 | }; 39 | 40 | if(i==0) { 41 | o.split = typeof o.split != "number" ? 0 : o.split; 42 | o.val2id = []; 43 | o.id2val = []; 44 | o.id2title = []; 45 | o.name = o.isSelect ? self.$selec.get(0).name : this.name; 46 | o.disabled = o.disabled || (o.isSelect ? $(self.$selec).attr("disabled") : $(this).attr("disabled")); 47 | } 48 | 49 | /* 50 | * Consider it as a Cancel button? 51 | */ 52 | if(el.value == o.cancelValue) { 53 | o.cancelTitle = el.title; 54 | return null; 55 | } 56 | 57 | o.val2id[el.value] = id; 58 | o.id2val[id] = el.value; 59 | o.id2title[id] = el.title; 60 | 61 | if(el.isDefault) { 62 | o.checked = id; 63 | o.value = o.defaultValue = el.value; 64 | o.title = el.title; 65 | } 66 | 67 | var $s = $("
").addClass(o.starClass); 68 | var $a = $('').attr("title", o.showTitles ? el.title : "").text(el.value); 69 | 70 | /* 71 | * Prepare division settings 72 | */ 73 | if(o.split) { 74 | var oddeven = (id % o.split); 75 | var stwidth = Math.floor(o.starWidth / o.split); 76 | $s.width(stwidth); 77 | $a.css("margin-left", "-" + (oddeven * stwidth) + "px"); 78 | } 79 | 80 | id++; 81 | return $s.append($a).get(0); 82 | }); 83 | 84 | /* 85 | * How many Stars? 86 | */ 87 | o.items = id; 88 | 89 | /* 90 | * Remove old content 91 | */ 92 | o.isSelect ? this.$selec.remove() : this.$rboxs.remove(); 93 | 94 | /* 95 | * Append Stars interface 96 | */ 97 | this.$cancel = $("
").addClass(o.cancelClass).append( $("").attr("title", o.showTitles ? o.cancelTitle : "").text(o.cancelValue) ); 98 | o.cancelShow &= !o.disabled && !o.oneVoteOnly; 99 | o.cancelShow && this.element.append(this.$cancel); 100 | this.element.append(this.$stars); 101 | 102 | /* 103 | * Initial selection 104 | */ 105 | if(o.checked === undefined) { 106 | o.checked = -1; 107 | o.value = o.defaultValue = o.cancelValue; 108 | o.title = ""; 109 | } 110 | 111 | this.$value = $(''); 112 | this.element.append(this.$value); 113 | 114 | 115 | /* 116 | * Attach stars event handler 117 | */ 118 | this.$stars.bind("click.stars", function(e) { 119 | if(!o.forceSelect && o.disabled) return false; 120 | 121 | var i = self.$stars.index(this); 122 | o.checked = i; 123 | o.value = o.id2val[i]; 124 | o.title = o.id2title[i]; 125 | self.$value.attr({disabled: o.disabled ? "disabled" : "", value: o.value}); 126 | 127 | fillTo(i, false); 128 | self._disableCancel(); 129 | 130 | !o.forceSelect && self.callback(e, "star"); 131 | }) 132 | .bind("mouseover.stars", function() { 133 | if(o.disabled) return false; 134 | var i = self.$stars.index(this); 135 | fillTo(i, true); 136 | }) 137 | .bind("mouseout.stars", function() { 138 | if(o.disabled) return false; 139 | fillTo(self.options.checked, false); 140 | }); 141 | 142 | 143 | /* 144 | * Attach cancel event handler 145 | */ 146 | this.$cancel.bind("click.stars", function(e) { 147 | if(!o.forceSelect && (o.disabled || o.value == o.cancelValue)) return false; 148 | 149 | o.checked = -1; 150 | o.value = o.cancelValue; 151 | o.title = ""; 152 | self.$value.val(o.value).attr({disabled: "disabled"}); 153 | 154 | fillNone(); 155 | self._disableCancel(); 156 | 157 | !o.forceSelect && self.callback(e, "cancel"); 158 | }) 159 | .bind("mouseover.stars", function() { 160 | if(self._disableCancel()) return false; 161 | self.$cancel.addClass(o.cancelHoverClass); 162 | fillNone(); 163 | self._showCap(o.cancelTitle); 164 | }) 165 | .bind("mouseout.stars", function() { 166 | if(self._disableCancel()) return false; 167 | self.$cancel.removeClass(o.cancelHoverClass); 168 | self.$stars.triggerHandler("mouseout.stars"); 169 | }); 170 | 171 | 172 | /* 173 | * Attach onReset event handler to the parent FORM 174 | */ 175 | this.$form.bind("reset.stars", function(){ 176 | !o.disabled && self.select(o.defaultValue); 177 | }); 178 | 179 | 180 | /* 181 | * Clean up to avoid memory leaks in certain versions of IE 6 182 | */ 183 | $(window).unload(function(){ 184 | self.$cancel.unbind(".stars"); 185 | self.$stars.unbind(".stars"); 186 | self.$form.unbind(".stars"); 187 | self.$selec = self.$rboxs = self.$stars = self.$value = self.$cancel = self.$form = null; 188 | }); 189 | 190 | 191 | /* 192 | * Star selection helpers 193 | */ 194 | function fillTo(index, hover) { 195 | if(index != -1) { 196 | var addClass = hover ? o.starHoverClass : o.starOnClass; 197 | var remClass = hover ? o.starOnClass : o.starHoverClass; 198 | self.$stars.eq(index).prevAll("." + o.starClass).andSelf().removeClass(remClass).addClass(addClass); 199 | self.$stars.eq(index).nextAll("." + o.starClass).removeClass(o.starHoverClass + " " + o.starOnClass); 200 | self._showCap(o.id2title[index]); 201 | } 202 | else fillNone(); 203 | }; 204 | function fillNone() { 205 | self.$stars.removeClass(o.starOnClass + " " + o.starHoverClass); 206 | self._showCap(""); 207 | }; 208 | 209 | 210 | /* 211 | * Finally, set up the Stars 212 | */ 213 | this.select(o.value); 214 | o.disabled && this.disable(); 215 | 216 | }, 217 | 218 | /* 219 | * Private functions 220 | */ 221 | _disableCancel: function() { 222 | var o = this.options, disabled = o.disabled || o.oneVoteOnly || (o.value == o.cancelValue); 223 | if(disabled) this.$cancel.removeClass(o.cancelHoverClass).addClass(o.cancelDisabledClass); 224 | else this.$cancel.removeClass(o.cancelDisabledClass); 225 | this.$cancel.css("opacity", disabled ? 0.5 : 1); 226 | return disabled; 227 | }, 228 | _disableAll: function() { 229 | var o = this.options; 230 | this._disableCancel(); 231 | if(o.disabled) this.$stars.filter("div").addClass(o.starDisabledClass); 232 | else this.$stars.filter("div").removeClass(o.starDisabledClass); 233 | }, 234 | _showCap: function(s) { 235 | var o = this.options; 236 | if(o.captionEl) o.captionEl.text(s); 237 | }, 238 | 239 | /* 240 | * Public functions 241 | */ 242 | value: function() { 243 | return this.options.value; 244 | }, 245 | select: function(val) { 246 | var o = this.options, e = (val == o.cancelValue) ? this.$cancel : this.$stars.eq(o.val2id[val]); 247 | o.forceSelect = true; 248 | e.triggerHandler("click.stars"); 249 | o.forceSelect = false; 250 | }, 251 | selectID: function(id) { 252 | var o = this.options, e = (id == -1) ? this.$cancel : this.$stars.eq(id); 253 | o.forceSelect = true; 254 | e.triggerHandler("click.stars"); 255 | o.forceSelect = false; 256 | }, 257 | enable: function() { 258 | this.options.disabled = false; 259 | this._disableAll(); 260 | }, 261 | disable: function() { 262 | this.options.disabled = true; 263 | this._disableAll(); 264 | }, 265 | destroy: function() { 266 | this.options.isSelect ? this.$selec.appendTo(this.element) : this.$rboxs.appendTo(this.element); 267 | this.$form.unbind(".stars"); 268 | this.$cancel.unbind(".stars").remove(); 269 | this.$stars.unbind(".stars").remove(); 270 | this.$value.remove(); 271 | this.element.unbind(".stars").removeData("stars"); 272 | }, 273 | callback: function(e, type) { 274 | var o = this.options; 275 | o.callback && o.callback(this, type, o.value, e); 276 | o.oneVoteOnly && !o.disabled && this.disable(); 277 | } 278 | }); 279 | 280 | $.extend($.ui.stars, { 281 | version: "2.1.1", 282 | getter: "value", 283 | defaults: { 284 | inputType: "radio", // radio|select 285 | split: 0, 286 | disabled: false, 287 | cancelTitle: "Cancel Rating", 288 | cancelValue: 0, 289 | cancelShow: true, 290 | oneVoteOnly: false, 291 | showTitles: false, 292 | captionEl: null, 293 | callback: null, // function(ui, type, value, event) 294 | 295 | /* 296 | * CSS classes 297 | */ 298 | starWidth: 16, 299 | cancelClass: 'ui-stars-cancel', 300 | starClass: 'ui-stars-star', 301 | starOnClass: 'ui-stars-star-on', 302 | starHoverClass: 'ui-stars-star-hover', 303 | starDisabledClass: 'ui-stars-star-disabled', 304 | cancelHoverClass: 'ui-stars-cancel-hover', 305 | cancelDisabledClass: 'ui-stars-cancel-disabled' 306 | } 307 | }); 308 | 309 | })(jQuery); 310 | -------------------------------------------------------------------------------- /lib/live/public/js/jquery.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery JavaScript Library v1.3.2 3 | * http://jquery.com/ 4 | * 5 | * Copyright (c) 2009 John Resig 6 | * Dual licensed under the MIT and GPL licenses. 7 | * http://docs.jquery.com/License 8 | * 9 | * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) 10 | * Revision: 6246 11 | */ 12 | (function(){ 13 | 14 | var 15 | // Will speed up references to window, and allows munging its name. 16 | window = this, 17 | // Will speed up references to undefined, and allows munging its name. 18 | undefined, 19 | // Map over jQuery in case of overwrite 20 | _jQuery = window.jQuery, 21 | // Map over the $ in case of overwrite 22 | _$ = window.$, 23 | 24 | jQuery = window.jQuery = window.$ = function( selector, context ) { 25 | // The jQuery object is actually just the init constructor 'enhanced' 26 | return new jQuery.fn.init( selector, context ); 27 | }, 28 | 29 | // A simple way to check for HTML strings or ID strings 30 | // (both of which we optimize for) 31 | quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/, 32 | // Is it a simple selector 33 | isSimple = /^.[^:#\[\.,]*$/; 34 | 35 | jQuery.fn = jQuery.prototype = { 36 | init: function( selector, context ) { 37 | // Make sure that a selection was provided 38 | selector = selector || document; 39 | 40 | // Handle $(DOMElement) 41 | if ( selector.nodeType ) { 42 | this[0] = selector; 43 | this.length = 1; 44 | this.context = selector; 45 | return this; 46 | } 47 | // Handle HTML strings 48 | if ( typeof selector === "string" ) { 49 | // Are we dealing with HTML string or an ID? 50 | var match = quickExpr.exec( selector ); 51 | 52 | // Verify a match, and that no context was specified for #id 53 | if ( match && (match[1] || !context) ) { 54 | 55 | // HANDLE: $(html) -> $(array) 56 | if ( match[1] ) 57 | selector = jQuery.clean( [ match[1] ], context ); 58 | 59 | // HANDLE: $("#id") 60 | else { 61 | var elem = document.getElementById( match[3] ); 62 | 63 | // Handle the case where IE and Opera return items 64 | // by name instead of ID 65 | if ( elem && elem.id != match[3] ) 66 | return jQuery().find( selector ); 67 | 68 | // Otherwise, we inject the element directly into the jQuery object 69 | var ret = jQuery( elem || [] ); 70 | ret.context = document; 71 | ret.selector = selector; 72 | return ret; 73 | } 74 | 75 | // HANDLE: $(expr, [context]) 76 | // (which is just equivalent to: $(content).find(expr) 77 | } else 78 | return jQuery( context ).find( selector ); 79 | 80 | // HANDLE: $(function) 81 | // Shortcut for document ready 82 | } else if ( jQuery.isFunction( selector ) ) 83 | return jQuery( document ).ready( selector ); 84 | 85 | // Make sure that old selector state is passed along 86 | if ( selector.selector && selector.context ) { 87 | this.selector = selector.selector; 88 | this.context = selector.context; 89 | } 90 | 91 | return this.setArray(jQuery.isArray( selector ) ? 92 | selector : 93 | jQuery.makeArray(selector)); 94 | }, 95 | 96 | // Start with an empty selector 97 | selector: "", 98 | 99 | // The current version of jQuery being used 100 | jquery: "1.3.2", 101 | 102 | // The number of elements contained in the matched element set 103 | size: function() { 104 | return this.length; 105 | }, 106 | 107 | // Get the Nth element in the matched element set OR 108 | // Get the whole matched element set as a clean array 109 | get: function( num ) { 110 | return num === undefined ? 111 | 112 | // Return a 'clean' array 113 | Array.prototype.slice.call( this ) : 114 | 115 | // Return just the object 116 | this[ num ]; 117 | }, 118 | 119 | // Take an array of elements and push it onto the stack 120 | // (returning the new matched element set) 121 | pushStack: function( elems, name, selector ) { 122 | // Build a new jQuery matched element set 123 | var ret = jQuery( elems ); 124 | 125 | // Add the old object onto the stack (as a reference) 126 | ret.prevObject = this; 127 | 128 | ret.context = this.context; 129 | 130 | if ( name === "find" ) 131 | ret.selector = this.selector + (this.selector ? " " : "") + selector; 132 | else if ( name ) 133 | ret.selector = this.selector + "." + name + "(" + selector + ")"; 134 | 135 | // Return the newly-formed element set 136 | return ret; 137 | }, 138 | 139 | // Force the current matched set of elements to become 140 | // the specified array of elements (destroying the stack in the process) 141 | // You should use pushStack() in order to do this, but maintain the stack 142 | setArray: function( elems ) { 143 | // Resetting the length to 0, then using the native Array push 144 | // is a super-fast way to populate an object with array-like properties 145 | this.length = 0; 146 | Array.prototype.push.apply( this, elems ); 147 | 148 | return this; 149 | }, 150 | 151 | // Execute a callback for every element in the matched set. 152 | // (You can seed the arguments with an array of args, but this is 153 | // only used internally.) 154 | each: function( callback, args ) { 155 | return jQuery.each( this, callback, args ); 156 | }, 157 | 158 | // Determine the position of an element within 159 | // the matched set of elements 160 | index: function( elem ) { 161 | // Locate the position of the desired element 162 | return jQuery.inArray( 163 | // If it receives a jQuery object, the first element is used 164 | elem && elem.jquery ? elem[0] : elem 165 | , this ); 166 | }, 167 | 168 | attr: function( name, value, type ) { 169 | var options = name; 170 | 171 | // Look for the case where we're accessing a style value 172 | if ( typeof name === "string" ) 173 | if ( value === undefined ) 174 | return this[0] && jQuery[ type || "attr" ]( this[0], name ); 175 | 176 | else { 177 | options = {}; 178 | options[ name ] = value; 179 | } 180 | 181 | // Check to see if we're setting style values 182 | return this.each(function(i){ 183 | // Set all the styles 184 | for ( name in options ) 185 | jQuery.attr( 186 | type ? 187 | this.style : 188 | this, 189 | name, jQuery.prop( this, options[ name ], type, i, name ) 190 | ); 191 | }); 192 | }, 193 | 194 | css: function( key, value ) { 195 | // ignore negative width and height values 196 | if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) 197 | value = undefined; 198 | return this.attr( key, value, "curCSS" ); 199 | }, 200 | 201 | text: function( text ) { 202 | if ( typeof text !== "object" && text != null ) 203 | return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); 204 | 205 | var ret = ""; 206 | 207 | jQuery.each( text || this, function(){ 208 | jQuery.each( this.childNodes, function(){ 209 | if ( this.nodeType != 8 ) 210 | ret += this.nodeType != 1 ? 211 | this.nodeValue : 212 | jQuery.fn.text( [ this ] ); 213 | }); 214 | }); 215 | 216 | return ret; 217 | }, 218 | 219 | wrapAll: function( html ) { 220 | if ( this[0] ) { 221 | // The elements to wrap the target around 222 | var wrap = jQuery( html, this[0].ownerDocument ).clone(); 223 | 224 | if ( this[0].parentNode ) 225 | wrap.insertBefore( this[0] ); 226 | 227 | wrap.map(function(){ 228 | var elem = this; 229 | 230 | while ( elem.firstChild ) 231 | elem = elem.firstChild; 232 | 233 | return elem; 234 | }).append(this); 235 | } 236 | 237 | return this; 238 | }, 239 | 240 | wrapInner: function( html ) { 241 | return this.each(function(){ 242 | jQuery( this ).contents().wrapAll( html ); 243 | }); 244 | }, 245 | 246 | wrap: function( html ) { 247 | return this.each(function(){ 248 | jQuery( this ).wrapAll( html ); 249 | }); 250 | }, 251 | 252 | append: function() { 253 | return this.domManip(arguments, true, function(elem){ 254 | if (this.nodeType == 1) 255 | this.appendChild( elem ); 256 | }); 257 | }, 258 | 259 | prepend: function() { 260 | return this.domManip(arguments, true, function(elem){ 261 | if (this.nodeType == 1) 262 | this.insertBefore( elem, this.firstChild ); 263 | }); 264 | }, 265 | 266 | before: function() { 267 | return this.domManip(arguments, false, function(elem){ 268 | this.parentNode.insertBefore( elem, this ); 269 | }); 270 | }, 271 | 272 | after: function() { 273 | return this.domManip(arguments, false, function(elem){ 274 | this.parentNode.insertBefore( elem, this.nextSibling ); 275 | }); 276 | }, 277 | 278 | end: function() { 279 | return this.prevObject || jQuery( [] ); 280 | }, 281 | 282 | // For internal use only. 283 | // Behaves like an Array's method, not like a jQuery method. 284 | push: [].push, 285 | sort: [].sort, 286 | splice: [].splice, 287 | 288 | find: function( selector ) { 289 | if ( this.length === 1 ) { 290 | var ret = this.pushStack( [], "find", selector ); 291 | ret.length = 0; 292 | jQuery.find( selector, this[0], ret ); 293 | return ret; 294 | } else { 295 | return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){ 296 | return jQuery.find( selector, elem ); 297 | })), "find", selector ); 298 | } 299 | }, 300 | 301 | clone: function( events ) { 302 | // Do the clone 303 | var ret = this.map(function(){ 304 | if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) { 305 | // IE copies events bound via attachEvent when 306 | // using cloneNode. Calling detachEvent on the 307 | // clone will also remove the events from the orignal 308 | // In order to get around this, we use innerHTML. 309 | // Unfortunately, this means some modifications to 310 | // attributes in IE that are actually only stored 311 | // as properties will not be copied (such as the 312 | // the name attribute on an input). 313 | var html = this.outerHTML; 314 | if ( !html ) { 315 | var div = this.ownerDocument.createElement("div"); 316 | div.appendChild( this.cloneNode(true) ); 317 | html = div.innerHTML; 318 | } 319 | 320 | return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0]; 321 | } else 322 | return this.cloneNode(true); 323 | }); 324 | 325 | // Copy the events from the original to the clone 326 | if ( events === true ) { 327 | var orig = this.find("*").andSelf(), i = 0; 328 | 329 | ret.find("*").andSelf().each(function(){ 330 | if ( this.nodeName !== orig[i].nodeName ) 331 | return; 332 | 333 | var events = jQuery.data( orig[i], "events" ); 334 | 335 | for ( var type in events ) { 336 | for ( var handler in events[ type ] ) { 337 | jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); 338 | } 339 | } 340 | 341 | i++; 342 | }); 343 | } 344 | 345 | // Return the cloned set 346 | return ret; 347 | }, 348 | 349 | filter: function( selector ) { 350 | return this.pushStack( 351 | jQuery.isFunction( selector ) && 352 | jQuery.grep(this, function(elem, i){ 353 | return selector.call( elem, i ); 354 | }) || 355 | 356 | jQuery.multiFilter( selector, jQuery.grep(this, function(elem){ 357 | return elem.nodeType === 1; 358 | }) ), "filter", selector ); 359 | }, 360 | 361 | closest: function( selector ) { 362 | var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null, 363 | closer = 0; 364 | 365 | return this.map(function(){ 366 | var cur = this; 367 | while ( cur && cur.ownerDocument ) { 368 | if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) { 369 | jQuery.data(cur, "closest", closer); 370 | return cur; 371 | } 372 | cur = cur.parentNode; 373 | closer++; 374 | } 375 | }); 376 | }, 377 | 378 | not: function( selector ) { 379 | if ( typeof selector === "string" ) 380 | // test special case where just one selector is passed in 381 | if ( isSimple.test( selector ) ) 382 | return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector ); 383 | else 384 | selector = jQuery.multiFilter( selector, this ); 385 | 386 | var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; 387 | return this.filter(function() { 388 | return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; 389 | }); 390 | }, 391 | 392 | add: function( selector ) { 393 | return this.pushStack( jQuery.unique( jQuery.merge( 394 | this.get(), 395 | typeof selector === "string" ? 396 | jQuery( selector ) : 397 | jQuery.makeArray( selector ) 398 | ))); 399 | }, 400 | 401 | is: function( selector ) { 402 | return !!selector && jQuery.multiFilter( selector, this ).length > 0; 403 | }, 404 | 405 | hasClass: function( selector ) { 406 | return !!selector && this.is( "." + selector ); 407 | }, 408 | 409 | val: function( value ) { 410 | if ( value === undefined ) { 411 | var elem = this[0]; 412 | 413 | if ( elem ) { 414 | if( jQuery.nodeName( elem, 'option' ) ) 415 | return (elem.attributes.value || {}).specified ? elem.value : elem.text; 416 | 417 | // We need to handle select boxes special 418 | if ( jQuery.nodeName( elem, "select" ) ) { 419 | var index = elem.selectedIndex, 420 | values = [], 421 | options = elem.options, 422 | one = elem.type == "select-one"; 423 | 424 | // Nothing was selected 425 | if ( index < 0 ) 426 | return null; 427 | 428 | // Loop through all the selected options 429 | for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { 430 | var option = options[ i ]; 431 | 432 | if ( option.selected ) { 433 | // Get the specifc value for the option 434 | value = jQuery(option).val(); 435 | 436 | // We don't need an array for one selects 437 | if ( one ) 438 | return value; 439 | 440 | // Multi-Selects return an array 441 | values.push( value ); 442 | } 443 | } 444 | 445 | return values; 446 | } 447 | 448 | // Everything else, we just grab the value 449 | return (elem.value || "").replace(/\r/g, ""); 450 | 451 | } 452 | 453 | return undefined; 454 | } 455 | 456 | if ( typeof value === "number" ) 457 | value += ''; 458 | 459 | return this.each(function(){ 460 | if ( this.nodeType != 1 ) 461 | return; 462 | 463 | if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) ) 464 | this.checked = (jQuery.inArray(this.value, value) >= 0 || 465 | jQuery.inArray(this.name, value) >= 0); 466 | 467 | else if ( jQuery.nodeName( this, "select" ) ) { 468 | var values = jQuery.makeArray(value); 469 | 470 | jQuery( "option", this ).each(function(){ 471 | this.selected = (jQuery.inArray( this.value, values ) >= 0 || 472 | jQuery.inArray( this.text, values ) >= 0); 473 | }); 474 | 475 | if ( !values.length ) 476 | this.selectedIndex = -1; 477 | 478 | } else 479 | this.value = value; 480 | }); 481 | }, 482 | 483 | html: function( value ) { 484 | return value === undefined ? 485 | (this[0] ? 486 | this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") : 487 | null) : 488 | this.empty().append( value ); 489 | }, 490 | 491 | replaceWith: function( value ) { 492 | return this.after( value ).remove(); 493 | }, 494 | 495 | eq: function( i ) { 496 | return this.slice( i, +i + 1 ); 497 | }, 498 | 499 | slice: function() { 500 | return this.pushStack( Array.prototype.slice.apply( this, arguments ), 501 | "slice", Array.prototype.slice.call(arguments).join(",") ); 502 | }, 503 | 504 | map: function( callback ) { 505 | return this.pushStack( jQuery.map(this, function(elem, i){ 506 | return callback.call( elem, i, elem ); 507 | })); 508 | }, 509 | 510 | andSelf: function() { 511 | return this.add( this.prevObject ); 512 | }, 513 | 514 | domManip: function( args, table, callback ) { 515 | if ( this[0] ) { 516 | var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(), 517 | scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ), 518 | first = fragment.firstChild; 519 | 520 | if ( first ) 521 | for ( var i = 0, l = this.length; i < l; i++ ) 522 | callback.call( root(this[i], first), this.length > 1 || i > 0 ? 523 | fragment.cloneNode(true) : fragment ); 524 | 525 | if ( scripts ) 526 | jQuery.each( scripts, evalScript ); 527 | } 528 | 529 | return this; 530 | 531 | function root( elem, cur ) { 532 | return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ? 533 | (elem.getElementsByTagName("tbody")[0] || 534 | elem.appendChild(elem.ownerDocument.createElement("tbody"))) : 535 | elem; 536 | } 537 | } 538 | }; 539 | 540 | // Give the init function the jQuery prototype for later instantiation 541 | jQuery.fn.init.prototype = jQuery.fn; 542 | 543 | function evalScript( i, elem ) { 544 | if ( elem.src ) 545 | jQuery.ajax({ 546 | url: elem.src, 547 | async: false, 548 | dataType: "script" 549 | }); 550 | 551 | else 552 | jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); 553 | 554 | if ( elem.parentNode ) 555 | elem.parentNode.removeChild( elem ); 556 | } 557 | 558 | function now(){ 559 | return +new Date; 560 | } 561 | 562 | jQuery.extend = jQuery.fn.extend = function() { 563 | // copy reference to target object 564 | var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; 565 | 566 | // Handle a deep copy situation 567 | if ( typeof target === "boolean" ) { 568 | deep = target; 569 | target = arguments[1] || {}; 570 | // skip the boolean and the target 571 | i = 2; 572 | } 573 | 574 | // Handle case when target is a string or something (possible in deep copy) 575 | if ( typeof target !== "object" && !jQuery.isFunction(target) ) 576 | target = {}; 577 | 578 | // extend jQuery itself if only one argument is passed 579 | if ( length == i ) { 580 | target = this; 581 | --i; 582 | } 583 | 584 | for ( ; i < length; i++ ) 585 | // Only deal with non-null/undefined values 586 | if ( (options = arguments[ i ]) != null ) 587 | // Extend the base object 588 | for ( var name in options ) { 589 | var src = target[ name ], copy = options[ name ]; 590 | 591 | // Prevent never-ending loop 592 | if ( target === copy ) 593 | continue; 594 | 595 | // Recurse if we're merging object values 596 | if ( deep && copy && typeof copy === "object" && !copy.nodeType ) 597 | target[ name ] = jQuery.extend( deep, 598 | // Never move original objects, clone them 599 | src || ( copy.length != null ? [ ] : { } ) 600 | , copy ); 601 | 602 | // Don't bring in undefined values 603 | else if ( copy !== undefined ) 604 | target[ name ] = copy; 605 | 606 | } 607 | 608 | // Return the modified object 609 | return target; 610 | }; 611 | 612 | // exclude the following css properties to add px 613 | var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i, 614 | // cache defaultView 615 | defaultView = document.defaultView || {}, 616 | toString = Object.prototype.toString; 617 | 618 | jQuery.extend({ 619 | noConflict: function( deep ) { 620 | window.$ = _$; 621 | 622 | if ( deep ) 623 | window.jQuery = _jQuery; 624 | 625 | return jQuery; 626 | }, 627 | 628 | // See test/unit/core.js for details concerning isFunction. 629 | // Since version 1.3, DOM methods and functions like alert 630 | // aren't supported. They return false on IE (#2968). 631 | isFunction: function( obj ) { 632 | return toString.call(obj) === "[object Function]"; 633 | }, 634 | 635 | isArray: function( obj ) { 636 | return toString.call(obj) === "[object Array]"; 637 | }, 638 | 639 | // check if an element is in a (or is an) XML document 640 | isXMLDoc: function( elem ) { 641 | return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || 642 | !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument ); 643 | }, 644 | 645 | // Evalulates a script in a global context 646 | globalEval: function( data ) { 647 | if ( data && /\S/.test(data) ) { 648 | // Inspired by code by Andrea Giammarchi 649 | // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html 650 | var head = document.getElementsByTagName("head")[0] || document.documentElement, 651 | script = document.createElement("script"); 652 | 653 | script.type = "text/javascript"; 654 | if ( jQuery.support.scriptEval ) 655 | script.appendChild( document.createTextNode( data ) ); 656 | else 657 | script.text = data; 658 | 659 | // Use insertBefore instead of appendChild to circumvent an IE6 bug. 660 | // This arises when a base node is used (#2709). 661 | head.insertBefore( script, head.firstChild ); 662 | head.removeChild( script ); 663 | } 664 | }, 665 | 666 | nodeName: function( elem, name ) { 667 | return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); 668 | }, 669 | 670 | // args is for internal usage only 671 | each: function( object, callback, args ) { 672 | var name, i = 0, length = object.length; 673 | 674 | if ( args ) { 675 | if ( length === undefined ) { 676 | for ( name in object ) 677 | if ( callback.apply( object[ name ], args ) === false ) 678 | break; 679 | } else 680 | for ( ; i < length; ) 681 | if ( callback.apply( object[ i++ ], args ) === false ) 682 | break; 683 | 684 | // A special, fast, case for the most common use of each 685 | } else { 686 | if ( length === undefined ) { 687 | for ( name in object ) 688 | if ( callback.call( object[ name ], name, object[ name ] ) === false ) 689 | break; 690 | } else 691 | for ( var value = object[0]; 692 | i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} 693 | } 694 | 695 | return object; 696 | }, 697 | 698 | prop: function( elem, value, type, i, name ) { 699 | // Handle executable functions 700 | if ( jQuery.isFunction( value ) ) 701 | value = value.call( elem, i ); 702 | 703 | // Handle passing in a number to a CSS property 704 | return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ? 705 | value + "px" : 706 | value; 707 | }, 708 | 709 | className: { 710 | // internal only, use addClass("class") 711 | add: function( elem, classNames ) { 712 | jQuery.each((classNames || "").split(/\s+/), function(i, className){ 713 | if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) 714 | elem.className += (elem.className ? " " : "") + className; 715 | }); 716 | }, 717 | 718 | // internal only, use removeClass("class") 719 | remove: function( elem, classNames ) { 720 | if (elem.nodeType == 1) 721 | elem.className = classNames !== undefined ? 722 | jQuery.grep(elem.className.split(/\s+/), function(className){ 723 | return !jQuery.className.has( classNames, className ); 724 | }).join(" ") : 725 | ""; 726 | }, 727 | 728 | // internal only, use hasClass("class") 729 | has: function( elem, className ) { 730 | return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; 731 | } 732 | }, 733 | 734 | // A method for quickly swapping in/out CSS properties to get correct calculations 735 | swap: function( elem, options, callback ) { 736 | var old = {}; 737 | // Remember the old values, and insert the new ones 738 | for ( var name in options ) { 739 | old[ name ] = elem.style[ name ]; 740 | elem.style[ name ] = options[ name ]; 741 | } 742 | 743 | callback.call( elem ); 744 | 745 | // Revert the old values 746 | for ( var name in options ) 747 | elem.style[ name ] = old[ name ]; 748 | }, 749 | 750 | css: function( elem, name, force, extra ) { 751 | if ( name == "width" || name == "height" ) { 752 | var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; 753 | 754 | function getWH() { 755 | val = name == "width" ? elem.offsetWidth : elem.offsetHeight; 756 | 757 | if ( extra === "border" ) 758 | return; 759 | 760 | jQuery.each( which, function() { 761 | if ( !extra ) 762 | val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; 763 | if ( extra === "margin" ) 764 | val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0; 765 | else 766 | val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; 767 | }); 768 | } 769 | 770 | if ( elem.offsetWidth !== 0 ) 771 | getWH(); 772 | else 773 | jQuery.swap( elem, props, getWH ); 774 | 775 | return Math.max(0, Math.round(val)); 776 | } 777 | 778 | return jQuery.curCSS( elem, name, force ); 779 | }, 780 | 781 | curCSS: function( elem, name, force ) { 782 | var ret, style = elem.style; 783 | 784 | // We need to handle opacity special in IE 785 | if ( name == "opacity" && !jQuery.support.opacity ) { 786 | ret = jQuery.attr( style, "opacity" ); 787 | 788 | return ret == "" ? 789 | "1" : 790 | ret; 791 | } 792 | 793 | // Make sure we're using the right name for getting the float value 794 | if ( name.match( /float/i ) ) 795 | name = styleFloat; 796 | 797 | if ( !force && style && style[ name ] ) 798 | ret = style[ name ]; 799 | 800 | else if ( defaultView.getComputedStyle ) { 801 | 802 | // Only "float" is needed here 803 | if ( name.match( /float/i ) ) 804 | name = "float"; 805 | 806 | name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); 807 | 808 | var computedStyle = defaultView.getComputedStyle( elem, null ); 809 | 810 | if ( computedStyle ) 811 | ret = computedStyle.getPropertyValue( name ); 812 | 813 | // We should always get a number back from opacity 814 | if ( name == "opacity" && ret == "" ) 815 | ret = "1"; 816 | 817 | } else if ( elem.currentStyle ) { 818 | var camelCase = name.replace(/\-(\w)/g, function(all, letter){ 819 | return letter.toUpperCase(); 820 | }); 821 | 822 | ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; 823 | 824 | // From the awesome hack by Dean Edwards 825 | // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 826 | 827 | // If we're not dealing with a regular pixel number 828 | // but a number that has a weird ending, we need to convert it to pixels 829 | if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { 830 | // Remember the original values 831 | var left = style.left, rsLeft = elem.runtimeStyle.left; 832 | 833 | // Put in the new values to get a computed value out 834 | elem.runtimeStyle.left = elem.currentStyle.left; 835 | style.left = ret || 0; 836 | ret = style.pixelLeft + "px"; 837 | 838 | // Revert the changed values 839 | style.left = left; 840 | elem.runtimeStyle.left = rsLeft; 841 | } 842 | } 843 | 844 | return ret; 845 | }, 846 | 847 | clean: function( elems, context, fragment ) { 848 | context = context || document; 849 | 850 | // !context.createElement fails in IE with an error but returns typeof 'object' 851 | if ( typeof context.createElement === "undefined" ) 852 | context = context.ownerDocument || context[0] && context[0].ownerDocument || document; 853 | 854 | // If a single string is passed in and it's a single tag 855 | // just do a createElement and skip the rest 856 | if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) { 857 | var match = /^<(\w+)\s*\/?>$/.exec(elems[0]); 858 | if ( match ) 859 | return [ context.createElement( match[1] ) ]; 860 | } 861 | 862 | var ret = [], scripts = [], div = context.createElement("div"); 863 | 864 | jQuery.each(elems, function(i, elem){ 865 | if ( typeof elem === "number" ) 866 | elem += ''; 867 | 868 | if ( !elem ) 869 | return; 870 | 871 | // Convert html string into DOM nodes 872 | if ( typeof elem === "string" ) { 873 | // Fix "XHTML"-style tags in all browsers 874 | elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ 875 | return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? 876 | all : 877 | front + ">"; 878 | }); 879 | 880 | // Trim whitespace, otherwise indexOf won't work as expected 881 | var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase(); 882 | 883 | var wrap = 884 | // option or optgroup 885 | !tags.indexOf("", "" ] || 887 | 888 | !tags.indexOf("", "" ] || 890 | 891 | tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && 892 | [ 1, "", "
" ] || 893 | 894 | !tags.indexOf("", "" ] || 896 | 897 | // matched above 898 | (!tags.indexOf("", "" ] || 900 | 901 | !tags.indexOf("", "" ] || 903 | 904 | // IE can't serialize and