mirror of
https://github.com/elastic/logstash.git
synced 2025-04-23 22:27:21 -04:00
- Purge old web ui
This commit is contained in:
parent
4684f65995
commit
9f3114c883
75 changed files with 0 additions and 18292 deletions
21
web/.gitignore
vendored
21
web/.gitignore
vendored
|
@ -1,21 +0,0 @@
|
|||
.DS_Store
|
||||
log/*
|
||||
tmp/*
|
||||
TAGS
|
||||
*~
|
||||
.#*
|
||||
schema/schema.rb
|
||||
schema/*_structure.sql
|
||||
schema/*.sqlite3
|
||||
schema/*.sqlite
|
||||
schema/*.db
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
*.db
|
||||
src/*
|
||||
.hgignore
|
||||
.hg/*
|
||||
.svn/*
|
||||
gems/gems/*
|
||||
gems/specifications/*
|
||||
merb_profile_results
|
35
web/Rakefile
35
web/Rakefile
|
@ -1,35 +0,0 @@
|
|||
require 'rubygems'
|
||||
require 'rake/rdoctask'
|
||||
|
||||
require 'merb-core'
|
||||
require 'merb-core/tasks/merb'
|
||||
|
||||
include FileUtils
|
||||
|
||||
# Load the basic runtime dependencies; this will include
|
||||
# any plugins and therefore plugin rake tasks.
|
||||
init_env = ENV['MERB_ENV'] || 'rake'
|
||||
Merb.load_dependencies(:environment => init_env)
|
||||
|
||||
# Get Merb plugins and dependencies
|
||||
Merb::Plugins.rakefiles.each { |r| require r }
|
||||
|
||||
# Load any app level custom rakefile extensions from lib/tasks
|
||||
tasks_path = File.join(File.dirname(__FILE__), "lib", "tasks")
|
||||
rake_files = Dir["#{tasks_path}/*.rake"]
|
||||
rake_files.each{|rake_file| load rake_file }
|
||||
|
||||
desc "Start runner environment"
|
||||
task :merb_env do
|
||||
Merb.start_environment(:environment => init_env, :adapter => 'runner')
|
||||
end
|
||||
|
||||
require 'spec/rake/spectask'
|
||||
require 'merb-core/test/tasks/spectasks'
|
||||
desc 'Default: run spec examples'
|
||||
task :default => 'spec'
|
||||
|
||||
##############################################################################
|
||||
# ADD YOUR CUSTOM TASKS IN /lib/tasks
|
||||
# NAME YOUR RAKE FILES file_name.rake
|
||||
##############################################################################
|
|
@ -1,2 +0,0 @@
|
|||
class Application < Merb::Controller
|
||||
end
|
|
@ -1,13 +0,0 @@
|
|||
class Exceptions < Merb::Controller
|
||||
|
||||
# handle NotFound exceptions (404)
|
||||
def not_found
|
||||
render :format => :html
|
||||
end
|
||||
|
||||
# handle NotAcceptable exceptions (406)
|
||||
def not_acceptable
|
||||
render :format => :html
|
||||
end
|
||||
|
||||
end
|
|
@ -1,105 +0,0 @@
|
|||
|
||||
$: << ".."
|
||||
require "lib/net/clients/search"
|
||||
require "timeout"
|
||||
require "ap"
|
||||
#require "elasticsearch"
|
||||
|
||||
class Search < Application
|
||||
def index
|
||||
render
|
||||
end
|
||||
|
||||
def query
|
||||
q = {}
|
||||
params[:log_type] = (params[:log_type] or "linux-syslog")
|
||||
params[:offset] = (params[:offset] ? params[:offset].to_i : 0) rescue 0
|
||||
params[:limit] = (params[:limit] ? params[:limit].to_i : 100) rescue 100
|
||||
|
||||
options = {}
|
||||
options[:from] = params[:offset]
|
||||
options[:size] = params[:limit]
|
||||
options[:sort] = [ "@DATE" ]
|
||||
q[:query_string] = {
|
||||
:default_field => "@LINE",
|
||||
:query => params[:q],
|
||||
}
|
||||
|
||||
options[:query] = q
|
||||
|
||||
search = LogStash::Net::Clients::ElasticSearch.new("/opt/logstash/etc/logstashd.yaml")
|
||||
params[:graphperiod] ||= 60 * 60 * 24
|
||||
params[:graphstep] ||= 60 * 60
|
||||
params[:graphstep] = params[:graphstep].to_i
|
||||
params[:graphperiod] = params[:graphperiod].to_i
|
||||
|
||||
if params[:graphperiod] > 60 * 60 * 24 * 7 * 2
|
||||
@readable_timeperiod = params[:graphperiod] / (60 * 60 * 24 * 7)
|
||||
@readable_timeunit = "week"
|
||||
elsif params[:graphperiod] >= 60 * 60 * 24 * 3
|
||||
@readable_timeperiod = params[:graphperiod] / (60 * 60 * 24)
|
||||
@readable_timeunit = "day"
|
||||
elsif params[:graphperiod] > 60 * 60 * 3
|
||||
@readable_timeperiod = params[:graphperiod] / (60 * 60)
|
||||
@readable_timeunit = "hour"
|
||||
else
|
||||
@readable_timeperiod = params[:graphperiod] / (60)
|
||||
@readable_timeunit = "minute"
|
||||
end
|
||||
|
||||
if @readable_timeperiod != 1
|
||||
@readable_timeunit = "#{@readable_timeunit}s"
|
||||
end
|
||||
|
||||
Timeout.timeout(10) do
|
||||
results = search.query(options)
|
||||
@hits = results.hits
|
||||
@results = results.results
|
||||
@graphdata = _graphpoints(search, q)
|
||||
render
|
||||
end
|
||||
end
|
||||
|
||||
def _graphpoints(search, query)
|
||||
#provides :json
|
||||
orig_query = query[:q]
|
||||
|
||||
graph_period = params[:graphperiod].to_i
|
||||
increment = params[:graphstep].to_i
|
||||
start_mod = 60 * 60
|
||||
|
||||
starttime = (Time.now - graph_period).to_i # + Time.now.gmt_offset
|
||||
starttime = starttime - (starttime % start_mod)
|
||||
curtime = starttime
|
||||
@points = []
|
||||
# correct for timezone date offset
|
||||
Timeout.timeout(20) do
|
||||
queries = []
|
||||
while starttime + graph_period + 3600 > curtime
|
||||
endtime = curtime + increment - 1
|
||||
querygen = [query.clone]
|
||||
querygen << {
|
||||
:range => {
|
||||
"@DATE" => {
|
||||
:to => endtime,
|
||||
:from => curtime,
|
||||
}
|
||||
}
|
||||
}
|
||||
queries << { :bool => { :must => querygen } }
|
||||
curtime += increment
|
||||
end
|
||||
|
||||
@data = Hash.new
|
||||
queries.each do |genquery|
|
||||
count = search.count(genquery)
|
||||
puts count
|
||||
p genquery
|
||||
time = genquery[:bool][:must][1][:range]["@DATE"][:from].to_i + Time.now.gmtoff
|
||||
@data[time * 1000] = count
|
||||
end
|
||||
@data = @data.to_a
|
||||
end
|
||||
return @data
|
||||
end
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
module Merb
|
||||
module GlobalHelpers
|
||||
# helpers defined here available to all views.
|
||||
end
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
module Merb
|
||||
module SearchHelper
|
||||
|
||||
end
|
||||
end # Merb
|
|
@ -1,63 +0,0 @@
|
|||
<div id="container">
|
||||
<div id="header-container">
|
||||
<img src="/images/merb.jpg" />
|
||||
<!-- <h1>Mongrel + Erb</h1> -->
|
||||
<h2>pocket rocket web framework</h2>
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
<div id="left-container">
|
||||
<h3>Exception:</h3>
|
||||
<p><%= request.exceptions.first.message %></p>
|
||||
</div>
|
||||
|
||||
<div id="main-container">
|
||||
<h3>Why am I seeing this page?</h3>
|
||||
<p>Merb couldn't find an appropriate content_type to return,
|
||||
based on what you said was available via provides() and
|
||||
what the client requested.</p>
|
||||
|
||||
<h3>How to add a mime-type</h3>
|
||||
<pre><code>
|
||||
Merb.add_mime_type :pdf, :to_pdf, %w[application/pdf], "Content-Encoding" => "gzip"
|
||||
</code></pre>
|
||||
<h3>What this means is:</h3>
|
||||
<ul>
|
||||
<li>Add a mime-type for :pdf</li>
|
||||
<li>Register the method for converting objects to PDF as <code>#to_pdf</code>.</li>
|
||||
<li>Register the incoming mime-type "Accept" header as <code>application/pdf</code>.</li>
|
||||
<li>Specify a new header for PDF types so it will set <code>Content-Encoding</code> to gzip.</li>
|
||||
</ul>
|
||||
|
||||
<h3>You can then do:</h3>
|
||||
<pre><code>
|
||||
class Foo < Application
|
||||
provides :pdf
|
||||
end
|
||||
</code></pre>
|
||||
|
||||
<h3>Where can I find help?</h3>
|
||||
<p>If you have any questions or if you can't figure something out, please take a
|
||||
look at our <a href="http://merbivore.com/"> project page</a>,
|
||||
feel free to come chat at irc.freenode.net, channel #merb,
|
||||
or post to <a href="http://groups.google.com/group/merb">merb mailing list</a>
|
||||
on Google Groups.</p>
|
||||
|
||||
<h3>What if I've found a bug?</h3>
|
||||
<p>If you want to file a bug or make your own contribution to Merb,
|
||||
feel free to register and create a ticket at our
|
||||
<a href="http://merb.lighthouseapp.com/">project development page</a>
|
||||
on Lighthouse.</p>
|
||||
|
||||
<h3>How do I edit this page?</h3>
|
||||
<p>You can change what people see when this happens by editing <tt>app/views/exceptions/not_acceptable.html.erb</tt>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="footer-container">
|
||||
<hr />
|
||||
<div class="left"></div>
|
||||
<div class="right">© 2008 the merb dev team</div>
|
||||
<p> </p>
|
||||
</div>
|
||||
</div>
|
|
@ -1,47 +0,0 @@
|
|||
<div id="container">
|
||||
<div id="header-container">
|
||||
<img src="/images/merb.jpg" />
|
||||
<!-- <h1>Mongrel + Erb</h1> -->
|
||||
<h2>pocket rocket web framework</h2>
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
<div id="left-container">
|
||||
<h3>Exception:</h3>
|
||||
<p><%= request.exceptions.first.message %></p>
|
||||
</div>
|
||||
|
||||
<div id="main-container">
|
||||
<h3>Welcome to Merb!</h3>
|
||||
<p>Merb is a light-weight MVC framework written in Ruby. We hope you enjoy it.</p>
|
||||
|
||||
<h3>Where can I find help?</h3>
|
||||
<p>If you have any questions or if you can't figure something out, please take a
|
||||
look at our <a href="http://merbivore.com/"> project page</a>,
|
||||
feel free to come chat at irc.freenode.net, channel #merb,
|
||||
or post to <a href="http://groups.google.com/group/merb">merb mailing list</a>
|
||||
on Google Groups.</p>
|
||||
|
||||
<h3>What if I've found a bug?</h3>
|
||||
<p>If you want to file a bug or make your own contribution to Merb,
|
||||
feel free to register and create a ticket at our
|
||||
<a href="http://merb.lighthouseapp.com/">project development page</a>
|
||||
on Lighthouse.</p>
|
||||
|
||||
<h3>How do I edit this page?</h3>
|
||||
<p>You're seeing this page because you need to edit the following files:
|
||||
<ul>
|
||||
<li>config/router.rb <strong><em>(recommended)</em></strong></li>
|
||||
<li>app/views/exceptions/not_found.html.erb <strong><em>(recommended)</em></strong></li>
|
||||
<li>app/views/layout/application.html.erb <strong><em>(change this layout)</em></strong></li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="footer-container">
|
||||
<hr />
|
||||
<div class="left"></div>
|
||||
<div class="right">© 2008 the merb dev team</div>
|
||||
<p> </p>
|
||||
</div>
|
||||
</div>
|
|
@ -1,15 +0,0 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
|
||||
<head>
|
||||
<title>Fresh Merb App</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="/stylesheets/master.css" type="text/css" media="screen" charset="utf-8" />
|
||||
<script src="/javascripts/flot/jquery.js"></script>
|
||||
<script src="/javascripts/flot/jquery.flot.js"></script>
|
||||
<script src="/javascripts/js/jquery-ui-1.8.1.custom.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<%#= message[:notice] %>
|
||||
<%= catch_content :for_layout %>
|
||||
</body>
|
||||
</html>
|
|
@ -1,15 +0,0 @@
|
|||
<div class="searchBar">
|
||||
<span>
|
||||
<%= form :action => url(:controller => "search", :action => "query"),
|
||||
:method => :get do %>
|
||||
<%= text_field :name => "q", :label => "Query: ", :value => escape_html(params[:q]), :size => 100 %>
|
||||
<%= hidden_field :name => "graphperiod", :value => 60*60*24 %>
|
||||
<%= hidden_field :name => "graphstep", :value => 60*60 %>
|
||||
<%= submit "Search" %>
|
||||
<% end =%>
|
||||
</span>
|
||||
|
||||
<span class="logstash-logo">
|
||||
logstash.
|
||||
</span>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
<%= @data.to_json %>
|
|
@ -1,17 +0,0 @@
|
|||
<div id="portal">
|
||||
<center>
|
||||
<div class="searchBar">
|
||||
<div>
|
||||
logstash.
|
||||
</div>
|
||||
|
||||
<span>
|
||||
<%= form :action => url(:controller => "search", :action => "query"),
|
||||
:method => :get do %>
|
||||
<%= text_field :name => "q", :label => "Query: ", :value => escape_html(params[:q]), :size => 100 %>
|
||||
<%= submit "Search" %>
|
||||
<% end =%>
|
||||
</span>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
|
@ -1,86 +0,0 @@
|
|||
<%= partial :searchform %>
|
||||
|
||||
<div id="content">
|
||||
<h4>Result counts over the past <%= @readable_timeperiod %> <%= @readable_timeunit %> for '<%=h params[:q] %>'</h4>
|
||||
<div id="visual" style="width:850px;height:200px;"></div>
|
||||
|
||||
<hr style="margin: 2em; width: 70%">
|
||||
|
||||
<h4>Results <%= params[:offset] %> - <%= [@hits,params[:offset] + params[:limit]].min %> of <%= @hits %> for <%=h params[:q] %></h4>
|
||||
<% if params[:offset] > 0 %>
|
||||
<%= link_to "first", url(:controller => "search", :action => "query",
|
||||
:q => params[:q],
|
||||
:offset => 0,
|
||||
:limit => params[:limit],
|
||||
:log_type => params[:log_type]) %> |
|
||||
<%= link_to "prev", url(:controller => "search", :action => "query",
|
||||
:q => params[:q],
|
||||
:offset => [0, params[:offset] - params[:limit]].max,
|
||||
:limit => params[:limit],
|
||||
:log_type => params[:log_type]) %>
|
||||
<% end %>
|
||||
<%= "|" if @hits > params[:limit] %>
|
||||
<% if params[:offset] + params[:limit] < @hits %>
|
||||
<%= link_to "next", url(:controller => "search", :action => "query",
|
||||
:q => params[:q],
|
||||
:offset => [@hits - params[:limit], params[:offset] + params[:limit]].min,
|
||||
:limit => params[:limit],
|
||||
:log_type => params[:log_type]) %>
|
||||
|
|
||||
<%= link_to "last", url(:controller => "search", :action => "query",
|
||||
:q => params[:q],
|
||||
:offset => @hits - params[:limit],
|
||||
:limit => params[:limit],
|
||||
:log_type => params[:log_type]) %>
|
||||
<% end %>
|
||||
|
||||
<pre>
|
||||
<% @results.each do |result| -%>
|
||||
(<span class="datestamp"><%=h Time.at(result["_source"]["@DATE"]).strftime("%Y/%m/%d %H:%M:%S") %></span>) <%=h result["_source"]["@LINE"] %>
|
||||
<% end -%>
|
||||
</pre>
|
||||
|
||||
<script id="source">
|
||||
$(function () {
|
||||
var graphdata = <%= @graphdata.to_json %>;
|
||||
|
||||
var plot = $.plot($("#visual"),
|
||||
[
|
||||
{ data: graphdata,
|
||||
bars: {
|
||||
show: true,
|
||||
barWidth: <%= (params[:graphstep] or 60 * 60).to_i * 1000 %>,
|
||||
}
|
||||
}
|
||||
],
|
||||
{ xaxis: { mode: "time" } }
|
||||
);
|
||||
|
||||
var nowpoint = plot.pointOffset( { x: <%= (Time.now.to_i + Time.now.gmtoff) * 1000 %>, y: 1 } );
|
||||
var note = $("<div>").css("position", "absolute")
|
||||
.css("left", nowpoint.left)
|
||||
.css("top", "10px")
|
||||
.css("height", "170px")
|
||||
.css("border-left", "1px dashed grey")
|
||||
//.css("border-bottom", "1px solid grey")
|
||||
//.css("border-top", "1px solid grey")
|
||||
//.css("text-align", "center")
|
||||
//.css("margin-left", ".5em")
|
||||
//.css("font-weight", "bold")
|
||||
//.css("text-align", "top")
|
||||
//.css("white-space", "nowrap")
|
||||
//.css("-webkit-transform", "rotate(90deg)")
|
||||
//.css("-webkit-transform-origin", "0 0")
|
||||
//.css("-moz-transform", "rotate(90deg)")
|
||||
//.css("-moz-transform-origin", "0 0")
|
||||
//.html("<%= Time.now.strftime("%b, %d %Y %H:%M:%S") %>");
|
||||
$("#visual").append(note)
|
||||
//var ctx = plot.getCanvas().getContext("2d");
|
||||
//ctx.moveTo(nowpoint.left, 0);
|
||||
//console.log(plot)
|
||||
//ctx.lineTo(nowpoint.left, nowpoint.top);
|
||||
//ctx.strokeStyle = "#88FF00";
|
||||
//ctx.stroke();
|
||||
});
|
||||
</script>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
Autotest.add_discovery { "merb" }
|
|
@ -1,149 +0,0 @@
|
|||
# Adapted from Autotest::Rails
|
||||
require 'autotest'
|
||||
|
||||
class Autotest::Merb < Autotest
|
||||
|
||||
# +model_tests_dir+:: the directory to find model-centric tests
|
||||
# +controller_tests_dir+:: the directory to find controller-centric tests
|
||||
# +view_tests_dir+:: the directory to find view-centric tests
|
||||
# +fixtures_dir+:: the directory to find fixtures in
|
||||
attr_accessor :model_tests_dir, :controller_tests_dir, :view_tests_dir, :fixtures_dir
|
||||
|
||||
def initialize
|
||||
super
|
||||
|
||||
initialize_test_layout
|
||||
|
||||
# Ignore any happenings in these directories
|
||||
add_exception %r%^\./(?:doc|log|public|tmp)%
|
||||
|
||||
# Ignore any mappings that Autotest may have already set up
|
||||
clear_mappings
|
||||
|
||||
# Any changes to a file in the root of the 'lib' directory will run any
|
||||
# model test with a corresponding name.
|
||||
add_mapping %r%^lib\/.*\.rb% do |filename, _|
|
||||
files_matching Regexp.new(["^#{model_test_for(filename)}$"])
|
||||
end
|
||||
|
||||
# Any changes to a fixture will run corresponding view, controller and
|
||||
# model tests
|
||||
add_mapping %r%^#{fixtures_dir}/(.*)s.yml% do |_, m|
|
||||
[
|
||||
model_test_for(m[1]),
|
||||
controller_test_for(m[1]),
|
||||
view_test_for(m[1])
|
||||
]
|
||||
end
|
||||
|
||||
# Any change to a test or test will cause it to be run
|
||||
add_mapping %r%^test/(unit|models|integration|controllers|views|functional)/.*rb$% do |filename, _|
|
||||
filename
|
||||
end
|
||||
|
||||
# Any change to a model will cause it's corresponding test to be run
|
||||
add_mapping %r%^app/models/(.*)\.rb$% do |_, m|
|
||||
model_test_for(m[1])
|
||||
end
|
||||
|
||||
# Any change to the global helper will result in all view and controller
|
||||
# tests being run
|
||||
add_mapping %r%^app/helpers/global_helpers.rb% do
|
||||
files_matching %r%^test/(views|functional|controllers)/.*_test\.rb$%
|
||||
end
|
||||
|
||||
# Any change to a helper will run it's corresponding view and controller
|
||||
# tests, unless the helper is the global helper. Changes to the global
|
||||
# helper run all view and controller tests.
|
||||
add_mapping %r%^app/helpers/(.*)_helper(s)?.rb% do |_, m|
|
||||
if m[1] == "global" then
|
||||
files_matching %r%^test/(views|functional|controllers)/.*_test\.rb$%
|
||||
else
|
||||
[
|
||||
view_test_for(m[1]),
|
||||
controller_test_for(m[1])
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
# Changes to views result in their corresponding view and controller test
|
||||
# being run
|
||||
add_mapping %r%^app/views/(.*)/% do |_, m|
|
||||
[
|
||||
view_test_for(m[1]),
|
||||
controller_test_for(m[1])
|
||||
]
|
||||
end
|
||||
|
||||
# Changes to a controller result in its corresponding test being run. If
|
||||
# the controller is the exception or application controller, all
|
||||
# controller tests are run.
|
||||
add_mapping %r%^app/controllers/(.*)\.rb$% do |_, m|
|
||||
if ["application", "exception"].include?(m[1])
|
||||
files_matching %r%^test/(controllers|views|functional)/.*_test\.rb$%
|
||||
else
|
||||
controller_test_for(m[1])
|
||||
end
|
||||
end
|
||||
|
||||
# If a change is made to the router, run all controller and view tests
|
||||
add_mapping %r%^config/router.rb$% do # FIX
|
||||
files_matching %r%^test/(controllers|views|functional)/.*_test\.rb$%
|
||||
end
|
||||
|
||||
# If any of the major files governing the environment are altered, run
|
||||
# everything
|
||||
add_mapping %r%^test/test_helper.rb|config/(init|rack|environments/test.rb|database.yml)% do # FIX
|
||||
files_matching %r%^test/(unit|models|controllers|views|functional)/.*_test\.rb$%
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Determines the paths we can expect tests or specs to reside, as well as
|
||||
# corresponding fixtures.
|
||||
def initialize_test_layout
|
||||
self.model_tests_dir = "test/unit"
|
||||
self.controller_tests_dir = "test/functional"
|
||||
self.view_tests_dir = "test/views"
|
||||
self.fixtures_dir = "test/fixtures"
|
||||
end
|
||||
|
||||
# Given a filename and the test type, this method will return the
|
||||
# corresponding test's or spec's name.
|
||||
#
|
||||
# ==== Arguments
|
||||
# +filename+<String>:: the file name of the model, view, or controller
|
||||
# +kind_of_test+<Symbol>:: the type of test we that we should run
|
||||
#
|
||||
# ==== Returns
|
||||
# String:: the name of the corresponding test or spec
|
||||
#
|
||||
# ==== Example
|
||||
#
|
||||
# > test_for("user", :model)
|
||||
# => "user_test.rb"
|
||||
# > test_for("login", :controller)
|
||||
# => "login_controller_test.rb"
|
||||
# > test_for("form", :view)
|
||||
# => "form_view_spec.rb" # If you're running a RSpec-like suite
|
||||
def test_for(filename, kind_of_test)
|
||||
name = [filename]
|
||||
name << kind_of_test.to_s if kind_of_test == :view
|
||||
name << "test"
|
||||
return name.join("_") + ".rb"
|
||||
end
|
||||
|
||||
def model_test_for(filename)
|
||||
[model_tests_dir, test_for(filename, :model)].join("/")
|
||||
end
|
||||
|
||||
def controller_test_for(filename)
|
||||
[controller_tests_dir, test_for(filename, :controller)].join("/")
|
||||
end
|
||||
|
||||
def view_test_for(filename)
|
||||
[view_tests_dir, test_for(filename, :view)].join("/")
|
||||
end
|
||||
|
||||
end
|
|
@ -1,165 +0,0 @@
|
|||
# Adapted from Autotest::Rails, RSpec's autotest class, as well as merb-core's.
|
||||
require 'autotest'
|
||||
|
||||
class RspecCommandError < StandardError; end
|
||||
|
||||
# This class maps your application's structure so Autotest can understand what
|
||||
# specs to run when files change.
|
||||
#
|
||||
# Fixtures are _not_ covered by this class. If you change a fixture file, you
|
||||
# will have to run your spec suite manually, or, better yet, provide your own
|
||||
# Autotest map explaining how your fixtures are set up.
|
||||
class Autotest::MerbRspec < Autotest
|
||||
def initialize
|
||||
super
|
||||
|
||||
# Ignore any happenings in these directories
|
||||
add_exception %r%^\./(?:doc|log|public|tmp|\.git|\.hg|\.svn|framework|gems|schema|\.DS_Store|autotest|bin|.*\.sqlite3)%
|
||||
# Ignore SCM directories and custom Autotest mappings
|
||||
%w[.svn .hg .git .autotest].each { |exception| add_exception(exception) }
|
||||
|
||||
# Ignore any mappings that Autotest may have already set up
|
||||
clear_mappings
|
||||
|
||||
# Anything in /lib could have a spec anywhere, if at all. So, look for
|
||||
# files with roughly the same name as the file in /lib
|
||||
add_mapping %r%^lib\/(.*)\.rb% do |_, m|
|
||||
files_matching %r%^spec\/#{m[1]}%
|
||||
end
|
||||
|
||||
add_mapping %r%^spec/(spec_helper|shared/.*)\.rb$% do
|
||||
all_specs
|
||||
end
|
||||
|
||||
# Changing a spec will cause it to run itself
|
||||
add_mapping %r%^spec/.*\.rb$% do |filename, _|
|
||||
filename
|
||||
end
|
||||
|
||||
# Any change to a model will cause it's corresponding test to be run
|
||||
add_mapping %r%^app/models/(.*)\.rb$% do |_, m|
|
||||
spec_for(m[1], 'model')
|
||||
end
|
||||
|
||||
# Any change to global_helpers will result in all view and controller
|
||||
# tests being run
|
||||
add_mapping %r%^app/helpers/global_helpers\.rb% do
|
||||
files_matching %r%^spec/(views|controllers|helpers)/.*_spec\.rb$%
|
||||
end
|
||||
|
||||
# Any change to a helper will cause its spec to be run
|
||||
add_mapping %r%^app/helpers/((.*)_helper(s)?)\.rb% do |_, m|
|
||||
spec_for(m[1], 'helper')
|
||||
end
|
||||
|
||||
# Changes to a view cause its spec to be run
|
||||
add_mapping %r%^app/views/(.*)/% do |_, m|
|
||||
spec_for(m[1], 'view')
|
||||
end
|
||||
|
||||
# Changes to a controller result in its corresponding spec being run. If
|
||||
# the controller is the exception or application controller, all
|
||||
# controller specs are run.
|
||||
add_mapping %r%^app/controllers/(.*)\.rb$% do |_, m|
|
||||
if ["application", "exception"].include?(m[1])
|
||||
files_matching %r%^spec/controllers/.*_spec\.rb$%
|
||||
else
|
||||
spec_for(m[1], 'controller')
|
||||
end
|
||||
end
|
||||
|
||||
# If a change is made to the router, run controller, view and helper specs
|
||||
add_mapping %r%^config/router.rb$% do
|
||||
files_matching %r%^spec/(controllers|views|helpers)/.*_spec\.rb$%
|
||||
end
|
||||
|
||||
# If any of the major files governing the environment are altered, run
|
||||
# everything
|
||||
add_mapping %r%^config/(init|rack|environments/test).*\.rb|database\.yml% do
|
||||
all_specs
|
||||
end
|
||||
end
|
||||
|
||||
def failed_results(results)
|
||||
results.scan(/^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m)
|
||||
end
|
||||
|
||||
def handle_results(results)
|
||||
@failures = failed_results(results)
|
||||
@files_to_test = consolidate_failures(@failures)
|
||||
@files_to_test.empty? && !$TESTING ? hook(:green) : hook(:red)
|
||||
@tainted = !@files_to_test.empty?
|
||||
end
|
||||
|
||||
def consolidate_failures(failed)
|
||||
filters = Hash.new { |h,k| h[k] = [] }
|
||||
failed.each do |spec, failed_trace|
|
||||
if f = test_files_for(failed).find { |f| f =~ /spec\// }
|
||||
filters[f] << spec
|
||||
break
|
||||
end
|
||||
end
|
||||
filters
|
||||
end
|
||||
|
||||
def make_test_cmd(specs_to_runs)
|
||||
[
|
||||
ruby,
|
||||
"-S",
|
||||
spec_command,
|
||||
add_options_if_present,
|
||||
files_to_test.keys.flatten.join(' ')
|
||||
].join(' ')
|
||||
end
|
||||
|
||||
def add_options_if_present
|
||||
File.exist?("spec/spec.opts") ? "-O spec/spec.opts " : ""
|
||||
end
|
||||
|
||||
# Finds the proper spec command to use. Precendence is set in the
|
||||
# lazily-evaluated method spec_commands. Alias + Override that in
|
||||
# ~/.autotest to provide a different spec command then the default
|
||||
# paths provided.
|
||||
def spec_command(separator=File::ALT_SEPARATOR)
|
||||
unless defined?(@spec_command)
|
||||
@spec_command = spec_commands.find { |cmd| File.exists?(cmd) }
|
||||
|
||||
raise RspecCommandError, "No spec command could be found" unless @spec_command
|
||||
|
||||
@spec_command.gsub!(File::SEPARATOR, separator) if separator
|
||||
end
|
||||
@spec_command
|
||||
end
|
||||
|
||||
# Autotest will look for spec commands in the following
|
||||
# locations, in this order:
|
||||
#
|
||||
# * default spec bin/loader installed in Rubygems
|
||||
# * any spec command found in PATH
|
||||
def spec_commands
|
||||
[File.join(Config::CONFIG['bindir'], 'spec'), 'spec']
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Runs +files_matching+ for all specs
|
||||
def all_specs
|
||||
files_matching %r%^spec/.*_spec\.rb$%
|
||||
end
|
||||
|
||||
# Generates a path to some spec given its kind and the match from a mapping
|
||||
#
|
||||
# ==== Arguments
|
||||
# match<String>:: the match from a mapping
|
||||
# kind<String>:: the kind of spec that the match represents
|
||||
#
|
||||
# ==== Returns
|
||||
# String
|
||||
#
|
||||
# ==== Example
|
||||
# > spec_for('post', :view')
|
||||
# => "spec/views/post_spec.rb"
|
||||
def spec_for(match, kind)
|
||||
File.join("spec", kind + 's', "#{match}_spec.rb")
|
||||
end
|
||||
end
|
|
@ -1,15 +0,0 @@
|
|||
Merb.logger.info("Loaded DEVELOPMENT Environment...")
|
||||
Merb::Config.use { |c|
|
||||
c[:exception_details] = true
|
||||
c[:reload_templates] = true
|
||||
c[:reload_classes] = true
|
||||
c[:reload_time] = 0.5
|
||||
c[:ignore_tampered_cookies] = true
|
||||
c[:log_auto_flush ] = true
|
||||
c[:log_level] = :debug
|
||||
|
||||
c[:log_stream] = STDOUT
|
||||
c[:log_file] = nil
|
||||
# Or redirect logging into a file:
|
||||
# c[:log_file] = Merb.root / "log" / "development.log"
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
Merb.logger.info("Loaded PRODUCTION Environment...")
|
||||
Merb::Config.use { |c|
|
||||
c[:exception_details] = false
|
||||
c[:reload_classes] = false
|
||||
c[:log_level] = :error
|
||||
|
||||
c[:log_file] = Merb.root / "log" / "production.log"
|
||||
# or redirect logger using IO handle
|
||||
# c[:log_stream] = STDOUT
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
Merb.logger.info("Loaded RAKE Environment...")
|
||||
Merb::Config.use { |c|
|
||||
c[:exception_details] = true
|
||||
c[:reload_classes] = false
|
||||
c[:log_auto_flush ] = true
|
||||
|
||||
c[:log_stream] = STDOUT
|
||||
c[:log_file] = nil
|
||||
# Or redirect logging into a file:
|
||||
# c[:log_file] = Merb.root / "log" / "development.log"
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
Merb.logger.info("Loaded STAGING Environment...")
|
||||
Merb::Config.use { |c|
|
||||
c[:exception_details] = false
|
||||
c[:reload_classes] = false
|
||||
c[:log_level] = :error
|
||||
|
||||
c[:log_file] = Merb.root / "log" / "staging.log"
|
||||
# or redirect logger using IO handle
|
||||
# c[:log_stream] = STDOUT
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
Merb.logger.info("Loaded TEST Environment...")
|
||||
Merb::Config.use { |c|
|
||||
c[:testing] = true
|
||||
c[:exception_details] = true
|
||||
c[:log_auto_flush ] = true
|
||||
# log less in testing environment
|
||||
c[:log_level] = :error
|
||||
|
||||
#c[:log_file] = Merb.root / "log" / "test.log"
|
||||
# or redirect logger using IO handle
|
||||
c[:log_stream] = STDOUT
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
# Go to http://wiki.merbivore.com/pages/init-rb
|
||||
|
||||
# Specify a specific version of a dependency
|
||||
# dependency "RedCloth", "> 3.0"
|
||||
dependency "merb-helpers", ">= 1.0.12"
|
||||
dependency "merb-assets", ">= 1.0.12"
|
||||
|
||||
# use_orm :none
|
||||
use_test :rspec
|
||||
use_template_engine :erb
|
||||
|
||||
Merb::Config.use do |c|
|
||||
c[:use_mutex] = false
|
||||
c[:session_store] = 'cookie' # can also be 'memory', 'memcache', 'container', 'datamapper
|
||||
|
||||
# cookie session store configuration
|
||||
c[:session_secret_key] = '04d4714e97846aec300bc25b3526a9fb942d9e3d' # required for cookie session store
|
||||
c[:session_id_key] = '_web_session_id' # cookie session id key, defaults to "_session_id"
|
||||
end
|
||||
|
||||
Merb::BootLoader.before_app_loads do
|
||||
# This will get executed after dependencies have been loaded but before your app's classes have loaded.
|
||||
end
|
||||
|
||||
Merb::BootLoader.after_app_loads do
|
||||
# This will get executed after your app's classes have been loaded.
|
||||
$: << "../"
|
||||
require "lib/net/clients/elasticsearch"
|
||||
$search = LogStash::Net::Clients::ElasticSearch.new("/opt/logstash/etc/logstashd.yaml")
|
||||
end
|
|
@ -1,11 +0,0 @@
|
|||
# use PathPrefix Middleware if :path_prefix is set in Merb::Config
|
||||
if prefix = ::Merb::Config[:path_prefix]
|
||||
use Merb::Rack::PathPrefix, prefix
|
||||
end
|
||||
|
||||
# comment this out if you are running merb behind a load balancer
|
||||
# that serves static files
|
||||
use Merb::Rack::Static, Merb.dir_for(:public)
|
||||
|
||||
# this is our main merb application
|
||||
run Merb::Rack::Application.new
|
|
@ -1,44 +0,0 @@
|
|||
# Merb::Router is the request routing mapper for the merb framework.
|
||||
#
|
||||
# You can route a specific URL to a controller / action pair:
|
||||
#
|
||||
# match("/contact").
|
||||
# to(:controller => "info", :action => "contact")
|
||||
#
|
||||
# You can define placeholder parts of the url with the :symbol notation. These
|
||||
# placeholders will be available in the params hash of your controllers. For example:
|
||||
#
|
||||
# match("/books/:book_id/:action").
|
||||
# to(:controller => "books")
|
||||
#
|
||||
# Or, use placeholders in the "to" results for more complicated routing, e.g.:
|
||||
#
|
||||
# match("/admin/:module/:controller/:action/:id").
|
||||
# to(:controller => ":module/:controller")
|
||||
#
|
||||
# You can specify conditions on the placeholder by passing a hash as the second
|
||||
# argument of "match"
|
||||
#
|
||||
# match("/registration/:course_name", :course_name => /^[a-z]{3,5}-\d{5}$/).
|
||||
# to(:controller => "registration")
|
||||
#
|
||||
# You can also use regular expressions, deferred routes, and many other options.
|
||||
# See merb/specs/merb/router.rb for a fairly complete usage sample.
|
||||
|
||||
Merb.logger.info("Compiling routes...")
|
||||
Merb::Router.prepare do
|
||||
# RESTful routes
|
||||
# resources :posts
|
||||
|
||||
# default page is search
|
||||
match('/').to(:controller => 'search', :action => 'index')
|
||||
|
||||
# This is the default route for /:controller/:action/:id
|
||||
# This is fine for most cases. If you're heavily using resource-based
|
||||
# routes, you may want to comment/remove this line to prevent
|
||||
# clients from calling your create or destroy actions with a GET
|
||||
default_routes
|
||||
|
||||
# Change this for your home page to be available at /
|
||||
# match('/').to(:controller => 'whatever', :action =>'index')
|
||||
end
|
File diff suppressed because it is too large
Load diff
|
@ -1,640 +0,0 @@
|
|||
|
||||
function setupPage(){
|
||||
hookUpActiveSearch();
|
||||
hookUpTabs();
|
||||
suppressPostbacks();
|
||||
var url_params = getUrlParams();
|
||||
if (url_params != null){
|
||||
loadUrlParams(url_params);
|
||||
}else{
|
||||
loadDefaults();
|
||||
}
|
||||
resizeDivs();
|
||||
window.onresize = function(){ resizeDivs(); };
|
||||
}
|
||||
|
||||
function getUrlParams(){
|
||||
var window_location = window.location.href
|
||||
var param_pos = window_location.search(/\?/)
|
||||
if (param_pos > 0){
|
||||
return(window_location.slice(param_pos, window_location.length));
|
||||
}else{
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
|
||||
function loadUrlParams(url_param){
|
||||
//get the tabs
|
||||
var t = getTabs();
|
||||
// now find our variables
|
||||
var s_params = /(\?)(a=.+?)(&)(name=.*)/;
|
||||
var results = url_param.match(s_params);
|
||||
url_anchor = results[2].replace(/a=/,'');
|
||||
|
||||
if (url_anchor.match(/M.+/)){//load the methods tab and scroller content
|
||||
setActiveTabAndLoadContent(t[0]);
|
||||
}else{
|
||||
if(url_anchor.match(/C.+/)){ //load the classes tab and scroller content
|
||||
setActiveTabAndLoadContent(t[1]);
|
||||
}else{
|
||||
if (url_anchor.match(/F.+/)){//load the files tab
|
||||
setActiveTabAndLoadContent(t[2]);
|
||||
}else{
|
||||
// default to loading the methods
|
||||
setActiveTabAndLoadContent(t[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
paramLoadOfContentAnchor(url_anchor + "_link");
|
||||
}
|
||||
|
||||
function updateUrlParams(anchor_id, name){
|
||||
//Also setting the page title
|
||||
//window.document.title = name + " method - MerbBrain.com ";
|
||||
|
||||
//updating the window location
|
||||
var current_href = window.location.href;
|
||||
//var m_name = name.replace("?","?");
|
||||
var rep_str = ".html?a=" + anchor_id + "&name=" + name;
|
||||
var new_href = current_href.replace(/\.html.*/, rep_str);
|
||||
if (new_href != current_href){
|
||||
window.location.href = new_href;
|
||||
}
|
||||
}
|
||||
|
||||
//does as it says...
|
||||
function hookUpActiveSearch(){
|
||||
|
||||
var s_field = $('searchForm').getInputs('text')[0];
|
||||
//var s_field = document.forms[0].searchText;
|
||||
Event.observe(s_field, 'keydown', function(event) {
|
||||
var el = Event.element(event);
|
||||
var key = event.which || event.keyCode;
|
||||
|
||||
switch (key) {
|
||||
case Event.KEY_RETURN:
|
||||
forceLoadOfContentAnchor(getCurrentAnchor());
|
||||
Event.stop(event);
|
||||
break;
|
||||
|
||||
case Event.KEY_UP:
|
||||
scrollListToElementOffset(getCurrentAnchor(),-1);
|
||||
break;
|
||||
|
||||
case Event.KEY_DOWN:
|
||||
scrollListToElementOffset(getCurrentAnchor(),1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Event.observe(s_field, 'keyup', function(event) {
|
||||
var el = Event.element(event);
|
||||
var key = event.which || event.keyCode;
|
||||
switch (key) {
|
||||
case Event.KEY_RETURN:
|
||||
Event.stop(event);
|
||||
break;
|
||||
|
||||
case Event.KEY_UP:
|
||||
break;
|
||||
|
||||
case Event.KEY_DOWN:
|
||||
break;
|
||||
|
||||
default:
|
||||
scrollToName(el.value);
|
||||
setSavedSearch(getCurrentTab(), el.value);
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Event.observe(s_field, 'keypress', function(event){
|
||||
var el = Event.element(event);
|
||||
var key = event.which || event.keyCode;
|
||||
switch (key) {
|
||||
case Event.KEY_RETURN:
|
||||
Event.stop(event);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//Event.observe(document, 'keypress', function(event){
|
||||
// var key = event.which || event.keyCode;
|
||||
// if (key == Event.KEY_TAB){
|
||||
// cycleNextTab();
|
||||
// Event.stop(event);
|
||||
// }
|
||||
//});
|
||||
}
|
||||
|
||||
function hookUpTabs(){
|
||||
|
||||
var tabs = getTabs();
|
||||
for(x=0; x < tabs.length; x++)
|
||||
{
|
||||
Event.observe(tabs[x], 'click', function(event){
|
||||
var el = Event.element(event);
|
||||
setActiveTabAndLoadContent(el);
|
||||
});
|
||||
//tabs[x].onclick = function (){ return setActiveTabAndLoadContent(this);}; //the prototype guys say this is bad..
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function suppressPostbacks(){
|
||||
Event.observe('searchForm', 'submit', function(event){
|
||||
Event.stop(event);
|
||||
});
|
||||
}
|
||||
|
||||
function loadDefaults(){
|
||||
var t = getTabs();
|
||||
setActiveTabAndLoadContent(t[0]); //default loading of the first tab
|
||||
}
|
||||
|
||||
function resizeDivs(){
|
||||
var inner_height = 700;
|
||||
if (window.innerHeight){
|
||||
inner_height = window.innerHeight; //all browsers except IE use this to determine the space available inside a window. Thank you Microsoft!!
|
||||
}else{
|
||||
if(document.documentElement.clientHeight > 0){ //IE uses this in 'strict' mode
|
||||
inner_height = document.documentElement.clientHeight;
|
||||
}else{
|
||||
inner_height = document.body.clientHeight; //IE uses this in 'quirks' mode
|
||||
}
|
||||
}
|
||||
$('rdocContent').style.height = (inner_height - 92) + "px";//Thankfully all browsers can agree on how to set the height of a div
|
||||
$('listScroller').style.height = (inner_height - 88) + "px";
|
||||
}
|
||||
|
||||
//The main function for handling clicks on the tabs
|
||||
function setActiveTabAndLoadContent(current_tab){
|
||||
changeLoadingStatus("on");
|
||||
var tab_string = String(current_tab.innerHTML).strip(); //thank you ProtoType!
|
||||
switch (tab_string){
|
||||
case "classes":
|
||||
setCurrentTab("classes");
|
||||
loadScrollerContent('fr_class_index.html');
|
||||
setSearchFieldValue(getSavedSearch("classes"));
|
||||
scrollToName(getSavedSearch("classes"));
|
||||
setSearchFocus();
|
||||
break;
|
||||
|
||||
case "files":
|
||||
setCurrentTab("files");
|
||||
loadScrollerContent('fr_file_index.html');
|
||||
setSearchFieldValue(getSavedSearch("files"));
|
||||
scrollToName(getSavedSearch("files"));
|
||||
setSearchFocus();
|
||||
break;
|
||||
|
||||
case "methods":
|
||||
setCurrentTab("methods");
|
||||
loadScrollerContent('fr_method_index.html');
|
||||
setSearchFieldValue(getSavedSearch("methods"));
|
||||
scrollToName(getSavedSearch("methods"));
|
||||
setSearchFocus();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
changeLoadingStatus("off");
|
||||
}
|
||||
|
||||
function cycleNextTab(){
|
||||
var currentT = getCurrentTab();
|
||||
var tabs = getTabs();
|
||||
if (currentT == "methods"){
|
||||
setActiveTabAndLoadContent(tabs[1]);
|
||||
setSearchFocus();
|
||||
}else{
|
||||
if (currentT == "classes"){
|
||||
setActiveTabAndLoadContent(tabs[2]);
|
||||
setSearchFocus();
|
||||
}else{
|
||||
if (currentT == "files"){
|
||||
setActiveTabAndLoadContent(tabs[0]);
|
||||
setSearchFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getTabs(){
|
||||
return($('groupType').getElementsByTagName('li'));
|
||||
}
|
||||
|
||||
var Active_Tab = "";
|
||||
function getCurrentTab(){
|
||||
return Active_Tab;
|
||||
}
|
||||
|
||||
function setCurrentTab(tab_name){
|
||||
var tabs = getTabs();
|
||||
for(x=0; x < tabs.length; x++)
|
||||
{
|
||||
if(tabs[x].innerHTML.strip() == tab_name) //W00t!!! String.prototype.strip!
|
||||
{
|
||||
tabs[x].className = "activeLi";
|
||||
Active_Tab = tab_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
tabs[x].className = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//These globals should not be used globally (hence the getters and setters)
|
||||
var File_Search = "";
|
||||
var Method_Search = "";
|
||||
var Class_Search = "";
|
||||
function setSavedSearch(tab_name, s_val){
|
||||
switch(tab_name){
|
||||
case "methods":
|
||||
Method_Search = s_val;
|
||||
break;
|
||||
case "files":
|
||||
File_Search = s_val;
|
||||
break;
|
||||
case "classes":
|
||||
Class_Search = s_val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function getSavedSearch(tab_name){
|
||||
switch(tab_name){
|
||||
case "methods":
|
||||
return (Method_Search);
|
||||
break;
|
||||
case "files":
|
||||
return (File_Search);
|
||||
break;
|
||||
case "classes":
|
||||
return (Class_Search);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//These globals handle the history stack
|
||||
|
||||
|
||||
function setListScrollerContent(s){
|
||||
|
||||
$('listScroller').innerHTML = s;
|
||||
}
|
||||
|
||||
function setMainContent(s){
|
||||
|
||||
$('rdocContent').innerHTML = s;
|
||||
}
|
||||
|
||||
function setSearchFieldValue(s){
|
||||
|
||||
document.forms[0].searchText.value = s;
|
||||
}
|
||||
|
||||
function getSearchFieldValue(){
|
||||
|
||||
return Form.Element.getValue('searchText');
|
||||
}
|
||||
|
||||
function setSearchFocus(){
|
||||
|
||||
document.forms[0].searchText.focus();
|
||||
}
|
||||
|
||||
var Anchor_ID_Of_Current = null; // holds the last highlighted anchor tag in the scroll lsit
|
||||
function getCurrentAnchor(){
|
||||
return(Anchor_ID_Of_Current);
|
||||
}
|
||||
|
||||
function setCurrentAnchor(a_id){
|
||||
Anchor_ID_Of_Current = a_id;
|
||||
}
|
||||
|
||||
//var Index_Of_Current = 0; //holds the last highlighted index
|
||||
//function getCurrentIndex(){
|
||||
// return (Index_Of_Current);
|
||||
//}
|
||||
|
||||
//function setCurrentIndex(new_i){
|
||||
// Index_Of_Current = new_i;
|
||||
//}
|
||||
|
||||
function loadScrollerContent(url){
|
||||
|
||||
var scrollerHtml = new Ajax.Request(url, {
|
||||
asynchronous: false,
|
||||
method: 'get',
|
||||
onComplete: function(method_data) {
|
||||
setListScrollerContent(method_data.responseText);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//called primarily from the links inside the scroller list
|
||||
//loads the main page div then jumps to the anchor/element with id
|
||||
function loadContent(url, anchor_id){
|
||||
|
||||
var mainHtml = new Ajax.Request(url, {
|
||||
method: 'get',
|
||||
onLoading: changeLoadingStatus("on"),
|
||||
onSuccess: function(method_data) {
|
||||
setMainContent(method_data.responseText);},
|
||||
onComplete: function(request) {
|
||||
changeLoadingStatus("off");
|
||||
new jumpToAnchor(anchor_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//An alternative function that also will stuff the index history for methods, files, classes
|
||||
function loadIndexContent(url, anchor_id, name, scope)
|
||||
{
|
||||
if (From_URL_Param == true){
|
||||
var mainHtml = new Ajax.Request(url, {
|
||||
method: 'get',
|
||||
onLoading: changeLoadingStatus("on"),
|
||||
onSuccess: function(method_data) {
|
||||
setMainContent(method_data.responseText);},
|
||||
onComplete: function(request) {
|
||||
changeLoadingStatus("off");
|
||||
updateBrowserBar(name, anchor_id, scope);
|
||||
new jumpToAnchor(anchor_id);}
|
||||
});
|
||||
From_URL_Param = false;
|
||||
}else{
|
||||
updateUrlParams(anchor_id, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function updateBrowserBar(name, anchor_id, scope){
|
||||
if (getCurrentTab() == "methods"){
|
||||
$('browserBarInfo').update("<small>class/module:</small> <a href=\"#\" onclick=\"jumpToTop();\">" + scope + "</a> <small>method:</small> <strong><a href=\"#\" onclick=\"jumpToAnchor('"+ anchor_id +"')\">" + name + "</a></strong> ");
|
||||
}else{ if(getCurrentTab() == "classes"){
|
||||
$('browserBarInfo').update("<small>class/module:</small> <a href=\"#\" onclick=\"jumpToTop();\">" + scope + "::" + name + "</strong> ");
|
||||
}else{
|
||||
$('browserBarInfo').update("<small>file:</small> <a href=\"#\" onclick=\"jumpToTop();\">" + scope + "/" + name + "</strong> ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Force loads the contents of the index of the current scroller list. It does this by
|
||||
// pulling the onclick method out and executing it manually.
|
||||
function forceLoadOfContent(index_to_load){
|
||||
var scroller = $('listScroller');
|
||||
var a_array = scroller.getElementsByTagName('a');
|
||||
if ((index_to_load >= 0) && (index_to_load < a_array.length)){
|
||||
var load_element = a_array[index_to_load];
|
||||
var el_text = load_element.innerHTML.strip();
|
||||
setSearchFieldValue(el_text);
|
||||
setSavedSearch(getCurrentTab(), el_text);
|
||||
eval("new " + load_element.onclick);
|
||||
}
|
||||
}
|
||||
|
||||
function forceLoadOfContentAnchor(anchor_id){
|
||||
|
||||
var load_element = $(anchor_id);
|
||||
if (load_element != null){
|
||||
var el_text = load_element.innerHTML.strip();
|
||||
setSearchFieldValue(el_text);
|
||||
scrollToAnchor(anchor_id);
|
||||
setSavedSearch(getCurrentTab(), el_text);
|
||||
eval("new " + load_element.onclick);
|
||||
}
|
||||
}
|
||||
|
||||
var From_URL_Param = false;
|
||||
function paramLoadOfContentAnchor(anchor_id){
|
||||
From_URL_Param = true;
|
||||
forceLoadOfContentAnchor(anchor_id);
|
||||
}
|
||||
|
||||
//this handles the up/down keystrokes to move the selection of items in the list
|
||||
function scrollListToElementOffset(anchor_id, offset){
|
||||
var scroller = $('listScroller');
|
||||
var a_array = scroller.getElementsByTagName('a');
|
||||
var current_index = findIndexOfAnchor(a_array, anchor_id);
|
||||
if ((current_index >= 0) && (current_index < a_array.length)){
|
||||
scrollListToAnchor(a_array[current_index + offset].id);
|
||||
setListActiveAnchor(a_array[current_index + offset].id);
|
||||
}
|
||||
}
|
||||
|
||||
function findIndexOfAnchor(a_array, anchor_id){
|
||||
var found=false;
|
||||
var counter = 0;
|
||||
while(!found && counter < a_array.length){
|
||||
if (a_array[counter].id == anchor_id){
|
||||
found = true;
|
||||
}else{
|
||||
counter +=1;
|
||||
}
|
||||
}
|
||||
return(counter);
|
||||
}
|
||||
|
||||
function scrollToName(searcher_name){
|
||||
|
||||
var scroller = $('listScroller');
|
||||
var a_array = scroller.getElementsByTagName('a');
|
||||
|
||||
if (!searcher_name.match(new RegExp(/\s+/))){ //if searcher name is blank
|
||||
|
||||
var searcher_pattern = new RegExp("^"+searcher_name, "i"); //the "i" is for case INsensitive
|
||||
var found_index = -1;
|
||||
|
||||
var found = false;
|
||||
var x = 0;
|
||||
while(!found && x < a_array.length){
|
||||
if(a_array[x].innerHTML.match(searcher_pattern)){
|
||||
found = true;
|
||||
found_index = x;
|
||||
}
|
||||
else{
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
// // an attempt at binary searching... have not given up on this yet...
|
||||
//found_index = binSearcher(searcher_pattern, a_array, 0, a_array.length);
|
||||
|
||||
if ((found_index >= 0) && (found_index < a_array.length)){
|
||||
|
||||
scrollListToAnchor(a_array[found_index].id);//scroll to the item
|
||||
setListActiveAnchor(a_array[found_index].id);//highlight the item
|
||||
}
|
||||
}else{ //since searcher name is blank
|
||||
//scrollListToIndex(a_array, 0);//scroll to the item
|
||||
//setListActiveItem(a_array, 0);//highlight the item
|
||||
}
|
||||
}
|
||||
|
||||
function scrollToAnchor(anchor_id){
|
||||
var scroller = $('listScroller');
|
||||
if ($(anchor_id) != null){
|
||||
scrollListToAnchor(anchor_id);
|
||||
setListActiveAnchor(anchor_id);
|
||||
}
|
||||
}
|
||||
|
||||
function getY(element){
|
||||
|
||||
var y = 0;
|
||||
for( var e = element; e; e = e.offsetParent)//iterate the offset Parents
|
||||
{
|
||||
y += e.offsetTop; //add up the offsetTop values
|
||||
}
|
||||
//for( e = element.parentNode; e && e != document.body; e = e.parentNode)
|
||||
// if (e.scrollTop) y -= e.scrollTop; //subtract scrollbar values
|
||||
return y;
|
||||
}
|
||||
|
||||
//function setListActiveItem(item_array, active_index){
|
||||
//
|
||||
// item_array[getCurrentIndex()].className = "";
|
||||
// setCurrentIndex(active_index);
|
||||
// item_array[getCurrentIndex()].className = "activeA"; //setting the active class name
|
||||
//}
|
||||
|
||||
function setListActiveAnchor(active_anchor){
|
||||
if ((getCurrentAnchor() != null) && ($(getCurrentAnchor()) != null)){
|
||||
$(getCurrentAnchor()).className = "";
|
||||
}
|
||||
setCurrentAnchor(active_anchor);
|
||||
$(getCurrentAnchor()).className = "activeA";
|
||||
|
||||
}
|
||||
|
||||
//handles the scrolling of the list and setting of the current index
|
||||
//function scrollListToIndex(a_array, scroll_index){
|
||||
// if (scroll_index > 0){
|
||||
// var scroller = $('listScroller');
|
||||
// scroller.scrollTop = getY(a_array[scroll_index]) - 120; //the -120 is what keeps it from going to the top...
|
||||
// }
|
||||
//}
|
||||
|
||||
function scrollListToAnchor(scroll2_anchor){
|
||||
var scroller = $('listScroller');
|
||||
scroller.scrollTop = getY($(scroll2_anchor)) - 120;
|
||||
}
|
||||
|
||||
function jumpToAnchor(anchor_id){
|
||||
|
||||
var contentScroller = $('rdocContent');
|
||||
var a_div = $(anchor_id);
|
||||
contentScroller.scrollTop = getY(a_div) - 80; //80 is the offset to adjust scroll point
|
||||
var a_title = $(anchor_id + "_title");
|
||||
a_title.style.backgroundColor = "#222";
|
||||
a_title.style.color = "#FFF";
|
||||
a_title.style.padding = "3px";
|
||||
// a_title.style.borderBottom = "2px solid #ccc";
|
||||
|
||||
//other attempts
|
||||
//a_div.className = "activeMethod"; //setting the active class name
|
||||
//a_div.style.backgroundColor = "#ffc";
|
||||
//var titles = a_div.getElementsByClassName("title");
|
||||
//titles[0].className = "activeTitle";
|
||||
|
||||
}
|
||||
|
||||
function jumpToTop(){
|
||||
$('rdocContent').scrollTop = 0;
|
||||
}
|
||||
|
||||
function changeLoadingStatus(status){
|
||||
if (status == "on"){
|
||||
$('loadingStatus').show();
|
||||
}
|
||||
else{
|
||||
$('loadingStatus').hide();
|
||||
}
|
||||
}
|
||||
|
||||
//************* Misc functions (mostly from the old rdocs) ***********************
|
||||
//snagged code from the old templating system
|
||||
function toggleSource( id ){
|
||||
|
||||
var elem
|
||||
var link
|
||||
|
||||
if( document.getElementById )
|
||||
{
|
||||
elem = document.getElementById( id )
|
||||
link = document.getElementById( "l_" + id )
|
||||
}
|
||||
else if ( document.all )
|
||||
{
|
||||
elem = eval( "document.all." + id )
|
||||
link = eval( "document.all.l_" + id )
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if( elem.style.display == "block" )
|
||||
{
|
||||
elem.style.display = "none"
|
||||
link.innerHTML = "show source"
|
||||
}
|
||||
else
|
||||
{
|
||||
elem.style.display = "block"
|
||||
link.innerHTML = "hide source"
|
||||
}
|
||||
}
|
||||
|
||||
function openCode( url ){
|
||||
window.open( url, "SOURCE_CODE", "width=400,height=400,scrollbars=yes" )
|
||||
}
|
||||
|
||||
//this function handles the ajax calling and afterits loaded the jumping to the anchor...
|
||||
function jsHref(url){
|
||||
//alert(url);
|
||||
var mainHtml = new Ajax.Request(url, {
|
||||
method: 'get',
|
||||
onSuccess: function(method_data) {
|
||||
setMainContent(method_data.responseText);}
|
||||
});
|
||||
}
|
||||
|
||||
//function comparePatterns(string, regexp){
|
||||
// var direction = 0;
|
||||
//
|
||||
//
|
||||
// return (direction)
|
||||
//}
|
||||
|
||||
////returns the index of the element
|
||||
//function binSearcher(regexp_pattern, list, start_index, stop_index){
|
||||
// //divide the list in half
|
||||
// var split_point = 0;
|
||||
// split_point = parseInt((stop_index - start_index)/2);
|
||||
// direction = comparePatterns(list[split_point].innerHTML, regexp_pattern);
|
||||
// if(direction < 0)
|
||||
// return (binSearcher(regexp_pattern, list, start_index, split_point));
|
||||
// else
|
||||
// if(direction > 0)
|
||||
// return (binSearcher(regexp_pattern, list, split_point, stop_index));
|
||||
// else
|
||||
// return(split_point);
|
||||
//
|
||||
//}
|
||||
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<head>
|
||||
<title>Documentation</title>
|
||||
<meta content='text/html;charset=UTF-8' http-equiv='content-type' />
|
||||
<meta content='all' name='robots' />
|
||||
<meta content='text/html;charset=utf-8' http-equiv='content-type' />
|
||||
<meta content='no' http-equiv='msthemecompatible' />
|
||||
<meta content='false' http-equiv='imagetoolbar' />
|
||||
<link href="generators/template/merb/merb.css" media="screen" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id='content'>
|
||||
<div class='wrap_to_center'>
|
||||
<div class='full_width' id='content_top'>
|
||||
<div id='content_bottom'>
|
||||
<div id='content_full'>
|
||||
<h1>Documentation</h1>
|
||||
<ul>
|
||||
<% @directories.each do |directory| %>
|
||||
<li id="merb-core"><a href="<%= directory %>/index.html"><%= directory.capitalize %></a></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
<div class='wrap_to_center'>
|
||||
<p>
|
||||
© 2008, Ezra Zygmuntowicz | Merb is released under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT License</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,252 +0,0 @@
|
|||
html, body, div, span, applet, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,a, abbr, acronym, address, big, cite, code,del, dfn, em, font, img, ins, kbd, q, s, samp,small, strike, strong, sub, sup, tt, var,dl, dt, dd, ol, ul, li,fieldset, form, label, legend,table, caption, tbody, tfoot, thead, tr, th, td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-weight: inherit;
|
||||
font-style: inherit;
|
||||
font-size: 100%;
|
||||
font-family: inherit;
|
||||
vertical-align: baseline; }
|
||||
|
||||
/* GENERAL RULES */
|
||||
|
||||
body {
|
||||
background: #000 url(../img/body.gif) repeat-x bottom center;
|
||||
color: #000;
|
||||
font: normal 12px "Lucida Grande", "Arial", sans-serif;
|
||||
line-height: 1;
|
||||
}
|
||||
ul {list-style-type: none;}
|
||||
#content_full ul.revisions{list-style-type: disc;}
|
||||
#content_full ul.revisions li{margin-left: 15px;padding: 3px 0;}
|
||||
li a {display: block;}
|
||||
#content_full ul.revisions li a{display: inline;}
|
||||
strong {font-weight: bold;}
|
||||
table {border-collapse: separate;border-spacing: 0; }
|
||||
caption, th, td {text-align: left;font-weight: normal; }
|
||||
.invisible {display: none;}
|
||||
.full_width {width:100%;}
|
||||
|
||||
/* LAYOUT */
|
||||
|
||||
.wrap_to_center, #foot {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
#content {width: 100%;}
|
||||
|
||||
#content_top {
|
||||
background: #fff url(../img/content_top.gif) no-repeat top center;
|
||||
float:left;
|
||||
margin:25px 0px;
|
||||
width:100%;
|
||||
}
|
||||
#content_bottom {
|
||||
background: url(../img/content_bottom.gif) no-repeat bottom center;
|
||||
width:100%;
|
||||
float:left;
|
||||
}
|
||||
#content_main {
|
||||
float:left;
|
||||
margin: 10px 20px 20px 20px;
|
||||
width:506px;
|
||||
}
|
||||
#content p {
|
||||
line-height:17px;
|
||||
}
|
||||
#content_full {margin: 10px 20px 20px 20px;}
|
||||
|
||||
/* HEADER & NAVIGATION */
|
||||
|
||||
#header {
|
||||
background: #1db900 url(../img/header_waves.gif) repeat-x top center;
|
||||
height:74px;
|
||||
width: 100%;
|
||||
}
|
||||
#waves {
|
||||
background: url(../img/header_waves.gif)no-repeat top left;
|
||||
height:74px;
|
||||
width:980px;
|
||||
}
|
||||
#header img {margin-top:8px; float:left;}
|
||||
#header a {color:#fff; text-decoration:none;}
|
||||
#header a:hover {color:#000;}
|
||||
ul#nav {float:right;display:block;width:43.3em;margin-top:25px;}
|
||||
ul#nav li {display:block;float:left;}
|
||||
ul#nav li a {display:block;float:left;margin:0px 5px;padding:6px 9px 31px 9px;}
|
||||
ul#nav li a:hover {background:url(../img/header_hover.gif) repeat-x bottom center;}
|
||||
ul#nav li a#active {background:url(../img/header_arrow.gif)no-repeat bottom center;}
|
||||
ul#nav li.last a {margin-right:0;}
|
||||
|
||||
/* TEXT FORMATTING */
|
||||
|
||||
h1 {
|
||||
border-bottom:2px solid #ccc;
|
||||
color:#000;
|
||||
font:bold 28px "Arial" sans-serif;
|
||||
letter-spacing:1px;
|
||||
margin:20px 0px;
|
||||
text-align:left;
|
||||
width:100%;
|
||||
}
|
||||
h1.home {
|
||||
border:0;
|
||||
color:#fff;
|
||||
font-size:36px;
|
||||
margin:20px 0px;
|
||||
text-align:center;
|
||||
}
|
||||
h2 {
|
||||
color:#7aad00;
|
||||
font:bold 22px "Lucida Grande" sans-serif;
|
||||
margin:10px 0px;
|
||||
}
|
||||
h3 {
|
||||
font:bold 16px "Lucida Grande";
|
||||
margin:10px 0px;
|
||||
}
|
||||
#content a {color:#d7ff00;}
|
||||
#content a:hover {background:#d7ff00;color:#000;}
|
||||
#content_main ul {margin:10px 0px;}
|
||||
#content_main ul li {
|
||||
background: url(../img/li.gif) no-repeat left center;
|
||||
padding: 4px 4px 4px 16px;
|
||||
font-weight:bold;
|
||||
}
|
||||
p {margin-bottom:12px;}
|
||||
#content_main a,#content_full a {color:#11b716;font-weight:bold;}
|
||||
#content_main a:hover,#content_full a:hover {background:#22d716;}
|
||||
pre {
|
||||
background:#222;
|
||||
color:#fff;
|
||||
font:12px "Courier" serif;
|
||||
line-height:18px;
|
||||
padding: 12px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
code {
|
||||
font:bold 12px "Courier" serif;
|
||||
}
|
||||
pre code {font-weight:normal;}
|
||||
|
||||
/* SIDEBAR FOR CONTENT */
|
||||
|
||||
#content_sidebar {
|
||||
float: left;
|
||||
margin: 20px 20px 15px 10px;
|
||||
width: 224px;
|
||||
}
|
||||
.sidebar_top {
|
||||
background:#868686 url(../img/sidebar_top.gif) no-repeat top center;
|
||||
margin-bottom:12px;
|
||||
width:224px;
|
||||
}
|
||||
dl.sidebar_bottom {
|
||||
background: url(../img/sidebar_bottom.gif) no-repeat bottom center;
|
||||
padding:12px;
|
||||
}
|
||||
dl.sidebar_bottom dt {
|
||||
color:#fff;
|
||||
font:bold 14px "Lucida Grande" sans-serif;
|
||||
margin-bottom:6px;
|
||||
}
|
||||
dl.sidebar_bottom dd {padding:3px 0px;}
|
||||
#content_sidebar p {padding:10px 0px;}
|
||||
p#rss a {
|
||||
background: url(../img/rss.gif) no-repeat left center;
|
||||
color:#000;
|
||||
font:bold 14px "Lucida Grande";
|
||||
padding: 8px 6px 8px 34px;
|
||||
text-decoration:none;
|
||||
}
|
||||
p#rss a:hover {
|
||||
background: url(../img/rss.gif) no-repeat left center;
|
||||
background-color:#fff;
|
||||
text-decoration:underline;
|
||||
}
|
||||
|
||||
/* FOOTER */
|
||||
|
||||
#footer {background:#444; clear:both;}
|
||||
#footer p {padding:12px; color:#999; margin:0; text-align:center;}
|
||||
|
||||
/* FEATURES PAGE */
|
||||
.feature {
|
||||
background-repeat:no-repeat;
|
||||
background-position:top left;
|
||||
border-bottom:2px solid #ccc;
|
||||
padding-left:150px;
|
||||
}
|
||||
div#speed {background-image: url(../img/feature_speed.gif);}
|
||||
div#light {background-image: url(../img/feature_light.gif);}
|
||||
div#power {background-image: url(../img/feature_power.gif);}
|
||||
|
||||
.quicklinks_top {
|
||||
background:#868686 url(../img/quicklinks_top.gif) no-repeat top center;
|
||||
float:right;
|
||||
margin-bottom:12px;
|
||||
width:169px;
|
||||
}
|
||||
ul.quicklinks_bottom {
|
||||
background: url(../img/quicklinks_bottom.gif) no-repeat bottom center;
|
||||
padding:12px;
|
||||
}
|
||||
ul.quicklinks_bottom li {
|
||||
display:block;
|
||||
padding:3px 0px;
|
||||
}
|
||||
#content_full ul.quicklinks_bottom li a{
|
||||
color:#d7ff00;
|
||||
display:inline;
|
||||
}
|
||||
#content_full ul.quicklinks_bottom li a:hover {
|
||||
background:#d7ff00;
|
||||
color:#000;
|
||||
}
|
||||
|
||||
/* DOCUMENTATION PAGE */
|
||||
.sub-framework {
|
||||
border-bottom:2px solid #ccc;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* ICONS FOR HOMEPAGE */
|
||||
|
||||
#icons_top {
|
||||
background: url(../img/icons_top.gif) no-repeat top center;
|
||||
float:left;
|
||||
width:800px;
|
||||
}
|
||||
#icons_bottom {
|
||||
background: url(../img/icons_bottom.gif) no-repeat bottom center;
|
||||
float:left;
|
||||
width:800px;
|
||||
}
|
||||
#icons_top dl {
|
||||
color:#fff;
|
||||
float:left;
|
||||
width: 224px;
|
||||
padding: 15px 20px;
|
||||
}
|
||||
#icons_top dt {
|
||||
background-repeat:no-repeat;
|
||||
background-position:center 2.5em;
|
||||
color:#35d726;
|
||||
font:bold 18px 'Lucida Grande' sans-serif;
|
||||
padding: 6px 6px 150px 6px;
|
||||
text-align:center;
|
||||
}
|
||||
#icons_top dd {
|
||||
font: 11px "Lucida Grande";
|
||||
line-height:18px;
|
||||
text-align:center;
|
||||
}
|
||||
dl#speed, dl#light {border-right:1px solid #444;}
|
||||
dl#light, dl#power {border-left:1px solid #000;}
|
||||
dl#speed dt {background-image: url(../img/icon_speed.gif);}
|
||||
dl#light dt {background-image: url(../img/icon_light.gif);}
|
||||
dl#power dt {background-image: url(../img/icon_power.gif);}
|
|
@ -1,351 +0,0 @@
|
|||
module RDoc
|
||||
module Page
|
||||
|
||||
STYLE = File.read(File.join(File.dirname(__FILE__), 'merb_doc_styles.css'))
|
||||
FONTS = ""
|
||||
|
||||
###################################################################
|
||||
|
||||
CLASS_PAGE = <<HTML
|
||||
<div id="%class_seq%">
|
||||
<div class='banner'>
|
||||
<span class="file-title-prefix">%classmod%</span><br />%full_name%<br/>
|
||||
In:
|
||||
START:infiles
|
||||
<a href="#" onclick="jsHref('%full_path_url%');">%full_path%</a>
|
||||
IF:cvsurl
|
||||
(<a href="#" onclick="jsHref('%cvsurl%');">CVS</a>)
|
||||
ENDIF:cvsurl
|
||||
END:infiles
|
||||
|
||||
IF:parent
|
||||
Parent:
|
||||
IF:par_url
|
||||
<a href="#" onclick="jsHref('%par_url%');">
|
||||
ENDIF:par_url
|
||||
%parent%
|
||||
IF:par_url
|
||||
</a>
|
||||
ENDIF:par_url
|
||||
ENDIF:parent
|
||||
</div>
|
||||
HTML
|
||||
|
||||
###################################################################
|
||||
|
||||
METHOD_LIST = <<HTML
|
||||
<div id="content">
|
||||
IF:diagram
|
||||
<table cellpadding='0' cellspacing='0' border='0' width="100%"><tr><td align="center">
|
||||
%diagram%
|
||||
</td></tr></table>
|
||||
ENDIF:diagram
|
||||
|
||||
IF:description
|
||||
<div class="description">%description%</div>
|
||||
ENDIF:description
|
||||
|
||||
IF:requires
|
||||
<div class="sectiontitle">Required Files</div>
|
||||
<ul>
|
||||
START:requires
|
||||
<li><a href="#" onclick="jsHref('%href%');">%name%</a></li>
|
||||
END:requires
|
||||
</ul>
|
||||
ENDIF:requires
|
||||
|
||||
IF:toc
|
||||
<div class="sectiontitle">Contents</div>
|
||||
<ul>
|
||||
START:toc
|
||||
<li><a href="#" onclick="jsHref('%href%');">%secname%</a></li>
|
||||
END:toc
|
||||
</ul>
|
||||
ENDIF:toc
|
||||
|
||||
IF:methods
|
||||
<div class="sectiontitle">Methods</div>
|
||||
<ul>
|
||||
START:methods
|
||||
<li><a href="index.html?a=%href%&name=%name%" >%name%</a></li>
|
||||
END:methods
|
||||
</ul>
|
||||
ENDIF:methods
|
||||
|
||||
IF:includes
|
||||
<div class="sectiontitle">Included Modules</div>
|
||||
<ul>
|
||||
START:includes
|
||||
<li><a href="#" onclick="jsHref('%href%');">%name%</a></li>
|
||||
END:includes
|
||||
</ul>
|
||||
ENDIF:includes
|
||||
|
||||
START:sections
|
||||
IF:sectitle
|
||||
<div class="sectiontitle"><a href="%secsequence%">%sectitle%</a></div>
|
||||
IF:seccomment
|
||||
<div class="description">
|
||||
%seccomment%
|
||||
</div>
|
||||
ENDIF:seccomment
|
||||
ENDIF:sectitle
|
||||
|
||||
IF:classlist
|
||||
<div class="sectiontitle">Classes and Modules</div>
|
||||
%classlist%
|
||||
ENDIF:classlist
|
||||
|
||||
IF:constants
|
||||
<div class="sectiontitle">Constants</div>
|
||||
<table border='0' cellpadding='5'>
|
||||
START:constants
|
||||
<tr valign='top'>
|
||||
<td class="attr-name">%name%</td>
|
||||
<td>=</td>
|
||||
<td class="attr-value">%value%</td>
|
||||
</tr>
|
||||
IF:desc
|
||||
<tr valign='top'>
|
||||
<td> </td>
|
||||
<td colspan="2" class="attr-desc">%desc%</td>
|
||||
</tr>
|
||||
ENDIF:desc
|
||||
END:constants
|
||||
</table>
|
||||
ENDIF:constants
|
||||
|
||||
IF:attributes
|
||||
<div class="sectiontitle">Attributes</div>
|
||||
<table border='0' cellpadding='5'>
|
||||
START:attributes
|
||||
<tr valign='top'>
|
||||
<td class='attr-rw'>
|
||||
IF:rw
|
||||
[%rw%]
|
||||
ENDIF:rw
|
||||
</td>
|
||||
<td class='attr-name'>%name%</td>
|
||||
<td class='attr-desc'>%a_desc%</td>
|
||||
</tr>
|
||||
END:attributes
|
||||
</table>
|
||||
ENDIF:attributes
|
||||
|
||||
IF:method_list
|
||||
START:method_list
|
||||
IF:methods
|
||||
<div class="sectiontitle">%type% %category% methods</div>
|
||||
START:methods
|
||||
<div id="%m_seq%" class="method">
|
||||
<div id="%m_seq%_title" class="title">
|
||||
IF:callseq
|
||||
<b>%callseq%</b>
|
||||
ENDIF:callseq
|
||||
IFNOT:callseq
|
||||
<b>%name%</b>%params%
|
||||
ENDIF:callseq
|
||||
IF:codeurl
|
||||
[ <a href="javascript:openCode('%codeurl%')">source</a> ]
|
||||
ENDIF:codeurl
|
||||
</div>
|
||||
IF:m_desc
|
||||
<div class="description">
|
||||
%m_desc%
|
||||
</div>
|
||||
ENDIF:m_desc
|
||||
IF:aka
|
||||
<div class="aka">
|
||||
This method is also aliased as
|
||||
START:aka
|
||||
<a href="index.html?a=%aref%&name=%name%">%name%</a>
|
||||
END:aka
|
||||
</div>
|
||||
ENDIF:aka
|
||||
IF:sourcecode
|
||||
<div class="sourcecode">
|
||||
<p class="source-link">[ <a href="javascript:toggleSource('%aref%_source')" id="l_%aref%_source">show source</a> ]</p>
|
||||
<div id="%aref%_source" class="dyn-source">
|
||||
<pre>
|
||||
%sourcecode%
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
ENDIF:sourcecode
|
||||
</div>
|
||||
END:methods
|
||||
ENDIF:methods
|
||||
END:method_list
|
||||
ENDIF:method_list
|
||||
END:sections
|
||||
</div>
|
||||
HTML
|
||||
|
||||
|
||||
|
||||
|
||||
BODY = <<ENDBODY
|
||||
!INCLUDE! <!-- banner header -->
|
||||
|
||||
<div id="bodyContent" >
|
||||
#{METHOD_LIST}
|
||||
</div>
|
||||
|
||||
ENDBODY
|
||||
|
||||
|
||||
|
||||
SRC_BODY = <<ENDSRCBODY
|
||||
!INCLUDE! <!-- banner header -->
|
||||
|
||||
<div id="bodyContent" >
|
||||
<h2>Source Code</h2>
|
||||
<pre>%file_source_code%</pre>
|
||||
</div>
|
||||
ENDSRCBODY
|
||||
|
||||
|
||||
###################### File Page ##########################
|
||||
FILE_PAGE = <<HTML
|
||||
<div id="fileHeader">
|
||||
<h1>%short_name%</h1>
|
||||
<table class="header-table">
|
||||
<tr class="top-aligned-row">
|
||||
<td><strong>Path:</strong></td>
|
||||
<td>%full_path%
|
||||
IF:cvsurl
|
||||
(<a href="%cvsurl%"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
|
||||
ENDIF:cvsurl
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="top-aligned-row">
|
||||
<td><strong>Last Update:</strong></td>
|
||||
<td>%dtm_modified%</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
HTML
|
||||
|
||||
|
||||
#### This is not used but kept for historical purposes
|
||||
########################## Source code ##########################
|
||||
# Separate page onlye
|
||||
|
||||
SRC_PAGE = <<HTML
|
||||
<html>
|
||||
<head><title>%title%</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
|
||||
<style>
|
||||
.ruby-comment { color: green; font-style: italic }
|
||||
.ruby-constant { color: #4433aa; font-weight: bold; }
|
||||
.ruby-identifier { color: #222222; }
|
||||
.ruby-ivar { color: #2233dd; }
|
||||
.ruby-keyword { color: #3333FF; font-weight: bold }
|
||||
.ruby-node { color: #777777; }
|
||||
.ruby-operator { color: #111111; }
|
||||
.ruby-regexp { color: #662222; }
|
||||
.ruby-value { color: #662222; font-style: italic }
|
||||
.kw { color: #3333FF; font-weight: bold }
|
||||
.cmt { color: green; font-style: italic }
|
||||
.str { color: #662222; font-style: italic }
|
||||
.re { color: #662222; }
|
||||
</style>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<pre>%code%</pre>
|
||||
</body>
|
||||
</html>
|
||||
HTML
|
||||
|
||||
########################### source page body ###################
|
||||
|
||||
SCR_CODE_BODY = <<HTML
|
||||
<div id="source">
|
||||
%source_code%
|
||||
</div>
|
||||
|
||||
HTML
|
||||
|
||||
########################## Index ################################
|
||||
|
||||
FR_INDEX_BODY = <<HTML
|
||||
!INCLUDE!
|
||||
HTML
|
||||
|
||||
FILE_INDEX = <<HTML
|
||||
<ul>
|
||||
START:entries
|
||||
<li><a id="%seq_id%_link" href="index.html?a=%seq_id%&name=%name%" onclick="loadIndexContent('%href%','%seq_id%','%name%', '%scope%');">%name%</a><small>%scope%</small></li>
|
||||
END:entries
|
||||
</ul>
|
||||
HTML
|
||||
|
||||
CLASS_INDEX = FILE_INDEX
|
||||
METHOD_INDEX = FILE_INDEX
|
||||
|
||||
INDEX = <<HTML
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta name="description" content="A nifty way to interact with the Merb API" />
|
||||
<meta name="author" content="created by Brian Chamberlain. You can contact me using 'blchamberlain' on the gmail." />
|
||||
<meta name="keywords" content="merb, ruby, purple, monkey, dishwasher" />
|
||||
<title>Merb | %title% API Documentation</title>
|
||||
<link rel="stylesheet" href="http://merbivore.com/documentation/stylesheet.css" type="text/css" media="screen" />
|
||||
<script type="text/javascript" src="http://merbivore.com/documentation/prototype.js" ></script>
|
||||
<script type="text/javascript" src="http://merbivore.com/documentation/api_grease.js" ></script>
|
||||
</head>
|
||||
<body onload="setupPage();">
|
||||
<ul id="groupType">
|
||||
<li>methods</li>
|
||||
<li>classes</li>
|
||||
<li>files</li>
|
||||
<li id="loadingStatus" style="display:none;"> loading...</li>
|
||||
</ul>
|
||||
<div id="listFrame">
|
||||
<div id="listSearch">
|
||||
<form id="searchForm" method="get" action="#" onsubmit="return false">
|
||||
<input type="text" name="searchText" id="searchTextField" size="30" autocomplete="off" />
|
||||
</form>
|
||||
</div>
|
||||
<div id="listScroller">
|
||||
Loading via ajax... this could take a sec.
|
||||
</div>
|
||||
</div>
|
||||
<div id="browserBar">
|
||||
<span id="browserBarInfo">%title% README</span>
|
||||
</div>
|
||||
<div id="rdocContent">
|
||||
%content%
|
||||
</div>
|
||||
<div id="floater">
|
||||
<strong>Documentation for %title% </strong><a href="#" onmouseover="$('tips').show();" onmouseout="$('tips').hide();">usage tips</a>
|
||||
<div id="tips" style="position:absolute;width:350px;top:15px;right:20px;padding:5px;border:1px solid #333;background-color:#fafafa;display:none;">
|
||||
<p><strong>Some tips</strong>
|
||||
<ul>
|
||||
<li> Up/Down keys move through the search list</li>
|
||||
<li> Return/enter key loads selected item</li>
|
||||
<li> Want to use this RDOC template for your own project? Check out <br /> http://rubyforge.org/projects/jaxdoc</li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
<div id="blowOutListBox" style="display:none;"> </div>
|
||||
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
_uacct = "UA-3085184-1";
|
||||
urchinTracker();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
HTML
|
||||
|
||||
API_GREASE_JS = File.read(File.join(File.dirname(__FILE__), 'api_grease.js'))
|
||||
|
||||
PROTOTYPE_JS = File.read(File.join(File.dirname(__FILE__), 'prototype.js'))
|
||||
end
|
||||
end
|
||||
|
|
@ -1,492 +0,0 @@
|
|||
html, body {
|
||||
padding:10px 0px 0px 5px;
|
||||
margin: 0px;
|
||||
font-family: "Lucida Grande", "Lucida Sans Unicode", sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #000000 url(http://merbivore.com/img/header_waves.gif) repeat-x scroll center top;
|
||||
}
|
||||
|
||||
td, p {
|
||||
background: #FFF;
|
||||
color: #000;
|
||||
margin: 0px;
|
||||
font-size: small;
|
||||
line-height: 17px;
|
||||
margin-bottom 12px;
|
||||
}
|
||||
|
||||
#floater {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
#floater strong {
|
||||
color: white;
|
||||
}
|
||||
|
||||
#floater a {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#floater a:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
/*holds the whole searching/drill down stuff */
|
||||
#listFrame{
|
||||
float:left;
|
||||
padding: 2px;
|
||||
width: 350px;
|
||||
background-color: #868686;
|
||||
border: 1px solid #999;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
#browserBar{
|
||||
height: 25px;
|
||||
padding:11px 0px 0px 0px;
|
||||
margin:0px;
|
||||
background-color: #868686;
|
||||
border-top: 1px solid #999;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#browserBar a{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.button{
|
||||
text-decoration: none;
|
||||
padding:3px 8px 3px 8px;
|
||||
border: 1px solid #66a;
|
||||
background-color: #ccf;
|
||||
color: #66a;
|
||||
}
|
||||
|
||||
.buttonInactive{
|
||||
text-decoration: none;
|
||||
padding:3px 8px 3px 8px;
|
||||
border: 1px solid #999;
|
||||
background-color: #ccc;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.miniButton{
|
||||
text-decoration: none;
|
||||
padding:3px 2px 3px 2px;
|
||||
border: 1px solid #66a;
|
||||
background-color: #ccf;
|
||||
color: #66a;
|
||||
}
|
||||
|
||||
.miniButtonInactive{
|
||||
text-decoration: none;
|
||||
padding:3px 2px 3px 2px;
|
||||
border: 1px solid #999;
|
||||
background-color: #ccc;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
#blowOutListBox{
|
||||
position: absolute;
|
||||
top: 63px;
|
||||
left: 399px;
|
||||
border: 1px solid #999;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
z-index: 1000;
|
||||
background-color: #ccf;
|
||||
color: #66a;
|
||||
}
|
||||
|
||||
#blowOutListBox ul{
|
||||
list-style-type:none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#blowOutListBox ul li{
|
||||
padding: 3px;
|
||||
margin: 0px;
|
||||
line-height: 1.1em;
|
||||
|
||||
}
|
||||
|
||||
#blowOutListBox ul li a{
|
||||
text-decoration: none;
|
||||
padding: 3px;
|
||||
}
|
||||
#blowOutListBox ul li a:hover{
|
||||
background-color: #ddf;
|
||||
}
|
||||
|
||||
/*holds the content for browsing etc... also is the target of method/class/file name clicks */
|
||||
#rdocContent{
|
||||
height: 600px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #999;
|
||||
border-left: 0px;
|
||||
padding:5px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/*the grouping for methods,files,class,all... i.e. the tabs */
|
||||
ul#groupType{
|
||||
list-style-type: none;
|
||||
padding: 0px;
|
||||
padding-left: 5px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
ul#groupType li{
|
||||
color: white;
|
||||
display:inline;
|
||||
padding: 5px 5px 0px 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ul#groupType li#loadingStatus{
|
||||
margin: 3px;
|
||||
border: 0px;
|
||||
padding: 3px 3px 6px 3px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
ul#groupType li.activeLi{
|
||||
border: 1px solid #999;
|
||||
border-bottom: 0px;
|
||||
background-color: #868686;
|
||||
font-weight: bold;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
#listSearch{
|
||||
height: 25px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
#listSearch input[type=text]{
|
||||
width: 340px;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
#listScroller{
|
||||
width: 342px;
|
||||
height: 700px;
|
||||
margin: 3px;
|
||||
background-color: #fcfcfc;
|
||||
border: 1px solid #999;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#listScroller ul{
|
||||
width: 500px;
|
||||
padding:0px;
|
||||
margin:0px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#listScroller li{
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
display: block;
|
||||
line-height: 1.1em;
|
||||
}
|
||||
|
||||
a, h1 a, h2 a, .sectiontitle a, #listScroller a{
|
||||
color: #11B716;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
padding: 0px 1px 1px 1px;
|
||||
margin: 3px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
a:hover, h1 a:hover, h2 a:hover, .sectiontitle a:hover, #listScroller a:hover{
|
||||
background-color: #22D716;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#browserBar a, .banner a {
|
||||
color: #D7FF00;
|
||||
}
|
||||
|
||||
#browserBar a:hover, .banner a:hover {
|
||||
background-color: #D7FF00;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#listScroller a.activeA {
|
||||
background-color: #22D716;
|
||||
color: black ;
|
||||
border: 1px solid #ccc;
|
||||
padding: 0px 1px 1px 1px;
|
||||
}
|
||||
|
||||
#listScroller small{
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.activeTitle{
|
||||
font-family: monospace;
|
||||
font-size: large;
|
||||
border-bottom: 1px dashed black;
|
||||
margin-bottom: 0.3em;
|
||||
padding-bottom: 0.1em;
|
||||
background-color: #ffc;
|
||||
}
|
||||
|
||||
.activeMethod{
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
|
||||
.activeMethod .title {
|
||||
font-family: monospace;
|
||||
font-size: large;
|
||||
border-bottom: 1px dashed black;
|
||||
margin-bottom: 0.3em;
|
||||
padding-bottom: 0.1em;
|
||||
background-color: #ffa;
|
||||
}
|
||||
|
||||
.activeMethod .description, .activeMethod .sourcecode {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.activeMethod .sourcecode p.source-link {
|
||||
text-indent: 0em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.activeMethod .aka {
|
||||
margin-top: 0.3em;
|
||||
margin-left: 1em;
|
||||
font-style: italic;
|
||||
text-indent: 2em;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
#description p {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.sectiontitle {
|
||||
color: black;
|
||||
font-size: 28px;
|
||||
margin: 20px 0px;
|
||||
border-bottom: 2px solid #CCCCCC;
|
||||
|
||||
/* margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
padding: 0.5em;
|
||||
padding-left: 2em;
|
||||
background: #005;
|
||||
color: #FFF;
|
||||
font-weight: bold;
|
||||
border: 1px dotted black;*/
|
||||
}
|
||||
|
||||
.attr-rw {
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
text-align: center;
|
||||
color: #7AAD00;
|
||||
}
|
||||
|
||||
.attr-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.attr-desc {
|
||||
}
|
||||
|
||||
.attr-value {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.file-title-prefix {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.file-title {
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
background: #005;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.banner {
|
||||
background: #888;
|
||||
color: #FFF;
|
||||
/* border: 1px solid black;*/
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.banner td {
|
||||
background: transparent;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.dyn-source {
|
||||
display: none;
|
||||
color: #000;
|
||||
border: 0px;
|
||||
border-left: 1px dotted #CCC;
|
||||
border-top: 1px dotted #CCC;
|
||||
margin: 0em;
|
||||
padding: 0em;
|
||||
}
|
||||
|
||||
.dyn-source .cmt {
|
||||
color: #7AAD00;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.dyn-source .kw {
|
||||
color: #11B716;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.method {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.description pre, .description td {
|
||||
font-family:"Courier",serif;
|
||||
}
|
||||
pre, .description pre {
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
color: white;
|
||||
padding: 12px;
|
||||
background: #222;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
h2.title, .method .title {
|
||||
color: #7AAD00;
|
||||
font-size: 22px;
|
||||
margin: 10px 0px;
|
||||
|
||||
/* font-size: large;
|
||||
border-bottom: 1px dashed black;
|
||||
margin: 0.3em;
|
||||
padding: 0.2em;
|
||||
*/}
|
||||
|
||||
.method .description, .method .sourcecode {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.description p, .sourcecode p {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.method .sourcecode p.source-link {
|
||||
text-indent: 0em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.method .aka {
|
||||
margin-top: 0.3em;
|
||||
margin-left: 1em;
|
||||
font-style: italic;
|
||||
text-indent: 2em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
padding: 1em;
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding: 0.5em 1em 0.5em 1em;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: white;
|
||||
background-color: #868686;
|
||||
}
|
||||
|
||||
h3, h4, h5, h6 {
|
||||
padding: 0.2em 1em 0.2em 1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.sourcecode > pre {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
border: 1px dotted black;
|
||||
background: #FFE;
|
||||
}
|
||||
|
||||
/* ============= */
|
||||
/* = home page = */
|
||||
/* ============= */
|
||||
|
||||
body#home {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin: 0 auto;
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
#content h1.home {
|
||||
background-color: transparent;
|
||||
border:0pt none;
|
||||
color:#FFFFFF;
|
||||
font-size:36px;
|
||||
margin:20px 0px;
|
||||
padding: 0;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
#content #documentation-links h2.title {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#documentation-links {
|
||||
background-color : white;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
#documentation-links p {
|
||||
margin: 22px;
|
||||
}
|
||||
|
||||
body#home #footer {
|
||||
background:#444444 none repeat scroll 0%;
|
||||
clear:both;
|
||||
}
|
||||
|
||||
#footer p {
|
||||
background-color: transparent;
|
||||
color:#999999;
|
||||
margin:0 auto;
|
||||
padding:12px;
|
||||
text-align:center;
|
||||
width: 800px;
|
||||
}
|
2515
web/doc/rdoc/generators/template/merb/prototype.js
vendored
2515
web/doc/rdoc/generators/template/merb/prototype.js
vendored
File diff suppressed because it is too large
Load diff
|
@ -1,17 +0,0 @@
|
|||
# Sets the default handler for FastCGI scripts
|
||||
AddHandler fastcgi-script .fcgi
|
||||
|
||||
# If Apache2 is used together with mod_fcgid,
|
||||
# uncomment the line below and comment in the line
|
||||
# above to set the correct script handler
|
||||
#AddHandler fcgid-script .fcgi
|
||||
|
||||
RewriteEngine On
|
||||
|
||||
RewriteRule ^$ index.html [QSA]
|
||||
RewriteRule ^([^.]+)$ $1.html [QSA]
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^(.*)$ merb.fcgi [QSA,L]
|
||||
|
||||
|
||||
ErrorDocument 500 "<h2>Application Error</h2>Merb could not be reached"
|
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.7 KiB |
|
@ -1 +0,0 @@
|
|||
// Common JavaScript code across your application goes here.
|
File diff suppressed because it is too large
Load diff
|
@ -1,71 +0,0 @@
|
|||
Frequently asked questions
|
||||
--------------------------
|
||||
|
||||
Q: How much data can Flot cope with?
|
||||
|
||||
A: Flot will happily draw everything you send to it so the answer
|
||||
depends on the browser. The excanvas emulation used for IE (built with
|
||||
VML) makes IE by far the slowest browser so be sure to test with that
|
||||
if IE users are in your target group.
|
||||
|
||||
1000 points is not a problem, but as soon as you start having more
|
||||
points than the pixel width, you should probably start thinking about
|
||||
downsampling/aggregation as this is near the resolution limit of the
|
||||
chart anyway. If you downsample server-side, you also save bandwidth.
|
||||
|
||||
|
||||
Q: Flot isn't working when I'm using JSON data as source!
|
||||
|
||||
A: Actually, Flot loves JSON data, you just got the format wrong.
|
||||
Double check that you're not inputting strings instead of numbers,
|
||||
like [["0", "-2.13"], ["5", "4.3"]]. This is most common mistake, and
|
||||
the error might not show up immediately because Javascript can do some
|
||||
conversion automatically.
|
||||
|
||||
|
||||
Q: Can I export the graph?
|
||||
|
||||
A: This is a limitation of the canvas technology. There's a hook in
|
||||
the canvas object for getting an image out, but you won't get the tick
|
||||
labels. And it's not likely to be supported by IE. At this point, your
|
||||
best bet is probably taking a screenshot, e.g. with PrtScn.
|
||||
|
||||
|
||||
Q: The bars are all tiny in time mode?
|
||||
|
||||
A: It's not really possible to determine the bar width automatically.
|
||||
So you have to set the width with the barWidth option which is NOT in
|
||||
pixels, but in the units of the x axis (or the y axis for horizontal
|
||||
bars). For time mode that's milliseconds so the default value of 1
|
||||
makes the bars 1 millisecond wide.
|
||||
|
||||
|
||||
Q: Can I use Flot with libraries like Mootools or Prototype?
|
||||
|
||||
A: Yes, Flot supports it out of the box and it's easy! Just use jQuery
|
||||
instead of $, e.g. call jQuery.plot instead of $.plot and use
|
||||
jQuery(something) instead of $(something). As a convenience, you can
|
||||
put in a DOM element for the graph placeholder where the examples and
|
||||
the API documentation are using jQuery objects.
|
||||
|
||||
Depending on how you include jQuery, you may have to add one line of
|
||||
code to prevent jQuery from overwriting functions from the other
|
||||
libraries, see the documentation in jQuery ("Using jQuery with other
|
||||
libraries") for details.
|
||||
|
||||
|
||||
Q: Flot doesn't work with [widget framework xyz]!
|
||||
|
||||
A: The problem is most likely within the framework, or your use of the
|
||||
framework.
|
||||
|
||||
The only non-standard thing used by Flot is the canvas tag; otherwise
|
||||
it is simply a series of absolute positioned divs within the
|
||||
placeholder tag you put in. If this is not working, it's probably
|
||||
because the framework you're using is doing something weird with the
|
||||
DOM. As a last resort, you might try replotting and see if it helps.
|
||||
|
||||
If you find there's a specific thing we can do to Flot to help, feel
|
||||
free to submit a bug report. Otherwise, you're welcome to ask for help
|
||||
on the mailing list, but please don't submit a bug report to Flot -
|
||||
try the framework instead.
|
|
@ -1,22 +0,0 @@
|
|||
Copyright (c) 2007-2009 IOLA and Ole Laursen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -1,15 +0,0 @@
|
|||
# Makefile for generating minified files
|
||||
|
||||
YUICOMPRESSOR_PATH=../yuicompressor-2.3.5.jar
|
||||
|
||||
# if you need another compressor path, just copy the above line to a
|
||||
# file called Makefile.local, customize it and you're good to go
|
||||
-include Makefile.local
|
||||
|
||||
.PHONY: all
|
||||
|
||||
# we cheat and process all .js files instead of listing them
|
||||
all: $(patsubst %.js,%.min.js,$(filter-out %.min.js,$(wildcard *.js)))
|
||||
|
||||
%.min.js: %.js
|
||||
java -jar $(YUICOMPRESSOR_PATH) $< -o $@
|
|
@ -1,340 +0,0 @@
|
|||
Flot 0.6
|
||||
--------
|
||||
|
||||
API changes:
|
||||
|
||||
1. Selection support has been moved to a plugin. Thus if you're
|
||||
passing selection: { mode: something }, you MUST include the file
|
||||
jquery.flot.selection.js after jquery.flot.js. This reduces the size
|
||||
of base Flot and makes it easier to customize the selection as well as
|
||||
improving code clarity. The change is based on patch from andershol.
|
||||
|
||||
2. In the global options specified in the $.plot command,
|
||||
"lines", "points", "bars" and "shadowSize" have been moved to a
|
||||
sub-object called "series", i.e.
|
||||
|
||||
$.plot(placeholder, data, { lines: { show: true }})
|
||||
|
||||
should be changed to
|
||||
|
||||
$.plot(placeholder, data, { series: { lines: { show: true }}})
|
||||
|
||||
All future series-specific options will go into this sub-object to
|
||||
simplify plugin writing. Backward-compatibility code is in place, so
|
||||
old code should not break.
|
||||
|
||||
3. "plothover" no longer provides the original data point, but instead
|
||||
a normalized one, since there may be no corresponding original point.
|
||||
|
||||
4. Due to a bug in previous versions of jQuery, you now need at least
|
||||
jQuery 1.2.6. But if you can, try jQuery 1.3.2 as it got some
|
||||
improvements in event handling speed.
|
||||
|
||||
|
||||
Changes:
|
||||
|
||||
- Added support for disabling interactivity for specific data series
|
||||
(request from Ronald Schouten and Steve Upton).
|
||||
|
||||
- Flot now calls $() on the placeholder and optional legend container
|
||||
passed in so you can specify DOM elements or CSS expressions to make
|
||||
it easier to use Flot with libraries like Prototype or Mootools or
|
||||
through raw JSON from Ajax responses.
|
||||
|
||||
- A new "plotselecting" event is now emitted while the user is making
|
||||
a selection.
|
||||
|
||||
- The "plothover" event is now emitted immediately instead of at most
|
||||
10 times per second, you'll have to put in a setTimeout yourself if
|
||||
you're doing something really expensive on this event.
|
||||
|
||||
- The built-in date formatter can now be accessed as
|
||||
$.plot.formatDate(...) (suggestion by Matt Manela) and even
|
||||
replaced.
|
||||
|
||||
- Added "borderColor" option to the grid (patch from Amaury Chamayou
|
||||
and patch from Mike R. Williamson).
|
||||
|
||||
- Added support for gradient backgrounds for the grid, take a look at
|
||||
the "setting options" example (based on patch from Amaury Chamayou,
|
||||
issue 90).
|
||||
|
||||
- Gradient bars (suggestion by stefpet).
|
||||
|
||||
- Added a "plotunselected" event which is triggered when the selection
|
||||
is removed, see "selection" example (suggestion by Meda Ugo);
|
||||
|
||||
- The option legend.margin can now specify horizontal and vertical
|
||||
margins independently (suggestion by someone who's annoyed).
|
||||
|
||||
- Data passed into Flot is now copied to a new canonical format to
|
||||
enable further processing before it hits the drawing routines. As a
|
||||
side-effect, this should make Flot more robust in the face of bad
|
||||
data (and fixes issue 112).
|
||||
|
||||
- Step-wise charting: line charts have a new option "steps" that when
|
||||
set to true connects the points with horizontal/vertical steps
|
||||
instead of diagonal lines.
|
||||
|
||||
- The legend labelFormatter now passes the series in addition to just
|
||||
the label (suggestion by Vincent Lemeltier).
|
||||
|
||||
- Horizontal bars (based on patch by Jason LeBrun).
|
||||
|
||||
- Support for partial bars by specifying a third coordinate, i.e. they
|
||||
don't have to start from the axis. This can be used to make stacked
|
||||
bars.
|
||||
|
||||
- New option to disable the (grid.show).
|
||||
|
||||
- Added pointOffset method for converting a point in data space to an
|
||||
offset within the placeholder.
|
||||
|
||||
- Plugin system: register an init method in the $.flot.plugins array
|
||||
to get started, see PLUGINS.txt for details on how to write plugins
|
||||
(it's easy). There are also some extra methods to enable access to
|
||||
internal state.
|
||||
|
||||
- Hooks: you can register functions that are called while Flot is
|
||||
crunching the data and doing the plot. This can be used to modify
|
||||
Flot without changing the source, useful for writing plugins. Some
|
||||
hooks are defined, more are likely to come.
|
||||
|
||||
- Threshold plugin: you can set a threshold and a color, and the data
|
||||
points below that threshold will then get the color. Useful for
|
||||
marking data below 0, for instance.
|
||||
|
||||
- Stack plugin: you can specify a stack key for each series to have
|
||||
them summed. This is useful for drawing additive/cumulative graphs
|
||||
with bars and (currently unfilled) lines.
|
||||
|
||||
- Crosshairs plugin: trace the mouse position on the axes, enable with
|
||||
crosshair: { mode: "x"} (see the new tracking example for a use).
|
||||
|
||||
- Image plugin: plot prerendered images.
|
||||
|
||||
- Navigation plugin for panning and zooming a plot.
|
||||
|
||||
- More configurable grid.
|
||||
|
||||
- Axis transformation support, useful for non-linear plots, e.g. log
|
||||
axes and compressed time axes (like omitting weekends).
|
||||
|
||||
- Support for twelve-hour date formatting (patch by Forrest Aldridge).
|
||||
|
||||
- The color parsing code in Flot has been cleaned up and split out so
|
||||
it's now available as a separate jQuery plugin. It's included inline
|
||||
in the Flot source to make dependency managing easier. This also
|
||||
makes it really easy to use the color helpers in Flot plugins.
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- Fixed two corner-case bugs when drawing filled curves (report and
|
||||
analysis by Joshua Varner).
|
||||
- Fix auto-adjustment code when setting min to 0 for an axis where the
|
||||
dataset is completely flat on that axis (report by chovy).
|
||||
- Fixed a bug with passing in data from getData to setData when the
|
||||
secondary axes are used (issue 65, reported by nperelman).
|
||||
- Fixed so that it is possible to turn lines off when no other chart
|
||||
type is shown (based on problem reported by Glenn Vanderburg), and
|
||||
fixed so that setting lineWidth to 0 also hides the shadow (based on
|
||||
problem reported by Sergio Nunes).
|
||||
- Updated mousemove position expression to the latest from jQuery (bug
|
||||
reported by meyuchas).
|
||||
- Use CSS borders instead of background in legend (fix printing issue 25
|
||||
and 45).
|
||||
- Explicitly convert axis min/max to numbers.
|
||||
- Fixed a bug with drawing marking lines with different colors
|
||||
(reported by Khurram).
|
||||
- Fixed a bug with returning y2 values in the selection event (fix
|
||||
by exists, issue 75).
|
||||
- Only set position relative on placeholder if it hasn't already a
|
||||
position different from static (reported by kyberneticist, issue 95).
|
||||
- Don't round markings to prevent sub-pixel problems (reported by Dan
|
||||
Lipsitt).
|
||||
- Make the grid border act similarly to a regular CSS border, i.e.
|
||||
prevent it from overlapping the plot itself. This also fixes a
|
||||
problem with anti-aliasing when the width is 1 pixel (reported by
|
||||
Anthony Ettinger).
|
||||
- Imported version 3 of excanvas and fixed two issues with the newer
|
||||
version. Hopefully, this will make Flot work with IE8 (nudge by
|
||||
Fabien Menager, further analysis by Booink, issue 133).
|
||||
- Changed the shadow code for lines to hopefully look a bit better
|
||||
with vertical lines.
|
||||
- Round tick positions to avoid possible problems with fractions
|
||||
(suggestion by Fred, issue 130).
|
||||
- Made the heuristic for determining how many ticks to aim for a bit
|
||||
smarter.
|
||||
- Fix for uneven axis margins (report and patch by Paul Kienzle) and
|
||||
snapping to ticks (concurrent report and patch by lifthrasiir).
|
||||
- Fixed bug with slicing in findNearbyItems (patch by zollman).
|
||||
- Make heuristic for x axis label widths more dynamic (patch by
|
||||
rickinhethuis).
|
||||
- Make sure points on top take precedence when finding nearby points
|
||||
when hovering (reported by didroe, issue 224).
|
||||
|
||||
Flot 0.5
|
||||
--------
|
||||
|
||||
Backwards API change summary: Timestamps are now in UTC. Also
|
||||
"selected" event -> becomes "plotselected" with new data, the
|
||||
parameters for setSelection are now different (but backwards
|
||||
compatibility hooks are in place), coloredAreas becomes markings with
|
||||
a new interface (but backwards compatibility hooks are in place).
|
||||
|
||||
|
||||
Interactivity: added a new "plothover" event and this and the
|
||||
"plotclick" event now returns the closest data item (based on patch by
|
||||
/david, patch by Mark Byers for bar support). See the revamped
|
||||
"interacting with the data" example for some hints on what you can do.
|
||||
|
||||
Highlighting: you can now highlight points and datapoints are
|
||||
autohighlighted when you hover over them (if hovering is turned on).
|
||||
|
||||
Support for dual axis has been added (based on patch by someone who's
|
||||
annoyed and /david). For each data series you can specify which axes
|
||||
it belongs to, and there are two more axes, x2axis and y2axis, to
|
||||
customize. This affects the "selected" event which has been renamed to
|
||||
"plotselected" and spews out { xaxis: { from: -10, to: 20 } ... },
|
||||
setSelection in which the parameters are on a new form (backwards
|
||||
compatible hooks are in place so old code shouldn't break) and
|
||||
markings (formerly coloredAreas).
|
||||
|
||||
Timestamps in time mode are now displayed according to
|
||||
UTC instead of the time zone of the visitor. This affects the way the
|
||||
timestamps should be input; you'll probably have to offset the
|
||||
timestamps according to your local time zone. It also affects any
|
||||
custom date handling code (which basically now should use the
|
||||
equivalent UTC date mehods, e.g. .setUTCMonth() instead of
|
||||
.setMonth().
|
||||
|
||||
Added support for specifying the size of tick labels (axis.labelWidth,
|
||||
axis.labelHeight). Useful for specifying a max label size to keep
|
||||
multiple plots aligned.
|
||||
|
||||
Markings, previously coloredAreas, are now specified as ranges on the
|
||||
axes, like { xaxis: { from: 0, to: 10 }}. Furthermore with markings
|
||||
you can now draw horizontal/vertical lines by setting from and to to
|
||||
the same coordinate (idea from line support patch by by Ryan Funduk).
|
||||
|
||||
The "fill" option can now be a number that specifies the opacity of
|
||||
the fill.
|
||||
|
||||
You can now specify a coordinate as null (like [2, null]) and Flot
|
||||
will take the other coordinate into account when scaling the axes
|
||||
(based on patch by joebno).
|
||||
|
||||
New option for bars "align". Set it to "center" to center the bars on
|
||||
the value they represent.
|
||||
|
||||
setSelection now takes a second parameter which you can use to prevent
|
||||
the method from firing the "plotselected" handler.
|
||||
|
||||
Using the "container" option in legend now overwrites the container
|
||||
element instead of just appending to it (fixes infinite legend bug,
|
||||
reported by several people, fix by Brad Dewey).
|
||||
|
||||
Fixed a bug in calculating spacing around the plot (reported by
|
||||
timothytoe). Fixed a bug in finding max values for all-negative data
|
||||
sets. Prevent the possibility of eternal looping in tick calculations.
|
||||
Fixed a bug when borderWidth is set to 0 (reported by
|
||||
Rob/sanchothefat). Fixed a bug with drawing bars extending below 0
|
||||
(reported by James Hewitt, patch by Ryan Funduk). Fixed a
|
||||
bug with line widths of bars (reported by MikeM). Fixed a bug with
|
||||
'nw' and 'sw' legend positions. Improved the handling of axis
|
||||
auto-scaling with bars. Fixed a bug with multi-line x-axis tick
|
||||
labels (reported by Luca Ciano). IE-fix help by Savage Zhang.
|
||||
|
||||
|
||||
Flot 0.4
|
||||
--------
|
||||
|
||||
API changes: deprecated axis.noTicks in favor of just specifying the
|
||||
number as axis.ticks. So "xaxis: { noTicks: 10 }" becomes
|
||||
"xaxis: { ticks: 10 }"
|
||||
|
||||
Time series support. Specify axis.mode: "time", put in Javascript
|
||||
timestamps as data, and Flot will automatically spit out sensible
|
||||
ticks. Take a look at the two new examples. The format can be
|
||||
customized with axis.timeformat and axis.monthNames, or if that fails
|
||||
with axis.tickFormatter.
|
||||
|
||||
Support for colored background areas via grid.coloredAreas. Specify an
|
||||
array of { x1, y1, x2, y2 } objects or a function that returns these
|
||||
given { xmin, xmax, ymin, ymax }.
|
||||
|
||||
More members on the plot object (report by Chris Davies and others).
|
||||
"getData" for inspecting the assigned settings on data series (e.g.
|
||||
color) and "setData", "setupGrid" and "draw" for updating the contents
|
||||
without a total replot.
|
||||
|
||||
The default number of ticks to aim for is now dependent on the size of
|
||||
the plot in pixels. Support for customizing tick interval sizes
|
||||
directly with axis.minTickSize and axis.tickSize.
|
||||
|
||||
Cleaned up the automatic axis scaling algorithm and fixed how it
|
||||
interacts with ticks. Also fixed a couple of tick-related corner case
|
||||
bugs (one reported by mainstreetmark, another reported by timothytoe).
|
||||
|
||||
The option axis.tickFormatter now takes a function with two
|
||||
parameters, the second parameter is an optional object with
|
||||
information about the axis. It has min, max, tickDecimals, tickSize.
|
||||
|
||||
Added support for segmented lines (based on patch from Michael
|
||||
MacDonald) and for ignoring null and bad values (suggestion from Nick
|
||||
Konidaris and joshwaihi).
|
||||
|
||||
Added support for changing the border width (joebno and safoo).
|
||||
Label colors can be changed via CSS by selecting the tickLabel class.
|
||||
|
||||
Fixed a bug in handling single-item bar series (reported by Emil
|
||||
Filipov). Fixed erratic behaviour when interacting with the plot
|
||||
with IE 7 (reported by Lau Bech Lauritzen). Prevent IE/Safari text
|
||||
selection when selecting stuff on the canvas.
|
||||
|
||||
|
||||
|
||||
Flot 0.3
|
||||
--------
|
||||
|
||||
This is mostly a quick-fix release because jquery.js wasn't included
|
||||
in the previous zip/tarball.
|
||||
|
||||
Support clicking on the plot. Turn it on with grid: { clickable: true },
|
||||
then you get a "plotclick" event on the graph placeholder with the
|
||||
position in units of the plot.
|
||||
|
||||
Fixed a bug in dealing with data where min = max, thanks to Michael
|
||||
Messinides.
|
||||
|
||||
Include jquery.js in the zip/tarball.
|
||||
|
||||
|
||||
Flot 0.2
|
||||
--------
|
||||
|
||||
Added support for putting a background behind the default legend. The
|
||||
default is the partly transparent background color. Added
|
||||
backgroundColor and backgroundOpacity to the legend options to control
|
||||
this.
|
||||
|
||||
The ticks options can now be a callback function that takes one
|
||||
parameter, an object with the attributes min and max. The function
|
||||
should return a ticks array.
|
||||
|
||||
Added labelFormatter option in legend, useful for turning the legend
|
||||
labels into links.
|
||||
|
||||
Fixed a couple of bugs.
|
||||
|
||||
The API should now be fully documented.
|
||||
|
||||
Patch from Guy Fraser to make parts of the code smaller.
|
||||
|
||||
API changes: Moved labelMargin option to grid from x/yaxis.
|
||||
|
||||
|
||||
Flot 0.1
|
||||
--------
|
||||
|
||||
First public release.
|
|
@ -1,105 +0,0 @@
|
|||
Writing plugins
|
||||
---------------
|
||||
|
||||
To make a new plugin, create an init function and a set of options (if
|
||||
needed), stuff it into an object and put it in the $.plot.plugins
|
||||
array. For example:
|
||||
|
||||
function myCoolPluginInit(plot) { plot.coolstring = "Hello!" };
|
||||
var myCoolOptions = { coolstuff: { show: true } }
|
||||
$.plot.plugins.push({ init: myCoolPluginInit, options: myCoolOptions });
|
||||
|
||||
// now when $.plot is called, the returned object will have the
|
||||
// attribute "coolstring"
|
||||
|
||||
Now, given that the plugin might run in many different places, it's
|
||||
a good idea to avoid leaking names. We can avoid this by wrapping the
|
||||
above lines in an anonymous function which we call immediately, like
|
||||
this: (function () { inner code ... })(). To make it even more robust
|
||||
in case $ is not bound to jQuery but some other Javascript library, we
|
||||
can write it as
|
||||
|
||||
(function ($) {
|
||||
// plugin definition
|
||||
// ...
|
||||
})(jQuery);
|
||||
|
||||
Here is a simple debug plugin which alerts each of the series in the
|
||||
plot. It has a single option that control whether it is enabled and
|
||||
how much info to output:
|
||||
|
||||
(function ($) {
|
||||
function init(plot) {
|
||||
var debugLevel = 1;
|
||||
|
||||
function checkDebugEnabled(plot, options) {
|
||||
if (options.debug) {
|
||||
debugLevel = options.debug;
|
||||
|
||||
plot.hooks.processDatapoints.push(alertSeries);
|
||||
}
|
||||
}
|
||||
|
||||
function alertSeries(plot, series, datapoints) {
|
||||
var msg = "series " + series.label;
|
||||
if (debugLevel > 1)
|
||||
msg += " with " + series.data.length + " points";
|
||||
alert(msg);
|
||||
}
|
||||
|
||||
plot.hooks.processOptions.push(checkDebugEnabled);
|
||||
}
|
||||
|
||||
var options = { debug: 0 };
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: "simpledebug",
|
||||
version: "0.1"
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
We also define "name" and "version". It's not used by Flot, but might
|
||||
be helpful for other plugins in resolving dependencies.
|
||||
|
||||
Put the above in a file named "jquery.flot.debug.js", include it in an
|
||||
HTML page and then it can be used with:
|
||||
|
||||
$.plot($("#placeholder"), [...], { debug: 2 });
|
||||
|
||||
This simple plugin illustrates a couple of points:
|
||||
|
||||
- It uses the anonymous function trick to avoid name pollution.
|
||||
- It can be enabled/disabled through an option.
|
||||
- Variables in the init function can be used to store plot-specific
|
||||
state between the hooks.
|
||||
|
||||
|
||||
Options guidelines
|
||||
==================
|
||||
|
||||
Plugins should always support appropriate options to enable/disable
|
||||
them because the plugin user may have several plots on the same page
|
||||
where only one should use the plugin.
|
||||
|
||||
If the plugin needs series-specific options, you can put them in
|
||||
"series" in the options object, e.g.
|
||||
|
||||
var options = {
|
||||
series: {
|
||||
downsample: {
|
||||
algorithm: null,
|
||||
maxpoints: 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Then they will be copied by Flot into each series, providing the
|
||||
defaults in case the plugin user doesn't specify any. Again, in most
|
||||
cases it's probably a good idea if the plugin is turned off rather
|
||||
than on per default, just like most of the powerful features in Flot.
|
||||
|
||||
Think hard and long about naming the options. These names are going to
|
||||
be public API, and code is going to depend on them if the plugin is
|
||||
successful.
|
|
@ -1,81 +0,0 @@
|
|||
About
|
||||
-----
|
||||
|
||||
Flot is a Javascript plotting library for jQuery. Read more at the
|
||||
website:
|
||||
|
||||
http://code.google.com/p/flot/
|
||||
|
||||
Take a look at the examples linked from above, they should give a good
|
||||
impression of what Flot can do and the source code of the examples is
|
||||
probably the fastest way to learn how to use Flot.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Just include the Javascript file after you've included jQuery.
|
||||
|
||||
Note that you need to get a version of Excanvas (e.g. the one bundled
|
||||
with Flot) which is canvas emulation on Internet Explorer. You can
|
||||
include the excanvas script like this:
|
||||
|
||||
<!--[if IE]><script language="javascript" type="text/javascript" src="excanvas.pack.js"></script><![endif]-->
|
||||
|
||||
If it's not working on your development IE 6.0, check that it has
|
||||
support for VML which excanvas is relying on. It appears that some
|
||||
stripped down versions used for test environments on virtual machines
|
||||
lack the VML support.
|
||||
|
||||
Also note that you need at least jQuery 1.2.6 (but at least jQuery
|
||||
1.3.2 is recommended for interactive charts because of performance
|
||||
improvements in event handling).
|
||||
|
||||
|
||||
Basic usage
|
||||
-----------
|
||||
|
||||
Create a placeholder div to put the graph in:
|
||||
|
||||
<div id="placeholder"></div>
|
||||
|
||||
You need to set the width and height of this div, otherwise the plot
|
||||
library doesn't know how to scale the graph. You can do it inline like
|
||||
this:
|
||||
|
||||
<div id="placeholder" style="width:600px;height:300px"></div>
|
||||
|
||||
You can also do it with an external stylesheet. Make sure that the
|
||||
placeholder isn't within something with a display:none CSS property -
|
||||
in that case, Flot has trouble measuring label dimensions which
|
||||
results in garbled looks and might have trouble measuring the
|
||||
placeholder dimensions which is fatal (it'll throw an exception).
|
||||
|
||||
Then when the div is ready in the DOM, which is usually on document
|
||||
ready, run the plot function:
|
||||
|
||||
$.plot($("#placeholder"), data, options);
|
||||
|
||||
Here, data is an array of data series and options is an object with
|
||||
settings if you want to customize the plot. Take a look at the
|
||||
examples for some ideas of what to put in or look at the reference
|
||||
in the file "API.txt". Here's a quick example that'll draw a line from
|
||||
(0, 0) to (1, 1):
|
||||
|
||||
$.plot($("#placeholder"), [ [[0, 0], [1, 1]] ], { yaxis: { max: 1 } });
|
||||
|
||||
The plot function immediately draws the chart and then returns a plot
|
||||
object with a couple of methods.
|
||||
|
||||
|
||||
What's with the name?
|
||||
---------------------
|
||||
|
||||
First: it's pronounced with a short o, like "plot". Not like "flawed".
|
||||
|
||||
So "Flot" rhymes with "plot".
|
||||
|
||||
And if you look up "flot" in a Danish-to-English dictionary, some up
|
||||
the words that come up are "good-looking", "attractive", "stylish",
|
||||
"smart", "impressive", "extravagant". One of the main goals with Flot
|
||||
is pretty looks.
|
File diff suppressed because it is too large
Load diff
1
web/public/javascripts/flot/excanvas.min.js
vendored
1
web/public/javascripts/flot/excanvas.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,174 +0,0 @@
|
|||
/* Plugin for jQuery for working with colors.
|
||||
*
|
||||
* Version 1.0.
|
||||
*
|
||||
* Inspiration from jQuery color animation plugin by John Resig.
|
||||
*
|
||||
* Released under the MIT license by Ole Laursen, October 2009.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
|
||||
* var c = $.color.extract($("#mydiv"), 'background-color');
|
||||
* console.log(c.r, c.g, c.b, c.a);
|
||||
* $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
|
||||
*
|
||||
* Note that .scale() and .add() work in-place instead of returning
|
||||
* new objects.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
jQuery.color = {};
|
||||
|
||||
// construct color object with some convenient chainable helpers
|
||||
jQuery.color.make = function (r, g, b, a) {
|
||||
var o = {};
|
||||
o.r = r || 0;
|
||||
o.g = g || 0;
|
||||
o.b = b || 0;
|
||||
o.a = a != null ? a : 1;
|
||||
|
||||
o.add = function (c, d) {
|
||||
for (var i = 0; i < c.length; ++i)
|
||||
o[c.charAt(i)] += d;
|
||||
return o.normalize();
|
||||
};
|
||||
|
||||
o.scale = function (c, f) {
|
||||
for (var i = 0; i < c.length; ++i)
|
||||
o[c.charAt(i)] *= f;
|
||||
return o.normalize();
|
||||
};
|
||||
|
||||
o.toString = function () {
|
||||
if (o.a >= 1.0) {
|
||||
return "rgb("+[o.r, o.g, o.b].join(",")+")";
|
||||
} else {
|
||||
return "rgba("+[o.r, o.g, o.b, o.a].join(",")+")";
|
||||
}
|
||||
};
|
||||
|
||||
o.normalize = function () {
|
||||
function clamp(min, value, max) {
|
||||
return value < min ? min: (value > max ? max: value);
|
||||
}
|
||||
|
||||
o.r = clamp(0, parseInt(o.r), 255);
|
||||
o.g = clamp(0, parseInt(o.g), 255);
|
||||
o.b = clamp(0, parseInt(o.b), 255);
|
||||
o.a = clamp(0, o.a, 1);
|
||||
return o;
|
||||
};
|
||||
|
||||
o.clone = function () {
|
||||
return jQuery.color.make(o.r, o.b, o.g, o.a);
|
||||
};
|
||||
|
||||
return o.normalize();
|
||||
}
|
||||
|
||||
// extract CSS color property from element, going up in the DOM
|
||||
// if it's "transparent"
|
||||
jQuery.color.extract = function (elem, css) {
|
||||
var c;
|
||||
do {
|
||||
c = elem.css(css).toLowerCase();
|
||||
// keep going until we find an element that has color, or
|
||||
// we hit the body
|
||||
if (c != '' && c != 'transparent')
|
||||
break;
|
||||
elem = elem.parent();
|
||||
} while (!jQuery.nodeName(elem.get(0), "body"));
|
||||
|
||||
// catch Safari's way of signalling transparent
|
||||
if (c == "rgba(0, 0, 0, 0)")
|
||||
c = "transparent";
|
||||
|
||||
return jQuery.color.parse(c);
|
||||
}
|
||||
|
||||
// parse CSS color string (like "rgb(10, 32, 43)" or "#fff"),
|
||||
// returns color object
|
||||
jQuery.color.parse = function (str) {
|
||||
var res, m = jQuery.color.make;
|
||||
|
||||
// Look for rgb(num,num,num)
|
||||
if (res = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))
|
||||
return m(parseInt(res[1], 10), parseInt(res[2], 10), parseInt(res[3], 10));
|
||||
|
||||
// Look for rgba(num,num,num,num)
|
||||
if (res = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))
|
||||
return m(parseInt(res[1], 10), parseInt(res[2], 10), parseInt(res[3], 10), parseFloat(res[4]));
|
||||
|
||||
// Look for rgb(num%,num%,num%)
|
||||
if (res = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))
|
||||
return m(parseFloat(res[1])*2.55, parseFloat(res[2])*2.55, parseFloat(res[3])*2.55);
|
||||
|
||||
// Look for rgba(num%,num%,num%,num)
|
||||
if (res = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))
|
||||
return m(parseFloat(res[1])*2.55, parseFloat(res[2])*2.55, parseFloat(res[3])*2.55, parseFloat(res[4]));
|
||||
|
||||
// Look for #a0b1c2
|
||||
if (res = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))
|
||||
return m(parseInt(res[1], 16), parseInt(res[2], 16), parseInt(res[3], 16));
|
||||
|
||||
// Look for #fff
|
||||
if (res = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))
|
||||
return m(parseInt(res[1]+res[1], 16), parseInt(res[2]+res[2], 16), parseInt(res[3]+res[3], 16));
|
||||
|
||||
// Otherwise, we're most likely dealing with a named color
|
||||
var name = jQuery.trim(str).toLowerCase();
|
||||
if (name == "transparent")
|
||||
return m(255, 255, 255, 0);
|
||||
else {
|
||||
res = lookupColors[name];
|
||||
return m(res[0], res[1], res[2]);
|
||||
}
|
||||
}
|
||||
|
||||
var lookupColors = {
|
||||
aqua:[0,255,255],
|
||||
azure:[240,255,255],
|
||||
beige:[245,245,220],
|
||||
black:[0,0,0],
|
||||
blue:[0,0,255],
|
||||
brown:[165,42,42],
|
||||
cyan:[0,255,255],
|
||||
darkblue:[0,0,139],
|
||||
darkcyan:[0,139,139],
|
||||
darkgrey:[169,169,169],
|
||||
darkgreen:[0,100,0],
|
||||
darkkhaki:[189,183,107],
|
||||
darkmagenta:[139,0,139],
|
||||
darkolivegreen:[85,107,47],
|
||||
darkorange:[255,140,0],
|
||||
darkorchid:[153,50,204],
|
||||
darkred:[139,0,0],
|
||||
darksalmon:[233,150,122],
|
||||
darkviolet:[148,0,211],
|
||||
fuchsia:[255,0,255],
|
||||
gold:[255,215,0],
|
||||
green:[0,128,0],
|
||||
indigo:[75,0,130],
|
||||
khaki:[240,230,140],
|
||||
lightblue:[173,216,230],
|
||||
lightcyan:[224,255,255],
|
||||
lightgreen:[144,238,144],
|
||||
lightgrey:[211,211,211],
|
||||
lightpink:[255,182,193],
|
||||
lightyellow:[255,255,224],
|
||||
lime:[0,255,0],
|
||||
magenta:[255,0,255],
|
||||
maroon:[128,0,0],
|
||||
navy:[0,0,128],
|
||||
olive:[128,128,0],
|
||||
orange:[255,165,0],
|
||||
pink:[255,192,203],
|
||||
purple:[128,0,128],
|
||||
violet:[128,0,128],
|
||||
red:[255,0,0],
|
||||
silver:[192,192,192],
|
||||
white:[255,255,255],
|
||||
yellow:[255,255,0]
|
||||
};
|
||||
})();
|
|
@ -1 +0,0 @@
|
|||
(function(){jQuery.color={};jQuery.color.make=function(E,D,B,C){var F={};F.r=E||0;F.g=D||0;F.b=B||0;F.a=C!=null?C:1;F.add=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]+=H}return F.normalize()};F.scale=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]*=H}return F.normalize()};F.toString=function(){if(F.a>=1){return"rgb("+[F.r,F.g,F.b].join(",")+")"}else{return"rgba("+[F.r,F.g,F.b,F.a].join(",")+")"}};F.normalize=function(){function G(I,J,H){return J<I?I:(J>H?H:J)}F.r=G(0,parseInt(F.r),255);F.g=G(0,parseInt(F.g),255);F.b=G(0,parseInt(F.b),255);F.a=G(0,F.a,1);return F};F.clone=function(){return jQuery.color.make(F.r,F.b,F.g,F.a)};return F.normalize()};jQuery.color.extract=function(C,B){var D;do{D=C.css(B).toLowerCase();if(D!=""&&D!="transparent"){break}C=C.parent()}while(!jQuery.nodeName(C.get(0),"body"));if(D=="rgba(0, 0, 0, 0)"){D="transparent"}return jQuery.color.parse(D)};jQuery.color.parse=function(E){var D,B=jQuery.color.make;if(D=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10))}if(D=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10),parseFloat(D[4]))}if(D=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55)}if(D=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55,parseFloat(D[4]))}if(D=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(E)){return B(parseInt(D[1],16),parseInt(D[2],16),parseInt(D[3],16))}if(D=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(E)){return B(parseInt(D[1]+D[1],16),parseInt(D[2]+D[2],16),parseInt(D[3]+D[3],16))}var C=jQuery.trim(E).toLowerCase();if(C=="transparent"){return B(255,255,255,0)}else{D=A[C];return B(D[0],D[1],D[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})();
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
Flot plugin for showing a crosshair, thin lines, when the mouse hovers
|
||||
over the plot.
|
||||
|
||||
crosshair: {
|
||||
mode: null or "x" or "y" or "xy"
|
||||
color: color
|
||||
lineWidth: number
|
||||
}
|
||||
|
||||
Set the mode to one of "x", "y" or "xy". The "x" mode enables a
|
||||
vertical crosshair that lets you trace the values on the x axis, "y"
|
||||
enables a horizontal crosshair and "xy" enables them both. "color" is
|
||||
the color of the crosshair (default is "rgba(170, 0, 0, 0.80)"),
|
||||
"lineWidth" is the width of the drawn lines (default is 1).
|
||||
|
||||
The plugin also adds four public methods:
|
||||
|
||||
- setCrosshair(pos)
|
||||
|
||||
Set the position of the crosshair. Note that this is cleared if
|
||||
the user moves the mouse. "pos" should be on the form { x: xpos,
|
||||
y: ypos } (or x2 and y2 if you're using the secondary axes), which
|
||||
is coincidentally the same format as what you get from a "plothover"
|
||||
event. If "pos" is null, the crosshair is cleared.
|
||||
|
||||
- clearCrosshair()
|
||||
|
||||
Clear the crosshair.
|
||||
|
||||
- lockCrosshair(pos)
|
||||
|
||||
Cause the crosshair to lock to the current location, no longer
|
||||
updating if the user moves the mouse. Optionally supply a position
|
||||
(passed on to setCrosshair()) to move it to.
|
||||
|
||||
Example usage:
|
||||
var myFlot = $.plot( $("#graph"), ..., { crosshair: { mode: "x" } } };
|
||||
$("#graph").bind("plothover", function (evt, position, item) {
|
||||
if (item) {
|
||||
// Lock the crosshair to the data point being hovered
|
||||
myFlot.lockCrosshair({ x: item.datapoint[0], y: item.datapoint[1] });
|
||||
}
|
||||
else {
|
||||
// Return normal crosshair operation
|
||||
myFlot.unlockCrosshair();
|
||||
}
|
||||
});
|
||||
|
||||
- unlockCrosshair()
|
||||
|
||||
Free the crosshair to move again after locking it.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
crosshair: {
|
||||
mode: null, // one of null, "x", "y" or "xy",
|
||||
color: "rgba(170, 0, 0, 0.80)",
|
||||
lineWidth: 1
|
||||
}
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
// position of crosshair in pixels
|
||||
var crosshair = { x: -1, y: -1, locked: false };
|
||||
|
||||
plot.setCrosshair = function setCrosshair(pos) {
|
||||
if (!pos)
|
||||
crosshair.x = -1;
|
||||
else {
|
||||
var axes = plot.getAxes();
|
||||
|
||||
crosshair.x = Math.max(0, Math.min(pos.x != null ? axes.xaxis.p2c(pos.x) : axes.x2axis.p2c(pos.x2), plot.width()));
|
||||
crosshair.y = Math.max(0, Math.min(pos.y != null ? axes.yaxis.p2c(pos.y) : axes.y2axis.p2c(pos.y2), plot.height()));
|
||||
}
|
||||
|
||||
plot.triggerRedrawOverlay();
|
||||
};
|
||||
|
||||
plot.clearCrosshair = plot.setCrosshair; // passes null for pos
|
||||
|
||||
plot.lockCrosshair = function lockCrosshair(pos) {
|
||||
if (pos)
|
||||
plot.setCrosshair(pos);
|
||||
crosshair.locked = true;
|
||||
}
|
||||
|
||||
plot.unlockCrosshair = function unlockCrosshair() {
|
||||
crosshair.locked = false;
|
||||
}
|
||||
|
||||
plot.hooks.bindEvents.push(function (plot, eventHolder) {
|
||||
if (!plot.getOptions().crosshair.mode)
|
||||
return;
|
||||
|
||||
eventHolder.mouseout(function () {
|
||||
if (crosshair.x != -1) {
|
||||
crosshair.x = -1;
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
});
|
||||
|
||||
eventHolder.mousemove(function (e) {
|
||||
if (plot.getSelection && plot.getSelection()) {
|
||||
crosshair.x = -1; // hide the crosshair while selecting
|
||||
return;
|
||||
}
|
||||
|
||||
if (crosshair.locked)
|
||||
return;
|
||||
|
||||
var offset = plot.offset();
|
||||
crosshair.x = Math.max(0, Math.min(e.pageX - offset.left, plot.width()));
|
||||
crosshair.y = Math.max(0, Math.min(e.pageY - offset.top, plot.height()));
|
||||
plot.triggerRedrawOverlay();
|
||||
});
|
||||
});
|
||||
|
||||
plot.hooks.drawOverlay.push(function (plot, ctx) {
|
||||
var c = plot.getOptions().crosshair;
|
||||
if (!c.mode)
|
||||
return;
|
||||
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(plotOffset.left, plotOffset.top);
|
||||
|
||||
if (crosshair.x != -1) {
|
||||
ctx.strokeStyle = c.color;
|
||||
ctx.lineWidth = c.lineWidth;
|
||||
ctx.lineJoin = "round";
|
||||
|
||||
ctx.beginPath();
|
||||
if (c.mode.indexOf("x") != -1) {
|
||||
ctx.moveTo(crosshair.x, 0);
|
||||
ctx.lineTo(crosshair.x, plot.height());
|
||||
}
|
||||
if (c.mode.indexOf("y") != -1) {
|
||||
ctx.moveTo(0, crosshair.y);
|
||||
ctx.lineTo(plot.width(), crosshair.y);
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.restore();
|
||||
});
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'crosshair',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1 +0,0 @@
|
|||
(function(B){var A={crosshair:{mode:null,color:"rgba(170, 0, 0, 0.80)",lineWidth:1}};function C(G){var H={x:-1,y:-1,locked:false};G.setCrosshair=function D(J){if(!J){H.x=-1}else{var I=G.getAxes();H.x=Math.max(0,Math.min(J.x!=null?I.xaxis.p2c(J.x):I.x2axis.p2c(J.x2),G.width()));H.y=Math.max(0,Math.min(J.y!=null?I.yaxis.p2c(J.y):I.y2axis.p2c(J.y2),G.height()))}G.triggerRedrawOverlay()};G.clearCrosshair=G.setCrosshair;G.lockCrosshair=function E(I){if(I){G.setCrosshair(I)}H.locked=true};G.unlockCrosshair=function F(){H.locked=false};G.hooks.bindEvents.push(function(J,I){if(!J.getOptions().crosshair.mode){return }I.mouseout(function(){if(H.x!=-1){H.x=-1;J.triggerRedrawOverlay()}});I.mousemove(function(K){if(J.getSelection&&J.getSelection()){H.x=-1;return }if(H.locked){return }var L=J.offset();H.x=Math.max(0,Math.min(K.pageX-L.left,J.width()));H.y=Math.max(0,Math.min(K.pageY-L.top,J.height()));J.triggerRedrawOverlay()})});G.hooks.drawOverlay.push(function(K,I){var L=K.getOptions().crosshair;if(!L.mode){return }var J=K.getPlotOffset();I.save();I.translate(J.left,J.top);if(H.x!=-1){I.strokeStyle=L.color;I.lineWidth=L.lineWidth;I.lineJoin="round";I.beginPath();if(L.mode.indexOf("x")!=-1){I.moveTo(H.x,0);I.lineTo(H.x,K.height())}if(L.mode.indexOf("y")!=-1){I.moveTo(0,H.y);I.lineTo(K.width(),H.y)}I.stroke()}I.restore()})}B.plot.plugins.push({init:C,options:A,name:"crosshair",version:"1.0"})})(jQuery);
|
|
@ -1,237 +0,0 @@
|
|||
/*
|
||||
Flot plugin for plotting images, e.g. useful for putting ticks on a
|
||||
prerendered complex visualization.
|
||||
|
||||
The data syntax is [[image, x1, y1, x2, y2], ...] where (x1, y1) and
|
||||
(x2, y2) are where you intend the two opposite corners of the image to
|
||||
end up in the plot. Image must be a fully loaded Javascript image (you
|
||||
can make one with new Image()). If the image is not complete, it's
|
||||
skipped when plotting.
|
||||
|
||||
There are two helpers included for retrieving images. The easiest work
|
||||
the way that you put in URLs instead of images in the data (like
|
||||
["myimage.png", 0, 0, 10, 10]), then call $.plot.image.loadData(data,
|
||||
options, callback) where data and options are the same as you pass in
|
||||
to $.plot. This loads the images, replaces the URLs in the data with
|
||||
the corresponding images and calls "callback" when all images are
|
||||
loaded (or failed loading). In the callback, you can then call $.plot
|
||||
with the data set. See the included example.
|
||||
|
||||
A more low-level helper, $.plot.image.load(urls, callback) is also
|
||||
included. Given a list of URLs, it calls callback with an object
|
||||
mapping from URL to Image object when all images are loaded or have
|
||||
failed loading.
|
||||
|
||||
Options for the plugin are
|
||||
|
||||
series: {
|
||||
images: {
|
||||
show: boolean
|
||||
anchor: "corner" or "center"
|
||||
alpha: [0,1]
|
||||
}
|
||||
}
|
||||
|
||||
which can be specified for a specific series
|
||||
|
||||
$.plot($("#placeholder"), [{ data: [ ... ], images: { ... } ])
|
||||
|
||||
Note that because the data format is different from usual data points,
|
||||
you can't use images with anything else in a specific data series.
|
||||
|
||||
Setting "anchor" to "center" causes the pixels in the image to be
|
||||
anchored at the corner pixel centers inside of at the pixel corners,
|
||||
effectively letting half a pixel stick out to each side in the plot.
|
||||
|
||||
|
||||
A possible future direction could be support for tiling for large
|
||||
images (like Google Maps).
|
||||
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
series: {
|
||||
images: {
|
||||
show: false,
|
||||
alpha: 1,
|
||||
anchor: "corner" // or "center"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.plot.image = {};
|
||||
|
||||
$.plot.image.loadDataImages = function (series, options, callback) {
|
||||
var urls = [], points = [];
|
||||
|
||||
var defaultShow = options.series.images.show;
|
||||
|
||||
$.each(series, function (i, s) {
|
||||
if (!(defaultShow || s.images.show))
|
||||
return;
|
||||
|
||||
if (s.data)
|
||||
s = s.data;
|
||||
|
||||
$.each(s, function (i, p) {
|
||||
if (typeof p[0] == "string") {
|
||||
urls.push(p[0]);
|
||||
points.push(p);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$.plot.image.load(urls, function (loadedImages) {
|
||||
$.each(points, function (i, p) {
|
||||
var url = p[0];
|
||||
if (loadedImages[url])
|
||||
p[0] = loadedImages[url];
|
||||
});
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
$.plot.image.load = function (urls, callback) {
|
||||
var missing = urls.length, loaded = {};
|
||||
if (missing == 0)
|
||||
callback({});
|
||||
|
||||
$.each(urls, function (i, url) {
|
||||
var handler = function () {
|
||||
--missing;
|
||||
|
||||
loaded[url] = this;
|
||||
|
||||
if (missing == 0)
|
||||
callback(loaded);
|
||||
};
|
||||
|
||||
$('<img />').load(handler).error(handler).attr('src', url);
|
||||
});
|
||||
}
|
||||
|
||||
function draw(plot, ctx) {
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
|
||||
$.each(plot.getData(), function (i, series) {
|
||||
var points = series.datapoints.points,
|
||||
ps = series.datapoints.pointsize;
|
||||
|
||||
for (var i = 0; i < points.length; i += ps) {
|
||||
var img = points[i],
|
||||
x1 = points[i + 1], y1 = points[i + 2],
|
||||
x2 = points[i + 3], y2 = points[i + 4],
|
||||
xaxis = series.xaxis, yaxis = series.yaxis,
|
||||
tmp;
|
||||
|
||||
// actually we should check img.complete, but it
|
||||
// appears to be a somewhat unreliable indicator in
|
||||
// IE6 (false even after load event)
|
||||
if (!img || img.width <= 0 || img.height <= 0)
|
||||
continue;
|
||||
|
||||
if (x1 > x2) {
|
||||
tmp = x2;
|
||||
x2 = x1;
|
||||
x1 = tmp;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
tmp = y2;
|
||||
y2 = y1;
|
||||
y1 = tmp;
|
||||
}
|
||||
|
||||
// if the anchor is at the center of the pixel, expand the
|
||||
// image by 1/2 pixel in each direction
|
||||
if (series.images.anchor == "center") {
|
||||
tmp = 0.5 * (x2-x1) / (img.width - 1);
|
||||
x1 -= tmp;
|
||||
x2 += tmp;
|
||||
tmp = 0.5 * (y2-y1) / (img.height - 1);
|
||||
y1 -= tmp;
|
||||
y2 += tmp;
|
||||
}
|
||||
|
||||
// clip
|
||||
if (x1 == x2 || y1 == y2 ||
|
||||
x1 >= xaxis.max || x2 <= xaxis.min ||
|
||||
y1 >= yaxis.max || y2 <= yaxis.min)
|
||||
continue;
|
||||
|
||||
var sx1 = 0, sy1 = 0, sx2 = img.width, sy2 = img.height;
|
||||
if (x1 < xaxis.min) {
|
||||
sx1 += (sx2 - sx1) * (xaxis.min - x1) / (x2 - x1);
|
||||
x1 = xaxis.min;
|
||||
}
|
||||
|
||||
if (x2 > xaxis.max) {
|
||||
sx2 += (sx2 - sx1) * (xaxis.max - x2) / (x2 - x1);
|
||||
x2 = xaxis.max;
|
||||
}
|
||||
|
||||
if (y1 < yaxis.min) {
|
||||
sy2 += (sy1 - sy2) * (yaxis.min - y1) / (y2 - y1);
|
||||
y1 = yaxis.min;
|
||||
}
|
||||
|
||||
if (y2 > yaxis.max) {
|
||||
sy1 += (sy1 - sy2) * (yaxis.max - y2) / (y2 - y1);
|
||||
y2 = yaxis.max;
|
||||
}
|
||||
|
||||
x1 = xaxis.p2c(x1);
|
||||
x2 = xaxis.p2c(x2);
|
||||
y1 = yaxis.p2c(y1);
|
||||
y2 = yaxis.p2c(y2);
|
||||
|
||||
// the transformation may have swapped us
|
||||
if (x1 > x2) {
|
||||
tmp = x2;
|
||||
x2 = x1;
|
||||
x1 = tmp;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
tmp = y2;
|
||||
y2 = y1;
|
||||
y1 = tmp;
|
||||
}
|
||||
|
||||
tmp = ctx.globalAlpha;
|
||||
ctx.globalAlpha *= series.images.alpha;
|
||||
ctx.drawImage(img,
|
||||
sx1, sy1, sx2 - sx1, sy2 - sy1,
|
||||
x1 + plotOffset.left, y1 + plotOffset.top,
|
||||
x2 - x1, y2 - y1);
|
||||
ctx.globalAlpha = tmp;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function processRawData(plot, series, data, datapoints) {
|
||||
if (!series.images.show)
|
||||
return;
|
||||
|
||||
// format is Image, x1, y1, x2, y2 (opposite corners)
|
||||
datapoints.format = [
|
||||
{ required: true },
|
||||
{ x: true, number: true, required: true },
|
||||
{ y: true, number: true, required: true },
|
||||
{ x: true, number: true, required: true },
|
||||
{ y: true, number: true, required: true }
|
||||
];
|
||||
}
|
||||
|
||||
function init(plot) {
|
||||
plot.hooks.processRawData.push(processRawData);
|
||||
plot.hooks.draw.push(draw);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'image',
|
||||
version: '1.1'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1 +0,0 @@
|
|||
(function(D){var B={series:{images:{show:false,alpha:1,anchor:"corner"}}};D.plot.image={};D.plot.image.loadDataImages=function(G,F,K){var J=[],H=[];var I=F.series.images.show;D.each(G,function(L,M){if(!(I||M.images.show)){return }if(M.data){M=M.data}D.each(M,function(N,O){if(typeof O[0]=="string"){J.push(O[0]);H.push(O)}})});D.plot.image.load(J,function(L){D.each(H,function(N,O){var M=O[0];if(L[M]){O[0]=L[M]}});K()})};D.plot.image.load=function(H,I){var G=H.length,F={};if(G==0){I({})}D.each(H,function(K,J){var L=function(){--G;F[J]=this;if(G==0){I(F)}};D("<img />").load(L).error(L).attr("src",J)})};function A(H,F){var G=H.getPlotOffset();D.each(H.getData(),function(O,P){var X=P.datapoints.points,I=P.datapoints.pointsize;for(var O=0;O<X.length;O+=I){var Q=X[O],M=X[O+1],V=X[O+2],K=X[O+3],T=X[O+4],W=P.xaxis,S=P.yaxis,N;if(!Q||Q.width<=0||Q.height<=0){continue}if(M>K){N=K;K=M;M=N}if(V>T){N=T;T=V;V=N}if(P.images.anchor=="center"){N=0.5*(K-M)/(Q.width-1);M-=N;K+=N;N=0.5*(T-V)/(Q.height-1);V-=N;T+=N}if(M==K||V==T||M>=W.max||K<=W.min||V>=S.max||T<=S.min){continue}var L=0,U=0,J=Q.width,R=Q.height;if(M<W.min){L+=(J-L)*(W.min-M)/(K-M);M=W.min}if(K>W.max){J+=(J-L)*(W.max-K)/(K-M);K=W.max}if(V<S.min){R+=(U-R)*(S.min-V)/(T-V);V=S.min}if(T>S.max){U+=(U-R)*(S.max-T)/(T-V);T=S.max}M=W.p2c(M);K=W.p2c(K);V=S.p2c(V);T=S.p2c(T);if(M>K){N=K;K=M;M=N}if(V>T){N=T;T=V;V=N}N=F.globalAlpha;F.globalAlpha*=P.images.alpha;F.drawImage(Q,L,U,J-L,R-U,M+G.left,V+G.top,K-M,T-V);F.globalAlpha=N}})}function C(I,F,G,H){if(!F.images.show){return }H.format=[{required:true},{x:true,number:true,required:true},{y:true,number:true,required:true},{x:true,number:true,required:true},{y:true,number:true,required:true}]}function E(F){F.hooks.processRawData.push(C);F.hooks.draw.push(A)}D.plot.plugins.push({init:E,options:B,name:"image",version:"1.1"})})(jQuery);
|
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
@ -1,272 +0,0 @@
|
|||
/*
|
||||
Flot plugin for adding panning and zooming capabilities to a plot.
|
||||
|
||||
The default behaviour is double click and scrollwheel up/down to zoom
|
||||
in, drag to pan. The plugin defines plot.zoom({ center }),
|
||||
plot.zoomOut() and plot.pan(offset) so you easily can add custom
|
||||
controls. It also fires a "plotpan" and "plotzoom" event when
|
||||
something happens, useful for synchronizing plots.
|
||||
|
||||
Example usage:
|
||||
|
||||
plot = $.plot(...);
|
||||
|
||||
// zoom default amount in on the pixel (100, 200)
|
||||
plot.zoom({ center: { left: 10, top: 20 } });
|
||||
|
||||
// zoom out again
|
||||
plot.zoomOut({ center: { left: 10, top: 20 } });
|
||||
|
||||
// pan 100 pixels to the left and 20 down
|
||||
plot.pan({ left: -100, top: 20 })
|
||||
|
||||
|
||||
Options:
|
||||
|
||||
zoom: {
|
||||
interactive: false
|
||||
trigger: "dblclick" // or "click" for single click
|
||||
amount: 1.5 // 2 = 200% (zoom in), 0.5 = 50% (zoom out)
|
||||
}
|
||||
|
||||
pan: {
|
||||
interactive: false
|
||||
}
|
||||
|
||||
xaxis, yaxis, x2axis, y2axis: {
|
||||
zoomRange: null // or [number, number] (min range, max range)
|
||||
panRange: null // or [number, number] (min, max)
|
||||
}
|
||||
|
||||
"interactive" enables the built-in drag/click behaviour. "amount" is
|
||||
the amount to zoom the viewport relative to the current range, so 1 is
|
||||
100% (i.e. no change), 1.5 is 150% (zoom in), 0.7 is 70% (zoom out).
|
||||
|
||||
"zoomRange" is the interval in which zooming can happen, e.g. with
|
||||
zoomRange: [1, 100] the zoom will never scale the axis so that the
|
||||
difference between min and max is smaller than 1 or larger than 100.
|
||||
You can set either of them to null to ignore.
|
||||
|
||||
"panRange" confines the panning to stay within a range, e.g. with
|
||||
panRange: [-10, 20] panning stops at -10 in one end and at 20 in the
|
||||
other. Either can be null.
|
||||
*/
|
||||
|
||||
|
||||
// First two dependencies, jquery.event.drag.js and
|
||||
// jquery.mousewheel.js, we put them inline here to save people the
|
||||
// effort of downloading them.
|
||||
|
||||
/*
|
||||
jquery.event.drag.js ~ v1.5 ~ Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
|
||||
Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-LICENSE.txt
|
||||
*/
|
||||
(function(E){E.fn.drag=function(L,K,J){if(K){this.bind("dragstart",L)}if(J){this.bind("dragend",J)}return !L?this.trigger("drag"):this.bind("drag",K?K:L)};var A=E.event,B=A.special,F=B.drag={not:":input",distance:0,which:1,dragging:false,setup:function(J){J=E.extend({distance:F.distance,which:F.which,not:F.not},J||{});J.distance=I(J.distance);A.add(this,"mousedown",H,J);if(this.attachEvent){this.attachEvent("ondragstart",D)}},teardown:function(){A.remove(this,"mousedown",H);if(this===F.dragging){F.dragging=F.proxy=false}G(this,true);if(this.detachEvent){this.detachEvent("ondragstart",D)}}};B.dragstart=B.dragend={setup:function(){},teardown:function(){}};function H(L){var K=this,J,M=L.data||{};if(M.elem){K=L.dragTarget=M.elem;L.dragProxy=F.proxy||K;L.cursorOffsetX=M.pageX-M.left;L.cursorOffsetY=M.pageY-M.top;L.offsetX=L.pageX-L.cursorOffsetX;L.offsetY=L.pageY-L.cursorOffsetY}else{if(F.dragging||(M.which>0&&L.which!=M.which)||E(L.target).is(M.not)){return }}switch(L.type){case"mousedown":E.extend(M,E(K).offset(),{elem:K,target:L.target,pageX:L.pageX,pageY:L.pageY});A.add(document,"mousemove mouseup",H,M);G(K,false);F.dragging=null;return false;case !F.dragging&&"mousemove":if(I(L.pageX-M.pageX)+I(L.pageY-M.pageY)<M.distance){break}L.target=M.target;J=C(L,"dragstart",K);if(J!==false){F.dragging=K;F.proxy=L.dragProxy=E(J||K)[0]}case"mousemove":if(F.dragging){J=C(L,"drag",K);if(B.drop){B.drop.allowed=(J!==false);B.drop.handler(L)}if(J!==false){break}L.type="mouseup"}case"mouseup":A.remove(document,"mousemove mouseup",H);if(F.dragging){if(B.drop){B.drop.handler(L)}C(L,"dragend",K)}G(K,true);F.dragging=F.proxy=M.elem=false;break}return true}function C(M,K,L){M.type=K;var J=E.event.handle.call(L,M);return J===false?false:J||M.result}function I(J){return Math.pow(J,2)}function D(){return(F.dragging===false)}function G(K,J){if(!K){return }K.unselectable=J?"off":"on";K.onselectstart=function(){return J};if(K.style){K.style.MozUserSelect=J?"":"none"}}})(jQuery);
|
||||
|
||||
|
||||
/* jquery.mousewheel.min.js
|
||||
* Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
|
||||
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
|
||||
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
|
||||
* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
|
||||
* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
|
||||
*
|
||||
* Version: 3.0.2
|
||||
*
|
||||
* Requires: 1.2.2+
|
||||
*/
|
||||
(function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(f){var d=[].slice.call(arguments,1),g=0,e=true;f=c.event.fix(f||window.event);f.type="mousewheel";if(f.wheelDelta){g=f.wheelDelta/120}if(f.detail){g=-f.detail/3}d.unshift(f,g);return c.event.handle.apply(this,d)}})(jQuery);
|
||||
|
||||
|
||||
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
xaxis: {
|
||||
zoomRange: null, // or [number, number] (min range, max range)
|
||||
panRange: null // or [number, number] (min, max)
|
||||
},
|
||||
zoom: {
|
||||
interactive: false,
|
||||
trigger: "dblclick", // or "click" for single click
|
||||
amount: 1.5 // how much to zoom relative to current position, 2 = 200% (zoom in), 0.5 = 50% (zoom out)
|
||||
},
|
||||
pan: {
|
||||
interactive: false
|
||||
}
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
function bindEvents(plot, eventHolder) {
|
||||
var o = plot.getOptions();
|
||||
if (o.zoom.interactive) {
|
||||
function clickHandler(e, zoomOut) {
|
||||
var c = plot.offset();
|
||||
c.left = e.pageX - c.left;
|
||||
c.top = e.pageY - c.top;
|
||||
if (zoomOut)
|
||||
plot.zoomOut({ center: c });
|
||||
else
|
||||
plot.zoom({ center: c });
|
||||
}
|
||||
|
||||
eventHolder[o.zoom.trigger](clickHandler);
|
||||
|
||||
eventHolder.mousewheel(function (e, delta) {
|
||||
clickHandler(e, delta < 0);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
if (o.pan.interactive) {
|
||||
var prevCursor = 'default', pageX = 0, pageY = 0;
|
||||
|
||||
eventHolder.bind("dragstart", { distance: 10 }, function (e) {
|
||||
if (e.which != 1) // only accept left-click
|
||||
return false;
|
||||
eventHolderCursor = eventHolder.css('cursor');
|
||||
eventHolder.css('cursor', 'move');
|
||||
pageX = e.pageX;
|
||||
pageY = e.pageY;
|
||||
});
|
||||
eventHolder.bind("drag", function (e) {
|
||||
// unused at the moment, but we need it here to
|
||||
// trigger the dragstart/dragend events
|
||||
});
|
||||
eventHolder.bind("dragend", function (e) {
|
||||
eventHolder.css('cursor', prevCursor);
|
||||
plot.pan({ left: pageX - e.pageX,
|
||||
top: pageY - e.pageY });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
plot.zoomOut = function (args) {
|
||||
if (!args)
|
||||
args = {};
|
||||
|
||||
if (!args.amount)
|
||||
args.amount = plot.getOptions().zoom.amount
|
||||
|
||||
args.amount = 1 / args.amount;
|
||||
plot.zoom(args);
|
||||
}
|
||||
|
||||
plot.zoom = function (args) {
|
||||
if (!args)
|
||||
args = {};
|
||||
|
||||
var axes = plot.getAxes(),
|
||||
options = plot.getOptions(),
|
||||
c = args.center,
|
||||
amount = args.amount ? args.amount : options.zoom.amount,
|
||||
w = plot.width(), h = plot.height();
|
||||
|
||||
if (!c)
|
||||
c = { left: w / 2, top: h / 2 };
|
||||
|
||||
var xf = c.left / w,
|
||||
x1 = c.left - xf * w / amount,
|
||||
x2 = c.left + (1 - xf) * w / amount,
|
||||
yf = c.top / h,
|
||||
y1 = c.top - yf * h / amount,
|
||||
y2 = c.top + (1 - yf) * h / amount;
|
||||
|
||||
function scaleAxis(min, max, name) {
|
||||
var axis = axes[name],
|
||||
axisOptions = options[name];
|
||||
|
||||
if (!axis.used)
|
||||
return;
|
||||
|
||||
min = axis.c2p(min);
|
||||
max = axis.c2p(max);
|
||||
if (max < min) { // make sure min < max
|
||||
var tmp = min
|
||||
min = max;
|
||||
max = tmp;
|
||||
}
|
||||
|
||||
var range = max - min, zr = axisOptions.zoomRange;
|
||||
if (zr &&
|
||||
((zr[0] != null && range < zr[0]) ||
|
||||
(zr[1] != null && range > zr[1])))
|
||||
return;
|
||||
|
||||
axisOptions.min = min;
|
||||
axisOptions.max = max;
|
||||
}
|
||||
|
||||
scaleAxis(x1, x2, 'xaxis');
|
||||
scaleAxis(x1, x2, 'x2axis');
|
||||
scaleAxis(y1, y2, 'yaxis');
|
||||
scaleAxis(y1, y2, 'y2axis');
|
||||
|
||||
plot.setupGrid();
|
||||
plot.draw();
|
||||
|
||||
if (!args.preventEvent)
|
||||
plot.getPlaceholder().trigger("plotzoom", [ plot ]);
|
||||
}
|
||||
|
||||
plot.pan = function (args) {
|
||||
var l = +args.left, t = +args.top,
|
||||
axes = plot.getAxes(), options = plot.getOptions();
|
||||
|
||||
if (isNaN(l))
|
||||
l = 0;
|
||||
if (isNaN(t))
|
||||
t = 0;
|
||||
|
||||
function panAxis(delta, name) {
|
||||
var axis = axes[name],
|
||||
axisOptions = options[name],
|
||||
min, max;
|
||||
|
||||
if (!axis.used)
|
||||
return;
|
||||
|
||||
min = axis.c2p(axis.p2c(axis.min) + delta),
|
||||
max = axis.c2p(axis.p2c(axis.max) + delta);
|
||||
|
||||
var pr = axisOptions.panRange;
|
||||
if (pr) {
|
||||
// check whether we hit the wall
|
||||
if (pr[0] != null && pr[0] > min) {
|
||||
delta = pr[0] - min;
|
||||
min += delta;
|
||||
max += delta;
|
||||
}
|
||||
|
||||
if (pr[1] != null && pr[1] < max) {
|
||||
delta = pr[1] - max;
|
||||
min += delta;
|
||||
max += delta;
|
||||
}
|
||||
}
|
||||
|
||||
axisOptions.min = min;
|
||||
axisOptions.max = max;
|
||||
}
|
||||
|
||||
panAxis(l, 'xaxis');
|
||||
panAxis(l, 'x2axis');
|
||||
panAxis(t, 'yaxis');
|
||||
panAxis(t, 'y2axis');
|
||||
|
||||
plot.setupGrid();
|
||||
plot.draw();
|
||||
|
||||
if (!args.preventEvent)
|
||||
plot.getPlaceholder().trigger("plotpan", [ plot ]);
|
||||
}
|
||||
|
||||
plot.hooks.bindEvents.push(bindEvents);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'navigate',
|
||||
version: '1.1'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1 +0,0 @@
|
|||
(function(R){R.fn.drag=function(A,B,C){if(B){this.bind("dragstart",A)}if(C){this.bind("dragend",C)}return !A?this.trigger("drag"):this.bind("drag",B?B:A)};var M=R.event,L=M.special,Q=L.drag={not:":input",distance:0,which:1,dragging:false,setup:function(A){A=R.extend({distance:Q.distance,which:Q.which,not:Q.not},A||{});A.distance=N(A.distance);M.add(this,"mousedown",O,A);if(this.attachEvent){this.attachEvent("ondragstart",J)}},teardown:function(){M.remove(this,"mousedown",O);if(this===Q.dragging){Q.dragging=Q.proxy=false}P(this,true);if(this.detachEvent){this.detachEvent("ondragstart",J)}}};L.dragstart=L.dragend={setup:function(){},teardown:function(){}};function O(A){var B=this,C,D=A.data||{};if(D.elem){B=A.dragTarget=D.elem;A.dragProxy=Q.proxy||B;A.cursorOffsetX=D.pageX-D.left;A.cursorOffsetY=D.pageY-D.top;A.offsetX=A.pageX-A.cursorOffsetX;A.offsetY=A.pageY-A.cursorOffsetY}else{if(Q.dragging||(D.which>0&&A.which!=D.which)||R(A.target).is(D.not)){return }}switch(A.type){case"mousedown":R.extend(D,R(B).offset(),{elem:B,target:A.target,pageX:A.pageX,pageY:A.pageY});M.add(document,"mousemove mouseup",O,D);P(B,false);Q.dragging=null;return false;case !Q.dragging&&"mousemove":if(N(A.pageX-D.pageX)+N(A.pageY-D.pageY)<D.distance){break}A.target=D.target;C=K(A,"dragstart",B);if(C!==false){Q.dragging=B;Q.proxy=A.dragProxy=R(C||B)[0]}case"mousemove":if(Q.dragging){C=K(A,"drag",B);if(L.drop){L.drop.allowed=(C!==false);L.drop.handler(A)}if(C!==false){break}A.type="mouseup"}case"mouseup":M.remove(document,"mousemove mouseup",O);if(Q.dragging){if(L.drop){L.drop.handler(A)}K(A,"dragend",B)}P(B,true);Q.dragging=Q.proxy=D.elem=false;break}return true}function K(D,B,A){D.type=B;var C=R.event.handle.call(A,D);return C===false?false:C||D.result}function N(A){return Math.pow(A,2)}function J(){return(Q.dragging===false)}function P(A,B){if(!A){return }A.unselectable=B?"off":"on";A.onselectstart=function(){return B};if(A.style){A.style.MozUserSelect=B?"":"none"}}})(jQuery);(function(C){var B=["DOMMouseScroll","mousewheel"];C.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var D=B.length;D;){this.addEventListener(B[--D],A,false)}}else{this.onmousewheel=A}},teardown:function(){if(this.removeEventListener){for(var D=B.length;D;){this.removeEventListener(B[--D],A,false)}}else{this.onmousewheel=null}}};C.fn.extend({mousewheel:function(D){return D?this.bind("mousewheel",D):this.trigger("mousewheel")},unmousewheel:function(D){return this.unbind("mousewheel",D)}});function A(E){var G=[].slice.call(arguments,1),D=0,F=true;E=C.event.fix(E||window.event);E.type="mousewheel";if(E.wheelDelta){D=E.wheelDelta/120}if(E.detail){D=-E.detail/3}G.unshift(E,D);return C.event.handle.apply(this,G)}})(jQuery);(function(B){var A={xaxis:{zoomRange:null,panRange:null},zoom:{interactive:false,trigger:"dblclick",amount:1.5},pan:{interactive:false}};function C(D){function E(J,F){var K=J.getOptions();if(K.zoom.interactive){function L(N,M){var O=J.offset();O.left=N.pageX-O.left;O.top=N.pageY-O.top;if(M){J.zoomOut({center:O})}else{J.zoom({center:O})}}F[K.zoom.trigger](L);F.mousewheel(function(M,N){L(M,N<0);return false})}if(K.pan.interactive){var I="default",H=0,G=0;F.bind("dragstart",{distance:10},function(M){if(M.which!=1){return false}eventHolderCursor=F.css("cursor");F.css("cursor","move");H=M.pageX;G=M.pageY});F.bind("drag",function(M){});F.bind("dragend",function(M){F.css("cursor",I);J.pan({left:H-M.pageX,top:G-M.pageY})})}}D.zoomOut=function(F){if(!F){F={}}if(!F.amount){F.amount=D.getOptions().zoom.amount}F.amount=1/F.amount;D.zoom(F)};D.zoom=function(M){if(!M){M={}}var L=D.getAxes(),S=D.getOptions(),N=M.center,J=M.amount?M.amount:S.zoom.amount,R=D.width(),I=D.height();if(!N){N={left:R/2,top:I/2}}var Q=N.left/R,G=N.left-Q*R/J,F=N.left+(1-Q)*R/J,H=N.top/I,P=N.top-H*I/J,O=N.top+(1-H)*I/J;function K(X,T,V){var Y=L[V],a=S[V];if(!Y.used){return }X=Y.c2p(X);T=Y.c2p(T);if(T<X){var W=X;X=T;T=W}var U=T-X,Z=a.zoomRange;if(Z&&((Z[0]!=null&&U<Z[0])||(Z[1]!=null&&U>Z[1]))){return }a.min=X;a.max=T}K(G,F,"xaxis");K(G,F,"x2axis");K(P,O,"yaxis");K(P,O,"y2axis");D.setupGrid();D.draw();if(!M.preventEvent){D.getPlaceholder().trigger("plotzoom",[D])}};D.pan=function(I){var F=+I.left,J=+I.top,K=D.getAxes(),H=D.getOptions();if(isNaN(F)){F=0}if(isNaN(J)){J=0}function G(R,M){var O=K[M],Q=H[M],N,L;if(!O.used){return }N=O.c2p(O.p2c(O.min)+R),L=O.c2p(O.p2c(O.max)+R);var P=Q.panRange;if(P){if(P[0]!=null&&P[0]>N){R=P[0]-N;N+=R;L+=R}if(P[1]!=null&&P[1]<L){R=P[1]-L;N+=R;L+=R}}Q.min=N;Q.max=L}G(F,"xaxis");G(F,"x2axis");G(J,"yaxis");G(J,"y2axis");D.setupGrid();D.draw();if(!I.preventEvent){D.getPlaceholder().trigger("plotpan",[D])}};D.hooks.bindEvents.push(E)}B.plot.plugins.push({init:C,options:A,name:"navigate",version:"1.1"})})(jQuery);
|
|
@ -1,299 +0,0 @@
|
|||
/*
|
||||
Flot plugin for selecting regions.
|
||||
|
||||
The plugin defines the following options:
|
||||
|
||||
selection: {
|
||||
mode: null or "x" or "y" or "xy",
|
||||
color: color
|
||||
}
|
||||
|
||||
You enable selection support by setting the mode to one of "x", "y" or
|
||||
"xy". In "x" mode, the user will only be able to specify the x range,
|
||||
similarly for "y" mode. For "xy", the selection becomes a rectangle
|
||||
where both ranges can be specified. "color" is color of the selection.
|
||||
|
||||
When selection support is enabled, a "plotselected" event will be emitted
|
||||
on the DOM element you passed into the plot function. The event
|
||||
handler gets one extra parameter with the ranges selected on the axes,
|
||||
like this:
|
||||
|
||||
placeholder.bind("plotselected", function(event, ranges) {
|
||||
alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
|
||||
// similar for yaxis, secondary axes are in x2axis
|
||||
// and y2axis if present
|
||||
});
|
||||
|
||||
The "plotselected" event is only fired when the user has finished
|
||||
making the selection. A "plotselecting" event is fired during the
|
||||
process with the same parameters as the "plotselected" event, in case
|
||||
you want to know what's happening while it's happening,
|
||||
|
||||
A "plotunselected" event with no arguments is emitted when the user
|
||||
clicks the mouse to remove the selection.
|
||||
|
||||
The plugin allso adds the following methods to the plot object:
|
||||
|
||||
- setSelection(ranges, preventEvent)
|
||||
|
||||
Set the selection rectangle. The passed in ranges is on the same
|
||||
form as returned in the "plotselected" event. If the selection
|
||||
mode is "x", you should put in either an xaxis (or x2axis) object,
|
||||
if the mode is "y" you need to put in an yaxis (or y2axis) object
|
||||
and both xaxis/x2axis and yaxis/y2axis if the selection mode is
|
||||
"xy", like this:
|
||||
|
||||
setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
|
||||
|
||||
setSelection will trigger the "plotselected" event when called. If
|
||||
you don't want that to happen, e.g. if you're inside a
|
||||
"plotselected" handler, pass true as the second parameter.
|
||||
|
||||
- clearSelection(preventEvent)
|
||||
|
||||
Clear the selection rectangle. Pass in true to avoid getting a
|
||||
"plotunselected" event.
|
||||
|
||||
- getSelection()
|
||||
|
||||
Returns the current selection in the same format as the
|
||||
"plotselected" event. If there's currently no selection, the
|
||||
function returns null.
|
||||
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
function init(plot) {
|
||||
var selection = {
|
||||
first: { x: -1, y: -1}, second: { x: -1, y: -1},
|
||||
show: false,
|
||||
active: false
|
||||
};
|
||||
|
||||
// FIXME: The drag handling implemented here should be
|
||||
// abstracted out, there's some similar code from a library in
|
||||
// the navigation plugin, this should be massaged a bit to fit
|
||||
// the Flot cases here better and reused. Doing this would
|
||||
// make this plugin much slimmer.
|
||||
var savedhandlers = {};
|
||||
|
||||
function onMouseMove(e) {
|
||||
if (selection.active) {
|
||||
plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]);
|
||||
|
||||
updateSelection(e);
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseDown(e) {
|
||||
if (e.which != 1) // only accept left-click
|
||||
return;
|
||||
|
||||
// cancel out any text selections
|
||||
document.body.focus();
|
||||
|
||||
// prevent text selection and drag in old-school browsers
|
||||
if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) {
|
||||
savedhandlers.onselectstart = document.onselectstart;
|
||||
document.onselectstart = function () { return false; };
|
||||
}
|
||||
if (document.ondrag !== undefined && savedhandlers.ondrag == null) {
|
||||
savedhandlers.ondrag = document.ondrag;
|
||||
document.ondrag = function () { return false; };
|
||||
}
|
||||
|
||||
setSelectionPos(selection.first, e);
|
||||
|
||||
selection.active = true;
|
||||
|
||||
$(document).one("mouseup", onMouseUp);
|
||||
}
|
||||
|
||||
function onMouseUp(e) {
|
||||
// revert drag stuff for old-school browsers
|
||||
if (document.onselectstart !== undefined)
|
||||
document.onselectstart = savedhandlers.onselectstart;
|
||||
if (document.ondrag !== undefined)
|
||||
document.ondrag = savedhandlers.ondrag;
|
||||
|
||||
// no more draggy-dee-drag
|
||||
selection.active = false;
|
||||
updateSelection(e);
|
||||
|
||||
if (selectionIsSane())
|
||||
triggerSelectedEvent();
|
||||
else {
|
||||
// this counts as a clear
|
||||
plot.getPlaceholder().trigger("plotunselected", [ ]);
|
||||
plot.getPlaceholder().trigger("plotselecting", [ null ]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSelection() {
|
||||
if (!selectionIsSane())
|
||||
return null;
|
||||
|
||||
var x1 = Math.min(selection.first.x, selection.second.x),
|
||||
x2 = Math.max(selection.first.x, selection.second.x),
|
||||
y1 = Math.max(selection.first.y, selection.second.y),
|
||||
y2 = Math.min(selection.first.y, selection.second.y);
|
||||
|
||||
var r = {};
|
||||
var axes = plot.getAxes();
|
||||
if (axes.xaxis.used)
|
||||
r.xaxis = { from: axes.xaxis.c2p(x1), to: axes.xaxis.c2p(x2) };
|
||||
if (axes.x2axis.used)
|
||||
r.x2axis = { from: axes.x2axis.c2p(x1), to: axes.x2axis.c2p(x2) };
|
||||
if (axes.yaxis.used)
|
||||
r.yaxis = { from: axes.yaxis.c2p(y1), to: axes.yaxis.c2p(y2) };
|
||||
if (axes.y2axis.used)
|
||||
r.y2axis = { from: axes.y2axis.c2p(y1), to: axes.y2axis.c2p(y2) };
|
||||
return r;
|
||||
}
|
||||
|
||||
function triggerSelectedEvent() {
|
||||
var r = getSelection();
|
||||
|
||||
plot.getPlaceholder().trigger("plotselected", [ r ]);
|
||||
|
||||
// backwards-compat stuff, to be removed in future
|
||||
var axes = plot.getAxes();
|
||||
if (axes.xaxis.used && axes.yaxis.used)
|
||||
plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
|
||||
}
|
||||
|
||||
function clamp(min, value, max) {
|
||||
return value < min? min: (value > max? max: value);
|
||||
}
|
||||
|
||||
function setSelectionPos(pos, e) {
|
||||
var o = plot.getOptions();
|
||||
var offset = plot.getPlaceholder().offset();
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width());
|
||||
pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height());
|
||||
|
||||
if (o.selection.mode == "y")
|
||||
pos.x = pos == selection.first? 0: plot.width();
|
||||
|
||||
if (o.selection.mode == "x")
|
||||
pos.y = pos == selection.first? 0: plot.height();
|
||||
}
|
||||
|
||||
function updateSelection(pos) {
|
||||
if (pos.pageX == null)
|
||||
return;
|
||||
|
||||
setSelectionPos(selection.second, pos);
|
||||
if (selectionIsSane()) {
|
||||
selection.show = true;
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
else
|
||||
clearSelection(true);
|
||||
}
|
||||
|
||||
function clearSelection(preventEvent) {
|
||||
if (selection.show) {
|
||||
selection.show = false;
|
||||
plot.triggerRedrawOverlay();
|
||||
if (!preventEvent)
|
||||
plot.getPlaceholder().trigger("plotunselected", [ ]);
|
||||
}
|
||||
}
|
||||
|
||||
function setSelection(ranges, preventEvent) {
|
||||
var axis, range, axes = plot.getAxes();
|
||||
var o = plot.getOptions();
|
||||
|
||||
if (o.selection.mode == "y") {
|
||||
selection.first.x = 0;
|
||||
selection.second.x = plot.width();
|
||||
}
|
||||
else {
|
||||
axis = ranges["xaxis"]? axes["xaxis"]: (ranges["x2axis"]? axes["x2axis"]: axes["xaxis"]);
|
||||
range = ranges["xaxis"] || ranges["x2axis"] || { from:ranges["x1"], to:ranges["x2"] }
|
||||
selection.first.x = axis.p2c(Math.min(range.from, range.to));
|
||||
selection.second.x = axis.p2c(Math.max(range.from, range.to));
|
||||
}
|
||||
|
||||
if (o.selection.mode == "x") {
|
||||
selection.first.y = 0;
|
||||
selection.second.y = plot.height();
|
||||
}
|
||||
else {
|
||||
axis = ranges["yaxis"]? axes["yaxis"]: (ranges["y2axis"]? axes["y2axis"]: axes["yaxis"]);
|
||||
range = ranges["yaxis"] || ranges["y2axis"] || { from:ranges["y1"], to:ranges["y2"] }
|
||||
selection.first.y = axis.p2c(Math.min(range.from, range.to));
|
||||
selection.second.y = axis.p2c(Math.max(range.from, range.to));
|
||||
}
|
||||
|
||||
selection.show = true;
|
||||
plot.triggerRedrawOverlay();
|
||||
if (!preventEvent)
|
||||
triggerSelectedEvent();
|
||||
}
|
||||
|
||||
function selectionIsSane() {
|
||||
var minSize = 5;
|
||||
return Math.abs(selection.second.x - selection.first.x) >= minSize &&
|
||||
Math.abs(selection.second.y - selection.first.y) >= minSize;
|
||||
}
|
||||
|
||||
plot.clearSelection = clearSelection;
|
||||
plot.setSelection = setSelection;
|
||||
plot.getSelection = getSelection;
|
||||
|
||||
plot.hooks.bindEvents.push(function(plot, eventHolder) {
|
||||
var o = plot.getOptions();
|
||||
if (o.selection.mode != null)
|
||||
eventHolder.mousemove(onMouseMove);
|
||||
|
||||
if (o.selection.mode != null)
|
||||
eventHolder.mousedown(onMouseDown);
|
||||
});
|
||||
|
||||
|
||||
plot.hooks.drawOverlay.push(function (plot, ctx) {
|
||||
// draw selection
|
||||
if (selection.show && selectionIsSane()) {
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
var o = plot.getOptions();
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(plotOffset.left, plotOffset.top);
|
||||
|
||||
var c = $.color.parse(o.selection.color);
|
||||
|
||||
ctx.strokeStyle = c.scale('a', 0.8).toString();
|
||||
ctx.lineWidth = 1;
|
||||
ctx.lineJoin = "round";
|
||||
ctx.fillStyle = c.scale('a', 0.4).toString();
|
||||
|
||||
var x = Math.min(selection.first.x, selection.second.x),
|
||||
y = Math.min(selection.first.y, selection.second.y),
|
||||
w = Math.abs(selection.second.x - selection.first.x),
|
||||
h = Math.abs(selection.second.y - selection.first.y);
|
||||
|
||||
ctx.fillRect(x, y, w, h);
|
||||
ctx.strokeRect(x, y, w, h);
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: {
|
||||
selection: {
|
||||
mode: null, // one of null, "x", "y" or "xy"
|
||||
color: "#e8cfac"
|
||||
}
|
||||
},
|
||||
name: 'selection',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1 +0,0 @@
|
|||
(function(A){function B(J){var O={first:{x:-1,y:-1},second:{x:-1,y:-1},show:false,active:false};var L={};function D(Q){if(O.active){J.getPlaceholder().trigger("plotselecting",[F()]);K(Q)}}function M(Q){if(Q.which!=1){return }document.body.focus();if(document.onselectstart!==undefined&&L.onselectstart==null){L.onselectstart=document.onselectstart;document.onselectstart=function(){return false}}if(document.ondrag!==undefined&&L.ondrag==null){L.ondrag=document.ondrag;document.ondrag=function(){return false}}C(O.first,Q);O.active=true;A(document).one("mouseup",I)}function I(Q){if(document.onselectstart!==undefined){document.onselectstart=L.onselectstart}if(document.ondrag!==undefined){document.ondrag=L.ondrag}O.active=false;K(Q);if(E()){H()}else{J.getPlaceholder().trigger("plotunselected",[]);J.getPlaceholder().trigger("plotselecting",[null])}return false}function F(){if(!E()){return null}var R=Math.min(O.first.x,O.second.x),Q=Math.max(O.first.x,O.second.x),T=Math.max(O.first.y,O.second.y),S=Math.min(O.first.y,O.second.y);var U={};var V=J.getAxes();if(V.xaxis.used){U.xaxis={from:V.xaxis.c2p(R),to:V.xaxis.c2p(Q)}}if(V.x2axis.used){U.x2axis={from:V.x2axis.c2p(R),to:V.x2axis.c2p(Q)}}if(V.yaxis.used){U.yaxis={from:V.yaxis.c2p(T),to:V.yaxis.c2p(S)}}if(V.y2axis.used){U.y2axis={from:V.y2axis.c2p(T),to:V.y2axis.c2p(S)}}return U}function H(){var Q=F();J.getPlaceholder().trigger("plotselected",[Q]);var R=J.getAxes();if(R.xaxis.used&&R.yaxis.used){J.getPlaceholder().trigger("selected",[{x1:Q.xaxis.from,y1:Q.yaxis.from,x2:Q.xaxis.to,y2:Q.yaxis.to}])}}function G(R,S,Q){return S<R?R:(S>Q?Q:S)}function C(U,R){var T=J.getOptions();var S=J.getPlaceholder().offset();var Q=J.getPlotOffset();U.x=G(0,R.pageX-S.left-Q.left,J.width());U.y=G(0,R.pageY-S.top-Q.top,J.height());if(T.selection.mode=="y"){U.x=U==O.first?0:J.width()}if(T.selection.mode=="x"){U.y=U==O.first?0:J.height()}}function K(Q){if(Q.pageX==null){return }C(O.second,Q);if(E()){O.show=true;J.triggerRedrawOverlay()}else{P(true)}}function P(Q){if(O.show){O.show=false;J.triggerRedrawOverlay();if(!Q){J.getPlaceholder().trigger("plotunselected",[])}}}function N(R,Q){var T,S,U=J.getAxes();var V=J.getOptions();if(V.selection.mode=="y"){O.first.x=0;O.second.x=J.width()}else{T=R.xaxis?U.xaxis:(R.x2axis?U.x2axis:U.xaxis);S=R.xaxis||R.x2axis||{from:R.x1,to:R.x2};O.first.x=T.p2c(Math.min(S.from,S.to));O.second.x=T.p2c(Math.max(S.from,S.to))}if(V.selection.mode=="x"){O.first.y=0;O.second.y=J.height()}else{T=R.yaxis?U.yaxis:(R.y2axis?U.y2axis:U.yaxis);S=R.yaxis||R.y2axis||{from:R.y1,to:R.y2};O.first.y=T.p2c(Math.min(S.from,S.to));O.second.y=T.p2c(Math.max(S.from,S.to))}O.show=true;J.triggerRedrawOverlay();if(!Q){H()}}function E(){var Q=5;return Math.abs(O.second.x-O.first.x)>=Q&&Math.abs(O.second.y-O.first.y)>=Q}J.clearSelection=P;J.setSelection=N;J.getSelection=F;J.hooks.bindEvents.push(function(R,Q){var S=R.getOptions();if(S.selection.mode!=null){Q.mousemove(D)}if(S.selection.mode!=null){Q.mousedown(M)}});J.hooks.drawOverlay.push(function(T,Y){if(O.show&&E()){var R=T.getPlotOffset();var Q=T.getOptions();Y.save();Y.translate(R.left,R.top);var U=A.color.parse(Q.selection.color);Y.strokeStyle=U.scale("a",0.8).toString();Y.lineWidth=1;Y.lineJoin="round";Y.fillStyle=U.scale("a",0.4).toString();var W=Math.min(O.first.x,O.second.x),V=Math.min(O.first.y,O.second.y),X=Math.abs(O.second.x-O.first.x),S=Math.abs(O.second.y-O.first.y);Y.fillRect(W,V,X,S);Y.strokeRect(W,V,X,S);Y.restore()}})}A.plot.plugins.push({init:B,options:{selection:{mode:null,color:"#e8cfac"}},name:"selection",version:"1.0"})})(jQuery);
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
Flot plugin for stacking data sets, i.e. putting them on top of each
|
||||
other, for accumulative graphs. Note that the plugin assumes the data
|
||||
is sorted on x. Also note that stacking a mix of positive and negative
|
||||
values in most instances doesn't make sense (so it looks weird).
|
||||
|
||||
Two or more series are stacked when their "stack" attribute is set to
|
||||
the same key (which can be any number or string or just "true"). To
|
||||
specify the default stack, you can set
|
||||
|
||||
series: {
|
||||
stack: null or true or key (number/string)
|
||||
}
|
||||
|
||||
or specify it for a specific series
|
||||
|
||||
$.plot($("#placeholder"), [{ data: [ ... ], stack: true ])
|
||||
|
||||
The stacking order is determined by the order of the data series in
|
||||
the array (later series end up on top of the previous).
|
||||
|
||||
Internally, the plugin modifies the datapoints in each series, adding
|
||||
an offset to the y value. For line series, extra data points are
|
||||
inserted through interpolation. For bar charts, the second y value is
|
||||
also adjusted.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
series: { stack: null } // or number/string
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
function findMatchingSeries(s, allseries) {
|
||||
var res = null
|
||||
for (var i = 0; i < allseries.length; ++i) {
|
||||
if (s == allseries[i])
|
||||
break;
|
||||
|
||||
if (allseries[i].stack == s.stack)
|
||||
res = allseries[i];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function stackData(plot, s, datapoints) {
|
||||
if (s.stack == null)
|
||||
return;
|
||||
|
||||
var other = findMatchingSeries(s, plot.getData());
|
||||
if (!other)
|
||||
return;
|
||||
|
||||
var ps = datapoints.pointsize,
|
||||
points = datapoints.points,
|
||||
otherps = other.datapoints.pointsize,
|
||||
otherpoints = other.datapoints.points,
|
||||
newpoints = [],
|
||||
px, py, intery, qx, qy, bottom,
|
||||
withlines = s.lines.show, withbars = s.bars.show,
|
||||
withsteps = withlines && s.lines.steps,
|
||||
i = 0, j = 0, l;
|
||||
|
||||
while (true) {
|
||||
if (i >= points.length)
|
||||
break;
|
||||
|
||||
l = newpoints.length;
|
||||
|
||||
if (j >= otherpoints.length
|
||||
|| otherpoints[j] == null
|
||||
|| points[i] == null) {
|
||||
// degenerate cases
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
i += ps;
|
||||
}
|
||||
else {
|
||||
// cases where we actually got two points
|
||||
px = points[i];
|
||||
py = points[i + 1];
|
||||
qx = otherpoints[j];
|
||||
qy = otherpoints[j + 1];
|
||||
bottom = 0;
|
||||
|
||||
if (px == qx) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
newpoints[l + 1] += qy;
|
||||
bottom = qy;
|
||||
|
||||
i += ps;
|
||||
j += otherps;
|
||||
}
|
||||
else if (px > qx) {
|
||||
// we got past point below, might need to
|
||||
// insert interpolated extra point
|
||||
if (withlines && i > 0 && points[i - ps] != null) {
|
||||
intery = py + (points[i - ps + 1] - py) * (qx - px) / (points[i - ps] - px);
|
||||
newpoints.push(qx);
|
||||
newpoints.push(intery + qy)
|
||||
for (m = 2; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
bottom = qy;
|
||||
}
|
||||
|
||||
j += otherps;
|
||||
}
|
||||
else {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
// we might be able to interpolate a point below,
|
||||
// this can give us a better y
|
||||
if (withlines && j > 0 && otherpoints[j - ps] != null)
|
||||
bottom = qy + (otherpoints[j - ps + 1] - qy) * (px - qx) / (otherpoints[j - ps] - qx);
|
||||
|
||||
newpoints[l + 1] += bottom;
|
||||
|
||||
i += ps;
|
||||
}
|
||||
|
||||
if (l != newpoints.length && withbars)
|
||||
newpoints[l + 2] += bottom;
|
||||
}
|
||||
|
||||
// maintain the line steps invariant
|
||||
if (withsteps && l != newpoints.length && l > 0
|
||||
&& newpoints[l] != null
|
||||
&& newpoints[l] != newpoints[l - ps]
|
||||
&& newpoints[l + 1] != newpoints[l - ps + 1]) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints[l + ps + m] = newpoints[l + m];
|
||||
newpoints[l + 1] = newpoints[l - ps + 1];
|
||||
}
|
||||
}
|
||||
|
||||
datapoints.points = newpoints;
|
||||
}
|
||||
|
||||
plot.hooks.processDatapoints.push(stackData);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'stack',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1 +0,0 @@
|
|||
(function(B){var A={series:{stack:null}};function C(F){function D(J,I){var H=null;for(var G=0;G<I.length;++G){if(J==I[G]){break}if(I[G].stack==J.stack){H=I[G]}}return H}function E(W,P,G){if(P.stack==null){return }var L=D(P,W.getData());if(!L){return }var T=G.pointsize,Y=G.points,H=L.datapoints.pointsize,S=L.datapoints.points,N=[],R,Q,I,a,Z,M,O=P.lines.show,K=P.bars.show,J=O&&P.lines.steps,X=0,V=0,U;while(true){if(X>=Y.length){break}U=N.length;if(V>=S.length||S[V]==null||Y[X]==null){for(m=0;m<T;++m){N.push(Y[X+m])}X+=T}else{R=Y[X];Q=Y[X+1];a=S[V];Z=S[V+1];M=0;if(R==a){for(m=0;m<T;++m){N.push(Y[X+m])}N[U+1]+=Z;M=Z;X+=T;V+=H}else{if(R>a){if(O&&X>0&&Y[X-T]!=null){I=Q+(Y[X-T+1]-Q)*(a-R)/(Y[X-T]-R);N.push(a);N.push(I+Z);for(m=2;m<T;++m){N.push(Y[X+m])}M=Z}V+=H}else{for(m=0;m<T;++m){N.push(Y[X+m])}if(O&&V>0&&S[V-T]!=null){M=Z+(S[V-T+1]-Z)*(R-a)/(S[V-T]-a)}N[U+1]+=M;X+=T}}if(U!=N.length&&K){N[U+2]+=M}}if(J&&U!=N.length&&U>0&&N[U]!=null&&N[U]!=N[U-T]&&N[U+1]!=N[U-T+1]){for(m=0;m<T;++m){N[U+T+m]=N[U+m]}N[U+1]=N[U-T+1]}}G.points=N}F.hooks.processDatapoints.push(E)}B.plot.plugins.push({init:C,options:A,name:"stack",version:"1.0"})})(jQuery);
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
Flot plugin for thresholding data. Controlled through the option
|
||||
"threshold" in either the global series options
|
||||
|
||||
series: {
|
||||
threshold: {
|
||||
below: number
|
||||
color: colorspec
|
||||
}
|
||||
}
|
||||
|
||||
or in a specific series
|
||||
|
||||
$.plot($("#placeholder"), [{ data: [ ... ], threshold: { ... }}])
|
||||
|
||||
The data points below "below" are drawn with the specified color. This
|
||||
makes it easy to mark points below 0, e.g. for budget data.
|
||||
|
||||
Internally, the plugin works by splitting the data into two series,
|
||||
above and below the threshold. The extra series below the threshold
|
||||
will have its label cleared and the special "originSeries" attribute
|
||||
set to the original series. You may need to check for this in hover
|
||||
events.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
series: { threshold: null } // or { below: number, color: color spec}
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
function thresholdData(plot, s, datapoints) {
|
||||
if (!s.threshold)
|
||||
return;
|
||||
|
||||
var ps = datapoints.pointsize, i, x, y, p, prevp,
|
||||
thresholded = $.extend({}, s); // note: shallow copy
|
||||
|
||||
thresholded.datapoints = { points: [], pointsize: ps };
|
||||
thresholded.label = null;
|
||||
thresholded.color = s.threshold.color;
|
||||
thresholded.threshold = null;
|
||||
thresholded.originSeries = s;
|
||||
thresholded.data = [];
|
||||
|
||||
var below = s.threshold.below,
|
||||
origpoints = datapoints.points,
|
||||
addCrossingPoints = s.lines.show;
|
||||
|
||||
threspoints = [];
|
||||
newpoints = [];
|
||||
|
||||
for (i = 0; i < origpoints.length; i += ps) {
|
||||
x = origpoints[i]
|
||||
y = origpoints[i + 1];
|
||||
|
||||
prevp = p;
|
||||
if (y < below)
|
||||
p = threspoints;
|
||||
else
|
||||
p = newpoints;
|
||||
|
||||
if (addCrossingPoints && prevp != p && x != null
|
||||
&& i > 0 && origpoints[i - ps] != null) {
|
||||
var interx = (x - origpoints[i - ps]) / (y - origpoints[i - ps + 1]) * (below - y) + x;
|
||||
prevp.push(interx);
|
||||
prevp.push(below);
|
||||
for (m = 2; m < ps; ++m)
|
||||
prevp.push(origpoints[i + m]);
|
||||
|
||||
p.push(null); // start new segment
|
||||
p.push(null);
|
||||
for (m = 2; m < ps; ++m)
|
||||
p.push(origpoints[i + m]);
|
||||
p.push(interx);
|
||||
p.push(below);
|
||||
for (m = 2; m < ps; ++m)
|
||||
p.push(origpoints[i + m]);
|
||||
}
|
||||
|
||||
p.push(x);
|
||||
p.push(y);
|
||||
}
|
||||
|
||||
datapoints.points = newpoints;
|
||||
thresholded.datapoints.points = threspoints;
|
||||
|
||||
if (thresholded.datapoints.points.length > 0)
|
||||
plot.getData().push(thresholded);
|
||||
|
||||
// FIXME: there are probably some edge cases left in bars
|
||||
}
|
||||
|
||||
plot.hooks.processDatapoints.push(thresholdData);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'threshold',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1 +0,0 @@
|
|||
(function(B){var A={series:{threshold:null}};function C(D){function E(L,S,M){if(!S.threshold){return }var F=M.pointsize,I,O,N,G,K,H=B.extend({},S);H.datapoints={points:[],pointsize:F};H.label=null;H.color=S.threshold.color;H.threshold=null;H.originSeries=S;H.data=[];var P=S.threshold.below,Q=M.points,R=S.lines.show;threspoints=[];newpoints=[];for(I=0;I<Q.length;I+=F){O=Q[I];N=Q[I+1];K=G;if(N<P){G=threspoints}else{G=newpoints}if(R&&K!=G&&O!=null&&I>0&&Q[I-F]!=null){var J=(O-Q[I-F])/(N-Q[I-F+1])*(P-N)+O;K.push(J);K.push(P);for(m=2;m<F;++m){K.push(Q[I+m])}G.push(null);G.push(null);for(m=2;m<F;++m){G.push(Q[I+m])}G.push(J);G.push(P);for(m=2;m<F;++m){G.push(Q[I+m])}}G.push(O);G.push(N)}M.points=newpoints;H.datapoints.points=threspoints;if(H.datapoints.points.length>0){L.getData().push(H)}}D.hooks.processDatapoints.push(E)}B.plot.plugins.push({init:C,options:A,name:"threshold",version:"1.0"})})(jQuery);
|
4376
web/public/javascripts/flot/jquery.js
vendored
4376
web/public/javascripts/flot/jquery.js
vendored
File diff suppressed because it is too large
Load diff
19
web/public/javascripts/flot/jquery.min.js
vendored
19
web/public/javascripts/flot/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,22 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'rubygems'
|
||||
require 'merb-core'
|
||||
|
||||
# this is Merb.root, change this if you have some funky setup.
|
||||
merb_root = File.expand_path(File.dirname(__FILE__) / '../')
|
||||
|
||||
# If the fcgi process runs as apache, make sure
|
||||
# we have an inlinedir set for Rubyinline action-args to work
|
||||
unless ENV["INLINEDIR"] || ENV["HOME"]
|
||||
tmpdir = merb_root / "tmp"
|
||||
unless File.directory?(tmpdir)
|
||||
Dir.mkdir(tmpdir)
|
||||
end
|
||||
ENV["INLINEDIR"] = tmpdir
|
||||
end
|
||||
|
||||
# start merb with the fcgi adapter, add options or change the log dir here
|
||||
Merb.start(:adapter => 'fcgi',
|
||||
:merb_root => merb_root,
|
||||
:log_file => merb_root /'log'/'merb.log')
|
|
@ -1,5 +0,0 @@
|
|||
# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
|
||||
#
|
||||
# To ban all spiders from the entire site uncomment the next two lines:
|
||||
# User-Agent: *
|
||||
# Disallow: /
|
|
@ -1,175 +0,0 @@
|
|||
body {
|
||||
font-family: Arial, Verdana, sans-serif;
|
||||
font-size: 12px;
|
||||
background-color: #fff;
|
||||
margin: 0px;
|
||||
}
|
||||
* {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
text-decoration: none;
|
||||
}
|
||||
html {
|
||||
height: 100%;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
#container {
|
||||
width: 80%;
|
||||
text-align: left;
|
||||
background-color: #fff;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
#header-container {
|
||||
width: 100%;
|
||||
padding-top: 15px;
|
||||
}
|
||||
#header-container h1, #header-container h2 {
|
||||
margin-left: 6px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.spacer {
|
||||
width: 100%;
|
||||
height: 15px;
|
||||
}
|
||||
hr {
|
||||
border: 0px;
|
||||
color: #ccc;
|
||||
background-color: #cdcdcd;
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
color: #c55;
|
||||
background-color: #fff;
|
||||
font-family: Arial, Verdana, sans-serif;
|
||||
font-weight: 300;
|
||||
}
|
||||
h2 {
|
||||
font-size: 15px;
|
||||
color: #999;
|
||||
font-family: Arial, Verdana, sans-serif;
|
||||
font-weight: 300;
|
||||
background-color: #fff;
|
||||
}
|
||||
h3 {
|
||||
color: #4d9b12;
|
||||
font-size: 15px;
|
||||
text-align: left;
|
||||
font-weight: 300;
|
||||
padding: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
#left-container {
|
||||
float: left;
|
||||
width: 250px;
|
||||
background-color: #FFFFFF;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#left-container h3 {
|
||||
color: #c55;
|
||||
}
|
||||
|
||||
#main-container {
|
||||
margin: 5px 5px 5px 260px;
|
||||
padding: 15px;
|
||||
border-left: 1px solid silver;
|
||||
min-height: 400px;
|
||||
}
|
||||
p {
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
line-height: 20px;
|
||||
padding: 5px;
|
||||
}
|
||||
a {
|
||||
color: #4d9b12;
|
||||
background-color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
color: #4d9b12;
|
||||
background-color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
#footer-container {
|
||||
clear: both;
|
||||
font-size: 12px;
|
||||
font-family: Verdana, Arial, sans-serif;
|
||||
}
|
||||
.right {
|
||||
float: right;
|
||||
font-size: 100%;
|
||||
margin-top: 5px;
|
||||
color: #999;
|
||||
background-color: #fff;
|
||||
}
|
||||
.left {
|
||||
float: left;
|
||||
font-size: 100%;
|
||||
margin-top: 5px;
|
||||
color: #999;
|
||||
background-color: #fff;
|
||||
}
|
||||
#main-container ul {
|
||||
margin-left: 3.0em;
|
||||
}
|
||||
|
||||
.searchBar {
|
||||
border-top: 2px solid black;
|
||||
border-bottom: 1px solid grey;
|
||||
background-color: #CCE8CF;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.searchBar label {
|
||||
font-weight: bold;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin-left: 1em;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.searchBar form {
|
||||
display: inline
|
||||
}
|
||||
|
||||
.logstash-logo {
|
||||
float:right;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 120%;
|
||||
padding-right: 1em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid black;
|
||||
}
|
||||
|
||||
#portal .searchBar {
|
||||
border: 2px solid black;
|
||||
width: 50%;
|
||||
margin-top: 5em;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
#portal .searchBar input[type="text"] {
|
||||
top: 0px;
|
||||
width: 20em;
|
||||
}
|
||||
|
||||
#portal .logstash-logo {
|
||||
float: none;
|
||||
position: relative;
|
||||
top: -2em;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
pre .datestamp {
|
||||
color: grey;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
|
||||
|
||||
describe "/search" do
|
||||
before(:each) do
|
||||
@response = request("/search")
|
||||
end
|
||||
end
|
|
@ -1,20 +0,0 @@
|
|||
require "rubygems"
|
||||
|
||||
# Add the local gems dir if found within the app root; any dependencies loaded
|
||||
# hereafter will try to load from the local gems before loading system gems.
|
||||
if (local_gem_dir = File.join(File.dirname(__FILE__), '..', 'gems')) && $BUNDLE.nil?
|
||||
$BUNDLE = true; Gem.clear_paths; Gem.path.unshift(local_gem_dir)
|
||||
end
|
||||
|
||||
require "merb-core"
|
||||
require "spec" # Satisfies Autotest and anyone else not using the Rake tasks
|
||||
|
||||
# this loads all plugins required in your init file so don't add them
|
||||
# here again, Merb will do it for you
|
||||
Merb.start_environment(:testing => true, :adapter => 'runner', :environment => ENV['MERB_ENV'] || 'test')
|
||||
|
||||
Spec::Runner.configure do |config|
|
||||
config.include(Merb::Test::ViewHelper)
|
||||
config.include(Merb::Test::RouteHelper)
|
||||
config.include(Merb::Test::ControllerHelper)
|
||||
end
|
|
@ -1,31 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This was added by Merb's bundler
|
||||
|
||||
require "rubygems"
|
||||
require File.join(File.dirname(__FILE__), "common")
|
||||
|
||||
gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')
|
||||
|
||||
if File.directory?(gems_dir)
|
||||
$BUNDLE = true
|
||||
Gem.clear_paths
|
||||
Gem.path.replace([File.expand_path(gems_dir)])
|
||||
ENV["PATH"] = "#{File.dirname(__FILE__)}:#{ENV["PATH"]}"
|
||||
|
||||
gem_file = File.join(gems_dir, "specifications", "<%= spec.name %>-*.gemspec")
|
||||
|
||||
if local_gem = Dir[gem_file].last
|
||||
version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1]
|
||||
end
|
||||
end
|
||||
|
||||
version ||= "<%= Gem::Requirement.default %>"
|
||||
|
||||
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
|
||||
version = $1
|
||||
ARGV.shift
|
||||
end
|
||||
|
||||
gem '<%= @spec.name %>', version
|
||||
load '<%= bin_file_name %>'
|
|
@ -1,68 +0,0 @@
|
|||
# This was added via Merb's bundler
|
||||
|
||||
require "rubygems"
|
||||
require "rubygems/source_index"
|
||||
|
||||
module Gem
|
||||
BUNDLED_SPECS = File.join(Dir.pwd, "gems", "specifications")
|
||||
MAIN_INDEX = Gem::SourceIndex.from_gems_in(BUNDLED_SPECS)
|
||||
FALLBACK_INDEX = Gem::SourceIndex.from_installed_gems
|
||||
|
||||
def self.source_index
|
||||
MultiSourceIndex.new
|
||||
end
|
||||
|
||||
def self.searcher
|
||||
MultiPathSearcher.new
|
||||
end
|
||||
|
||||
class ArbitrarySearcher < GemPathSearcher
|
||||
def initialize(source_index)
|
||||
@source_index = source_index
|
||||
super()
|
||||
end
|
||||
|
||||
def init_gemspecs
|
||||
@source_index.map { |_, spec| spec }.sort { |a,b|
|
||||
(a.name <=> b.name).nonzero? || (b.version <=> a.version)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
class MultiPathSearcher
|
||||
def initialize
|
||||
@main_searcher = ArbitrarySearcher.new(MAIN_INDEX)
|
||||
@fallback_searcher = ArbitrarySearcher.new(FALLBACK_INDEX)
|
||||
end
|
||||
|
||||
def find(path)
|
||||
try = @main_searcher.find(path)
|
||||
return try if try
|
||||
@fallback_searcher.find(path)
|
||||
end
|
||||
|
||||
def find_all(path)
|
||||
try = @main_searcher.find_all(path)
|
||||
return try unless try.empty?
|
||||
@fallback_searcher.find_all(path)
|
||||
end
|
||||
end
|
||||
|
||||
class MultiSourceIndex
|
||||
# Used by merb.thor to confirm; not needed when MSI is in use
|
||||
def load_gems_in(*args)
|
||||
end
|
||||
|
||||
def search(*args)
|
||||
try = MAIN_INDEX.search(*args)
|
||||
return try unless try.empty?
|
||||
FALLBACK_INDEX.search(*args)
|
||||
end
|
||||
|
||||
def find_name(*args)
|
||||
try = MAIN_INDEX.find_name(*args)
|
||||
return try unless try.empty?
|
||||
FALLBACK_INDEX.find_name(*args)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,125 +0,0 @@
|
|||
require "erb"
|
||||
|
||||
Gem.pre_install_hooks.push(proc do |installer|
|
||||
unless File.file?(installer.bin_dir / "common.rb")
|
||||
FileUtils.mkdir_p(installer.bin_dir)
|
||||
FileUtils.cp(File.dirname(__FILE__) / "common.rb", installer.bin_dir / "common.rb")
|
||||
end
|
||||
|
||||
include ColorfulMessages
|
||||
name = installer.spec.name
|
||||
if $GEMS && versions = ($GEMS.assoc(name) || [])[1]
|
||||
dep = Gem::Dependency.new(name, versions)
|
||||
unless dep.version_requirements.satisfied_by?(installer.spec.version)
|
||||
error "Cannot install #{installer.spec.full_name} " \
|
||||
"for #{$INSTALLING}; " \
|
||||
"you required #{dep}"
|
||||
::Thor::Tasks::Merb::Gem.rollback_trans
|
||||
exit!
|
||||
end
|
||||
end
|
||||
success "Installing #{installer.spec.full_name}"
|
||||
end)
|
||||
|
||||
class ::Gem::Uninstaller
|
||||
def self._with_silent_ui
|
||||
|
||||
ui = Gem::DefaultUserInteraction.ui
|
||||
def ui.say(str)
|
||||
puts "- #{str}"
|
||||
end
|
||||
|
||||
yield
|
||||
|
||||
class << Gem::DefaultUserInteraction.ui
|
||||
remove_method :say
|
||||
end
|
||||
end
|
||||
|
||||
def self._uninstall(source_index, name, op, version)
|
||||
unless source_index.find_name(name, "#{op} #{version}").empty?
|
||||
uninstaller = Gem::Uninstaller.new(
|
||||
name,
|
||||
:version => "#{op} #{version}",
|
||||
:install_dir => Dir.pwd / "gems",
|
||||
:all => true,
|
||||
:ignore => true
|
||||
)
|
||||
_with_silent_ui { uninstaller.uninstall }
|
||||
end
|
||||
end
|
||||
|
||||
def self._uninstall_others(source_index, name, version)
|
||||
_uninstall(source_index, name, "<", version)
|
||||
_uninstall(source_index, name, ">", version)
|
||||
end
|
||||
end
|
||||
|
||||
Gem.post_install_hooks.push(proc do |installer|
|
||||
source_index = installer.instance_variable_get("@source_index")
|
||||
::Gem::Uninstaller._uninstall_others(
|
||||
source_index, installer.spec.name, installer.spec.version
|
||||
)
|
||||
end)
|
||||
|
||||
class ::Gem::DependencyInstaller
|
||||
alias old_fg find_gems_with_sources
|
||||
|
||||
def find_gems_with_sources(dep)
|
||||
if @source_index.any? { |_, installed_spec|
|
||||
installed_spec.satisfies_requirement?(dep)
|
||||
}
|
||||
return []
|
||||
end
|
||||
|
||||
old_fg(dep)
|
||||
end
|
||||
end
|
||||
|
||||
class ::Gem::SpecFetcher
|
||||
alias old_fetch fetch
|
||||
def fetch(dependency, all = false, matching_platform = true)
|
||||
idx = Gem::SourceIndex.from_installed_gems
|
||||
|
||||
reqs = dependency.version_requirements.requirements
|
||||
|
||||
if reqs.size == 1 && reqs[0][0] == "="
|
||||
dep = idx.search(dependency).sort.last
|
||||
end
|
||||
|
||||
if dep
|
||||
file = dep.loaded_from.dup
|
||||
file.gsub!(/specifications/, "cache")
|
||||
file.gsub!(/gemspec$/, "gem")
|
||||
spec = ::Gem::Format.from_file_by_path(file).spec
|
||||
[[spec, file]]
|
||||
else
|
||||
old_fetch(dependency, all, matching_platform)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class ::Gem::Installer
|
||||
def app_script_text(bin_file_name)
|
||||
template = File.read(File.dirname(__FILE__) / "app_script.rb")
|
||||
erb = ERB.new(template)
|
||||
erb.result(binding)
|
||||
end
|
||||
end
|
||||
|
||||
class ::Gem::Specification
|
||||
def recursive_dependencies(from, index = Gem.source_index)
|
||||
specs = self.runtime_dependencies.map do |dep|
|
||||
spec = index.search(dep).last
|
||||
unless spec
|
||||
from_name = from.is_a?(::Gem::Specification) ? from.full_name : from.to_s
|
||||
wider_net = index.find_name(dep.name).last
|
||||
ThorUI.error "Needed #{dep} for #{from_name}, but could not find it"
|
||||
ThorUI.error "Found #{wider_net.full_name}" if wider_net
|
||||
::Thor::Tasks::Merb::Gem.rollback_trans
|
||||
end
|
||||
spec
|
||||
end
|
||||
specs + specs.map {|s| s.recursive_dependencies(self, index)}.flatten.uniq
|
||||
end
|
||||
end
|
|
@ -1,150 +0,0 @@
|
|||
require "rubygems"
|
||||
require "rubygems/source_index"
|
||||
require "rubygems/dependency_installer"
|
||||
require "rubygems/uninstaller"
|
||||
require "fileutils"
|
||||
require File.join(File.dirname(__FILE__), "utils")
|
||||
require File.join(File.dirname(__FILE__), "gem_ext")
|
||||
require File.join(File.dirname(__FILE__), "ops")
|
||||
|
||||
$INSTALLING = []
|
||||
|
||||
module Merb
|
||||
|
||||
class Gem < Thor
|
||||
extend ColorfulMessages
|
||||
|
||||
def initialize
|
||||
dirs = [Dir.pwd, File.dirname(__FILE__) / ".."]
|
||||
root = dirs.find {|d| File.file?(d / "config" / "dependencies.rb")}
|
||||
|
||||
if root
|
||||
@depsrb = root / "config" / "dependencies.rb"
|
||||
else
|
||||
self.class.error "dependencies.rb was not found"
|
||||
exit!
|
||||
end
|
||||
|
||||
FileUtils.mkdir_p(Dir.pwd / "gems")
|
||||
|
||||
@list = Collector.collect(File.read(@depsrb))
|
||||
@idx = ::Gem::SourceIndex.new.load_gems_in("gems/specifications")
|
||||
end
|
||||
|
||||
def list
|
||||
require "pp"
|
||||
pp @list
|
||||
end
|
||||
|
||||
desc "redeploy", "Syncs up gems/cache with gems/gems. All gems in the cache " \
|
||||
"that are not already installed will be installed from the " \
|
||||
"cache. All installed gems that are not in the cache will " \
|
||||
"be uninstalled."
|
||||
def redeploy
|
||||
gem_dir = Dir.pwd / "gems" / "gems"
|
||||
cache_dir = Dir.pwd / "gems" / "cache"
|
||||
|
||||
gems = Dir[gem_dir / "*"].map! {|n| File.basename(n)}
|
||||
cache = Dir[cache_dir / "*.gem"].map! {|n| File.basename(n, ".gem")}
|
||||
new_gems = cache - gems
|
||||
outdated = gems - cache
|
||||
idx = ::Gem::SourceIndex.new
|
||||
idx.load_gems_in(Dir.pwd / "gems" / "specifications")
|
||||
|
||||
new_gems.each do |g|
|
||||
installer = ::Gem::Installer.new(cache_dir / "#{g}.gem",
|
||||
:bin_dir => Dir.pwd / "bin",
|
||||
:install_dir => Dir.pwd / "gems",
|
||||
:ignore_dependencies => true,
|
||||
:user_install => false,
|
||||
:wrappers => true,
|
||||
:source_index => idx)
|
||||
|
||||
installer.install
|
||||
end
|
||||
|
||||
outdated.each do |g|
|
||||
/(.*)\-(.*)/ =~ g
|
||||
name, version = $1, $2
|
||||
uninstaller = ::Gem::Uninstaller.new(name,
|
||||
:version => version,
|
||||
:bin_dir => Dir.pwd / "bin",
|
||||
:install_dir => Dir.pwd / "gems",
|
||||
:ignore => true,
|
||||
:executables => true
|
||||
)
|
||||
uninstaller.uninstall
|
||||
end
|
||||
end
|
||||
|
||||
desc "confirm", "Confirm the current setup. merb:gem:install will " \
|
||||
"automatically run this task before committing the " \
|
||||
"changes it makes."
|
||||
def confirm(gems = @list)
|
||||
::Gem.path.replace([Dir.pwd / "gems"])
|
||||
::Gem.source_index.load_gems_in(Dir.pwd / "gems" / "specifications")
|
||||
|
||||
self.class.info "Confirming configuration..."
|
||||
|
||||
::Gem.loaded_specs.clear
|
||||
|
||||
begin
|
||||
gems.each do |name, versions|
|
||||
versions ||= []
|
||||
::Gem.activate name, *versions
|
||||
end
|
||||
rescue ::Gem::LoadError => e
|
||||
self.class.error "Configuration could not be confirmed: #{e.message}"
|
||||
self.class.rollback_trans
|
||||
end
|
||||
self.class.info "Confirmed"
|
||||
end
|
||||
|
||||
desc 'install', 'Sync up your bundled gems with the list in config/dependencies.rb'
|
||||
def install(*gems)
|
||||
if gems.empty?
|
||||
gems = @list
|
||||
else
|
||||
gems = gems.map {|desc| name, *versions = desc.split(" ") }
|
||||
end
|
||||
|
||||
$GEMS = gems
|
||||
|
||||
self.class.begin_trans
|
||||
|
||||
gems.each do |name, versions|
|
||||
dep = ::Gem::Dependency.new(name, versions || [])
|
||||
unless @idx.search(dep).empty?
|
||||
next
|
||||
end
|
||||
|
||||
rescue_failures do
|
||||
$INSTALLING = dep
|
||||
_install(dep)
|
||||
end
|
||||
end
|
||||
|
||||
gem_dir = Dir.pwd / "gems" / "gems"
|
||||
installed_gems = Dir[gem_dir / "*"].map! {|n| File.basename(n)}
|
||||
|
||||
list = full_list.map {|x| x.full_name}.compact
|
||||
|
||||
(installed_gems - list).each do |g|
|
||||
/^(.*)\-(.*)$/ =~ g
|
||||
name, version = $1, $2
|
||||
uninstaller = ::Gem::Uninstaller.new(name,
|
||||
:version => version,
|
||||
:bin_dir => (Dir.pwd / "bin").to_s,
|
||||
:install_dir => (Dir.pwd / "gems").to_s,
|
||||
:ignore => true,
|
||||
:executables => true
|
||||
)
|
||||
uninstaller.uninstall
|
||||
end
|
||||
|
||||
confirm(gems)
|
||||
|
||||
self.class.commit_trans
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,93 +0,0 @@
|
|||
module Thor::Tasks
|
||||
module Merb
|
||||
class Collector
|
||||
attr_reader :dependencies
|
||||
|
||||
def self.collect(str)
|
||||
collector = new
|
||||
collector.instance_eval(str)
|
||||
collector.dependencies
|
||||
end
|
||||
|
||||
def initialize
|
||||
@dependencies = []
|
||||
end
|
||||
|
||||
def dependency(name, *versions)
|
||||
versions.pop if versions.last.is_a?(Hash)
|
||||
@dependencies << [name, versions]
|
||||
end
|
||||
end
|
||||
|
||||
class Gem < Thor
|
||||
def full_list
|
||||
@idx.load_gems_in("gems/specifications")
|
||||
|
||||
@list.map do |name, versions|
|
||||
dep = ::Gem::Dependency.new(name, versions)
|
||||
spec = @idx.search(dep).last
|
||||
unless spec
|
||||
self.class.error "A required dependency #{dep} was not found"
|
||||
self.class.rollback_trans
|
||||
end
|
||||
deps = spec.recursive_dependencies(dep, @idx)
|
||||
[spec] + deps
|
||||
end.flatten.uniq
|
||||
end
|
||||
|
||||
def rescue_failures(error = StandardError, prc = nil)
|
||||
begin
|
||||
yield
|
||||
rescue error => e
|
||||
if prc
|
||||
prc.call(e)
|
||||
else
|
||||
puts e.message
|
||||
puts e.backtrace
|
||||
end
|
||||
self.class.rollback_trans
|
||||
end
|
||||
end
|
||||
|
||||
def self.begin_trans
|
||||
note "Beginning transaction"
|
||||
FileUtils.cp_r(Dir.pwd / "gems", Dir.pwd / ".original_gems")
|
||||
end
|
||||
|
||||
def self.commit_trans
|
||||
note "Committing transaction"
|
||||
FileUtils.rm_rf(Dir.pwd / ".original_gems")
|
||||
end
|
||||
|
||||
def self.rollback_trans
|
||||
if File.exist?(Dir.pwd / ".original_gems")
|
||||
note "Rolling back transaction"
|
||||
FileUtils.rm_rf(Dir.pwd / "gems")
|
||||
FileUtils.mv(Dir.pwd / ".original_gems", Dir.pwd / "gems")
|
||||
end
|
||||
exit!
|
||||
end
|
||||
|
||||
private
|
||||
def _install(dep)
|
||||
@idx.load_gems_in("gems/specifications")
|
||||
return if @idx.search(dep).last
|
||||
|
||||
installer = ::Gem::DependencyInstaller.new(
|
||||
:bin_dir => Dir.pwd / "bin",
|
||||
:install_dir => Dir.pwd / "gems",
|
||||
:user_install => false)
|
||||
|
||||
begin
|
||||
installer.install dep.name, dep.version_requirements
|
||||
rescue ::Gem::GemNotFoundException => e
|
||||
puts "Cannot find #{dep}"
|
||||
rescue ::Gem::RemoteFetcher::FetchError => e
|
||||
puts e.message
|
||||
puts "Retrying..."
|
||||
retry
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,40 +0,0 @@
|
|||
class String
|
||||
def /(other)
|
||||
(Pathname.new(self) + other).to_s
|
||||
end
|
||||
end
|
||||
|
||||
module ColorfulMessages
|
||||
|
||||
# red
|
||||
def error(*messages)
|
||||
puts messages.map { |msg| "\033[1;31m#{msg}\033[0m" }
|
||||
end
|
||||
|
||||
# yellow
|
||||
def warning(*messages)
|
||||
puts messages.map { |msg| "\033[1;33m#{msg}\033[0m" }
|
||||
end
|
||||
|
||||
# green
|
||||
def success(*messages)
|
||||
puts messages.map { |msg| "\033[1;32m#{msg}\033[0m" }
|
||||
end
|
||||
|
||||
alias_method :message, :success
|
||||
|
||||
# magenta
|
||||
def note(*messages)
|
||||
puts messages.map { |msg| "\033[1;35m#{msg}\033[0m" }
|
||||
end
|
||||
|
||||
# blue
|
||||
def info(*messages)
|
||||
puts messages.map { |msg| "\033[1;34m#{msg}\033[0m" }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module ThorUI
|
||||
extend ColorfulMessages
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue