pghero 2.3.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pghero might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +1 -0
- data/app/assets/javascripts/pghero/Chart.bundle.js +16260 -15580
- data/app/assets/javascripts/pghero/application.js +7 -6
- data/app/assets/javascripts/pghero/chartkick.js +1973 -1325
- data/app/assets/javascripts/pghero/highlight.pack.js +2 -2
- data/app/assets/javascripts/pghero/jquery.js +3605 -4015
- data/app/assets/javascripts/pghero/nouislider.js +2479 -0
- data/app/assets/stylesheets/pghero/application.css +1 -1
- data/app/assets/stylesheets/pghero/nouislider.css +299 -0
- data/app/controllers/pg_hero/home_controller.rb +16 -17
- data/app/views/pg_hero/home/_live_queries_table.html.erb +11 -1
- data/app/views/pg_hero/home/index.html.erb +47 -8
- data/app/views/pg_hero/home/live_queries.html.erb +1 -1
- data/app/views/pg_hero/home/relation_space.html.erb +2 -2
- data/app/views/pg_hero/home/show_query.html.erb +3 -3
- data/app/views/pg_hero/home/space.html.erb +2 -2
- data/app/views/pg_hero/home/system.html.erb +4 -4
- data/lib/generators/pghero/templates/config.yml.tt +14 -1
- data/lib/pghero.rb +39 -7
- data/lib/pghero/database.rb +29 -4
- data/lib/pghero/methods/constraints.rb +30 -0
- data/lib/pghero/methods/indexes.rb +1 -1
- data/lib/pghero/methods/system.rb +0 -16
- data/lib/pghero/stats.rb +1 -1
- data/lib/pghero/version.rb +1 -1
- metadata +5 -4
- data/app/assets/javascripts/pghero/jquery.nouislider.min.js +0 -31
- data/app/assets/stylesheets/pghero/jquery.nouislider.css +0 -165
@@ -6,9 +6,9 @@
|
|
6
6
|
<% end %>
|
7
7
|
</h1>
|
8
8
|
|
9
|
-
<h1>Size
|
9
|
+
<h1>Size</h1>
|
10
10
|
<div id="chart-1" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
11
11
|
<script>
|
12
|
-
new Chartkick.LineChart("chart-1", <%= json_escape(@chart_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false, min: null})
|
12
|
+
new Chartkick.LineChart("chart-1", <%= json_escape(@chart_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false, min: null, bytes: true, library: {tooltips: {intersect: false, mode: "index"}}})
|
13
13
|
</script>
|
14
14
|
</div>
|
@@ -49,19 +49,19 @@
|
|
49
49
|
<h1>Total Time <small>ms</small></h1>
|
50
50
|
<div id="chart-1" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
51
51
|
<script>
|
52
|
-
new Chartkick.LineChart("chart-1", <%= json_escape(@chart_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false})
|
52
|
+
new Chartkick.LineChart("chart-1", <%= json_escape(@chart_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false, library: {tooltips: {intersect: false, mode: "index"}}})
|
53
53
|
</script>
|
54
54
|
|
55
55
|
<h1>Average Time <small>ms</small></h1>
|
56
56
|
<div id="chart-2" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
57
57
|
<script>
|
58
|
-
new Chartkick.LineChart("chart-2", <%= json_escape(@chart2_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false})
|
58
|
+
new Chartkick.LineChart("chart-2", <%= json_escape(@chart2_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false, library: {tooltips: {intersect: false, mode: "index"}}})
|
59
59
|
</script>
|
60
60
|
|
61
61
|
<h1>Calls</h1>
|
62
62
|
<div id="chart-3" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
63
63
|
<script>
|
64
|
-
new Chartkick.LineChart("chart-3", <%= json_escape(@chart3_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false})
|
64
|
+
new Chartkick.LineChart("chart-3", <%= json_escape(@chart3_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false, library: {tooltips: {intersect: false, mode: "index"}}})
|
65
65
|
</script>
|
66
66
|
<% else %>
|
67
67
|
<p>
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<% if @system_stats_enabled %>
|
7
7
|
<div id="chart-1" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
8
8
|
<script>
|
9
|
-
new Chartkick.LineChart("chart-1", <%= json_escape(free_space_stats_path.to_json).html_safe %>, {colors: ["#5bc0de"]})
|
9
|
+
new Chartkick.LineChart("chart-1", <%= json_escape(free_space_stats_path.to_json).html_safe %>, {colors: ["#5bc0de"], bytes: true, library: {tooltips: {intersect: false, mode: "index"}}})
|
10
10
|
</script>
|
11
11
|
<% end %>
|
12
12
|
|
@@ -30,7 +30,7 @@
|
|
30
30
|
</p>
|
31
31
|
|
32
32
|
<div id="migration" style="display: none;">
|
33
|
-
<pre>rails
|
33
|
+
<pre>rails generate migration remove_unused_indexes</pre>
|
34
34
|
<p>And paste</p>
|
35
35
|
<pre style="overflow: scroll; white-space: pre; word-break: normal;"><% @unused_indexes.sort_by { |q| [-q[:size_bytes], q[:index]] }.each do |query| %>
|
36
36
|
remove_index <%= query[:table].to_sym.inspect %>, name: <%= query[:index].to_s.inspect %><% end %></pre>
|
@@ -9,26 +9,26 @@
|
|
9
9
|
<h1>CPU</h1>
|
10
10
|
<div id="chart-1" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
11
11
|
<script>
|
12
|
-
new Chartkick.LineChart("chart-1", <%= json_escape(cpu_usage_path(path_options).to_json).html_safe %>, {max: 100, colors: ["#5bc0de"]})
|
12
|
+
new Chartkick.LineChart("chart-1", <%= json_escape(cpu_usage_path(path_options).to_json).html_safe %>, {max: 100, colors: ["#5bc0de"], suffix: "%", library: {tooltips: {intersect: false, mode: "index"}}})
|
13
13
|
</script>
|
14
14
|
|
15
15
|
<h1>Load</h1>
|
16
16
|
<div id="chart-2" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
17
17
|
<script>
|
18
|
-
new Chartkick.LineChart("chart-2", <%= json_escape(load_stats_path(path_options).to_json).html_safe %>, {colors: ["#5bc0de", "#d9534f"]})
|
18
|
+
new Chartkick.LineChart("chart-2", <%= json_escape(load_stats_path(path_options).to_json).html_safe %>, {colors: ["#5bc0de", "#d9534f"], library: {tooltips: {intersect: false, mode: "nearest"}}})
|
19
19
|
</script>
|
20
20
|
|
21
21
|
<h1>Connections</h1>
|
22
22
|
<div id="chart-3" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
23
23
|
<script>
|
24
|
-
new Chartkick.LineChart("chart-3", <%= json_escape(connection_stats_path(path_options).to_json).html_safe %>, {colors: ["#5bc0de"]})
|
24
|
+
new Chartkick.LineChart("chart-3", <%= json_escape(connection_stats_path(path_options).to_json).html_safe %>, {colors: ["#5bc0de"], library: {tooltips: {intersect: false, mode: "index"}}})
|
25
25
|
</script>
|
26
26
|
|
27
27
|
<% if @database.replica? %>
|
28
28
|
<h1>Replication Lag</h1>
|
29
29
|
<div id="chart-4" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
30
30
|
<script>
|
31
|
-
new Chartkick.LineChart("chart-4", <%= json_escape(replication_lag_stats_path(path_options).to_json).html_safe %>, {colors: ["#5bc0de"]})
|
31
|
+
new Chartkick.LineChart("chart-4", <%= json_escape(replication_lag_stats_path(path_options).to_json).html_safe %>, {colors: ["#5bc0de"], library: {tooltips: {intersect: false, mode: "index"}}})
|
32
32
|
</script>
|
33
33
|
<% end %>
|
34
34
|
</div>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
databases:
|
2
|
-
|
2
|
+
primary:
|
3
3
|
# Database URL (defaults to app database)
|
4
4
|
# url: <%%= ENV["DATABASE_URL"] %>
|
5
5
|
|
@@ -24,3 +24,16 @@ databases:
|
|
24
24
|
|
25
25
|
# Time zone (defaults to app time zone)
|
26
26
|
# time_zone: "Pacific Time (US & Canada)"
|
27
|
+
|
28
|
+
# Basic authentication
|
29
|
+
# username: admin
|
30
|
+
# password: secret
|
31
|
+
|
32
|
+
# Stats database URL (defaults to app database)
|
33
|
+
# stats_database_url: <%%= ENV["PGHERO_STATS_DATABASE_URL"] %>
|
34
|
+
|
35
|
+
# AWS configuration (defaults to app AWS config)
|
36
|
+
# also need aws_db_instance_identifier with each database
|
37
|
+
# aws_access_key_id: ...
|
38
|
+
# aws_secret_access_key: ...
|
39
|
+
# aws_region: us-east-1
|
data/lib/pghero.rb
CHANGED
@@ -5,6 +5,7 @@ require "forwardable"
|
|
5
5
|
# methods
|
6
6
|
require "pghero/methods/basic"
|
7
7
|
require "pghero/methods/connections"
|
8
|
+
require "pghero/methods/constraints"
|
8
9
|
require "pghero/methods/explain"
|
9
10
|
require "pghero/methods/indexes"
|
10
11
|
require "pghero/methods/kill"
|
@@ -53,7 +54,7 @@ module PgHero
|
|
53
54
|
:best_index, :blocked_queries, :connection_sources, :connection_states, :connection_stats,
|
54
55
|
:cpu_usage, :create_user, :database_size, :db_instance_identifier, :disable_query_stats, :drop_user,
|
55
56
|
:duplicate_indexes, :enable_query_stats, :explain, :historical_query_stats_enabled?, :index_caching,
|
56
|
-
:index_hit_rate, :index_usage, :indexes, :invalid_indexes, :kill, :kill_all, :kill_long_running_queries,
|
57
|
+
:index_hit_rate, :index_usage, :indexes, :invalid_constraints, :invalid_indexes, :kill, :kill_all, :kill_long_running_queries,
|
57
58
|
:last_stats_reset_time, :long_running_queries, :maintenance_info, :missing_indexes, :query_stats,
|
58
59
|
:query_stats_available?, :query_stats_enabled?, :query_stats_extension_enabled?, :query_stats_readable?,
|
59
60
|
:rds_stats, :read_iops_stats, :region, :relation_sizes, :replica?, :replication_lag, :replication_lag_stats,
|
@@ -70,6 +71,22 @@ module PgHero
|
|
70
71
|
@time_zone || Time.zone
|
71
72
|
end
|
72
73
|
|
74
|
+
# use method instead of attr_accessor to ensure
|
75
|
+
# this works if variable set after PgHero is loaded
|
76
|
+
def username
|
77
|
+
@username ||= config["username"] || ENV["PGHERO_USERNAME"]
|
78
|
+
end
|
79
|
+
|
80
|
+
# use method instead of attr_accessor to ensure
|
81
|
+
# this works if variable set after PgHero is loaded
|
82
|
+
def password
|
83
|
+
@password ||= config["password"] || ENV["PGHERO_PASSWORD"]
|
84
|
+
end
|
85
|
+
|
86
|
+
def stats_database_url
|
87
|
+
@stats_database_url ||= config["stats_database_url"] || ENV["PGHERO_STATS_DATABASE_URL"]
|
88
|
+
end
|
89
|
+
|
73
90
|
def config
|
74
91
|
@config ||= begin
|
75
92
|
require "erb"
|
@@ -89,13 +106,23 @@ module PgHero
|
|
89
106
|
elsif config_file_exists
|
90
107
|
raise "Invalid config file"
|
91
108
|
else
|
92
|
-
{
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
109
|
+
databases = {}
|
110
|
+
|
111
|
+
if !ENV["PGHERO_DATABASE_URL"] && spec_supported?
|
112
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env, include_replicas: true).each do |db|
|
113
|
+
databases[db.spec_name] = {"spec" => db.spec_name}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
if databases.empty?
|
118
|
+
databases["primary"] = {
|
119
|
+
"url" => ENV["PGHERO_DATABASE_URL"] || ActiveRecord::Base.connection_config,
|
120
|
+
"db_instance_identifier" => ENV["PGHERO_DB_INSTANCE_IDENTIFIER"]
|
98
121
|
}
|
122
|
+
end
|
123
|
+
|
124
|
+
{
|
125
|
+
"databases" => databases
|
99
126
|
}
|
100
127
|
end
|
101
128
|
end
|
@@ -163,6 +190,11 @@ module PgHero
|
|
163
190
|
end
|
164
191
|
end
|
165
192
|
|
193
|
+
# private
|
194
|
+
def spec_supported?
|
195
|
+
ActiveRecord::VERSION::MAJOR >= 6
|
196
|
+
end
|
197
|
+
|
166
198
|
private
|
167
199
|
|
168
200
|
def each_database
|
data/lib/pghero/database.rb
CHANGED
@@ -2,6 +2,7 @@ module PgHero
|
|
2
2
|
class Database
|
3
3
|
include Methods::Basic
|
4
4
|
include Methods::Connections
|
5
|
+
include Methods::Constraints
|
5
6
|
include Methods::Explain
|
6
7
|
include Methods::Indexes
|
7
8
|
include Methods::Kill
|
@@ -28,10 +29,6 @@ module PgHero
|
|
28
29
|
@name ||= @config["name"] || id.titleize
|
29
30
|
end
|
30
31
|
|
31
|
-
def db_instance_identifier
|
32
|
-
@db_instance_identifier ||= @config["db_instance_identifier"]
|
33
|
-
end
|
34
|
-
|
35
32
|
def capture_query_stats?
|
36
33
|
config["capture_query_stats"] != false
|
37
34
|
end
|
@@ -64,11 +61,39 @@ module PgHero
|
|
64
61
|
(config["index_bloat_bytes"] || PgHero.config["index_bloat_bytes"] || 100.megabytes).to_i
|
65
62
|
end
|
66
63
|
|
64
|
+
def aws_access_key_id
|
65
|
+
config["aws_access_key_id"] || PgHero.config["aws_access_key_id"] || ENV["PGHERO_ACCESS_KEY_ID"] || ENV["AWS_ACCESS_KEY_ID"]
|
66
|
+
end
|
67
|
+
|
68
|
+
def aws_secret_access_key
|
69
|
+
config["aws_secret_access_key"] || PgHero.config["aws_secret_access_key"] || ENV["PGHERO_SECRET_ACCESS_KEY"] || ENV["AWS_SECRET_ACCESS_KEY"]
|
70
|
+
end
|
71
|
+
|
72
|
+
def aws_region
|
73
|
+
config["aws_region"] || PgHero.config["aws_region"] || ENV["PGHERO_REGION"] || ENV["AWS_REGION"] || (defined?(Aws) && Aws.config[:region]) || "us-east-1"
|
74
|
+
end
|
75
|
+
|
76
|
+
def aws_db_instance_identifier
|
77
|
+
@db_instance_identifier ||= config["aws_db_instance_identifier"] || config["db_instance_identifier"]
|
78
|
+
end
|
79
|
+
|
80
|
+
# TODO remove in next major version
|
81
|
+
alias_method :access_key_id, :aws_access_key_id
|
82
|
+
alias_method :secret_access_key, :aws_secret_access_key
|
83
|
+
alias_method :region, :aws_region
|
84
|
+
alias_method :db_instance_identifier, :aws_db_instance_identifier
|
85
|
+
|
67
86
|
private
|
68
87
|
|
69
88
|
def connection_model
|
70
89
|
@connection_model ||= begin
|
71
90
|
url = config["url"]
|
91
|
+
if !url && config["spec"]
|
92
|
+
raise Error, "Spec requires Rails 6+" unless PgHero.spec_supported?
|
93
|
+
resolved = ActiveRecord::Base.configurations.configs_for(env_name: PgHero.env, spec_name: config["spec"], include_replicas: true)
|
94
|
+
raise Error, "Spec not found: #{config["spec"]}" unless resolved
|
95
|
+
url = resolved.config
|
96
|
+
end
|
72
97
|
Class.new(PgHero::Connection) do
|
73
98
|
def self.name
|
74
99
|
"PgHero::Connection::Database#{object_id}"
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module PgHero
|
2
|
+
module Methods
|
3
|
+
module Constraints
|
4
|
+
# referenced fields can be nil
|
5
|
+
# as not all constraints are foreign keys
|
6
|
+
def invalid_constraints
|
7
|
+
select_all <<-SQL
|
8
|
+
SELECT
|
9
|
+
nsp.nspname AS schema,
|
10
|
+
rel.relname AS table,
|
11
|
+
con.conname AS name,
|
12
|
+
fnsp.nspname AS referenced_schema,
|
13
|
+
frel.relname AS referenced_table
|
14
|
+
FROM
|
15
|
+
pg_catalog.pg_constraint con
|
16
|
+
INNER JOIN
|
17
|
+
pg_catalog.pg_class rel ON rel.oid = con.conrelid
|
18
|
+
LEFT JOIN
|
19
|
+
pg_catalog.pg_class frel ON frel.oid = con.confrelid
|
20
|
+
LEFT JOIN
|
21
|
+
pg_catalog.pg_namespace nsp ON nsp.oid = con.connamespace
|
22
|
+
LEFT JOIN
|
23
|
+
pg_catalog.pg_namespace fnsp ON fnsp.oid = frel.relnamespace
|
24
|
+
WHERE
|
25
|
+
con.convalidated = 'f'
|
26
|
+
SQL
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -70,22 +70,6 @@ module PgHero
|
|
70
70
|
def system_stats_enabled?
|
71
71
|
!!((defined?(Aws) || defined?(AWS)) && db_instance_identifier)
|
72
72
|
end
|
73
|
-
|
74
|
-
def access_key_id
|
75
|
-
ENV["PGHERO_ACCESS_KEY_ID"] || ENV["AWS_ACCESS_KEY_ID"]
|
76
|
-
end
|
77
|
-
|
78
|
-
def secret_access_key
|
79
|
-
ENV["PGHERO_SECRET_ACCESS_KEY"] || ENV["AWS_SECRET_ACCESS_KEY"]
|
80
|
-
end
|
81
|
-
|
82
|
-
def region
|
83
|
-
ENV["PGHERO_REGION"] || ENV["AWS_REGION"] || (defined?(Aws) && Aws.config[:region]) || "us-east-1"
|
84
|
-
end
|
85
|
-
|
86
|
-
def db_instance_identifier
|
87
|
-
databases[current_database].db_instance_identifier
|
88
|
-
end
|
89
73
|
end
|
90
74
|
end
|
91
75
|
end
|
data/lib/pghero/stats.rb
CHANGED
data/lib/pghero/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pghero
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -124,10 +124,10 @@ files:
|
|
124
124
|
- app/assets/javascripts/pghero/chartkick.js
|
125
125
|
- app/assets/javascripts/pghero/highlight.pack.js
|
126
126
|
- app/assets/javascripts/pghero/jquery.js
|
127
|
-
- app/assets/javascripts/pghero/
|
127
|
+
- app/assets/javascripts/pghero/nouislider.js
|
128
128
|
- app/assets/stylesheets/pghero/application.css
|
129
129
|
- app/assets/stylesheets/pghero/arduino-light.css
|
130
|
-
- app/assets/stylesheets/pghero/
|
130
|
+
- app/assets/stylesheets/pghero/nouislider.css
|
131
131
|
- app/controllers/pg_hero/home_controller.rb
|
132
132
|
- app/helpers/pg_hero/home_helper.rb
|
133
133
|
- app/views/layouts/pg_hero/application.html.erb
|
@@ -161,6 +161,7 @@ files:
|
|
161
161
|
- lib/pghero/engine.rb
|
162
162
|
- lib/pghero/methods/basic.rb
|
163
163
|
- lib/pghero/methods/connections.rb
|
164
|
+
- lib/pghero/methods/constraints.rb
|
164
165
|
- lib/pghero/methods/explain.rb
|
165
166
|
- lib/pghero/methods/indexes.rb
|
166
167
|
- lib/pghero/methods/kill.rb
|
@@ -1,31 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
|
3
|
-
$.Link (part of noUiSlider) - WTFPL */
|
4
|
-
(function(c){function m(a,c,d){if((a[c]||a[d])&&a[c]===a[d])throw Error("(Link) '"+c+"' can't match '"+d+"'.'");}function r(a){void 0===a&&(a={});if("object"!==typeof a)throw Error("(Format) 'format' option must be an object.");var h={};c(u).each(function(c,n){if(void 0===a[n])h[n]=A[c];else if(typeof a[n]===typeof A[c]){if("decimals"===n&&(0>a[n]||7<a[n]))throw Error("(Format) 'format.decimals' option must be between 0 and 7.");h[n]=a[n]}else throw Error("(Format) 'format."+n+"' must be a "+typeof A[c]+
|
5
|
-
".");});m(h,"mark","thousand");m(h,"prefix","negative");m(h,"prefix","negativeBefore");this.r=h}function k(a,h){"object"!==typeof a&&c.error("(Link) Initialize with an object.");return new k.prototype.p(a.target||function(){},a.method,a.format||{},h)}var u="decimals mark thousand prefix postfix encoder decoder negative negativeBefore to from".split(" "),A=[2,".","","","",function(a){return a},function(a){return a},"-","",function(a){return a},function(a){return a}];r.prototype.a=function(a){return this.r[a]};
|
6
|
-
r.prototype.L=function(a){function c(a){return a.split("").reverse().join("")}a=this.a("encoder")(a);var d=this.a("decimals"),n="",k="",m="",r="";0===parseFloat(a.toFixed(d))&&(a="0");0>a&&(n=this.a("negative"),k=this.a("negativeBefore"));a=Math.abs(a).toFixed(d).toString();a=a.split(".");this.a("thousand")?(m=c(a[0]).match(/.{1,3}/g),m=c(m.join(c(this.a("thousand"))))):m=a[0];this.a("mark")&&1<a.length&&(r=this.a("mark")+a[1]);return this.a("to")(k+this.a("prefix")+n+m+r+this.a("postfix"))};r.prototype.w=
|
7
|
-
function(a){function c(a){return a.replace(/[\-\/\\\^$*+?.()|\[\]{}]/g,"\\$&")}var d;if(null===a||void 0===a)return!1;a=this.a("from")(a);a=a.toString();d=a.replace(RegExp("^"+c(this.a("negativeBefore"))),"");a!==d?(a=d,d="-"):d="";a=a.replace(RegExp("^"+c(this.a("prefix"))),"");this.a("negative")&&(d="",a=a.replace(RegExp("^"+c(this.a("negative"))),"-"));a=a.replace(RegExp(c(this.a("postfix"))+"$"),"").replace(RegExp(c(this.a("thousand")),"g"),"").replace(this.a("mark"),".");a=this.a("decoder")(parseFloat(d+
|
8
|
-
a));return isNaN(a)?!1:a};k.prototype.K=function(a,h){this.method=h||"html";this.j=c(a.replace("-tooltip-","")||"<div/>")[0]};k.prototype.H=function(a){this.method="val";this.j=document.createElement("input");this.j.name=a;this.j.type="hidden"};k.prototype.G=function(a){function h(a,c){return[c?null:a,c?a:null]}var d=this;this.method="val";this.target=a.on("change",function(a){d.B.val(h(c(a.target).val(),d.t),{link:d,set:!0})})};k.prototype.p=function(a,h,d,k){this.g=d;this.update=!k;if("string"===
|
9
|
-
typeof a&&0===a.indexOf("-tooltip-"))this.K(a,h);else if("string"===typeof a&&0!==a.indexOf("-"))this.H(a);else if("function"===typeof a)this.target=!1,this.method=a;else{if(a instanceof c||c.zepto&&c.zepto.isZ(a)){if(!h){if(a.is("input, select, textarea")){this.G(a);return}h="html"}if("function"===typeof h||"string"===typeof h&&a[h]){this.method=h;this.target=a;return}}throw new RangeError("(Link) Invalid Link.");}};k.prototype.write=function(a,c,d,k){if(!this.update||!1!==k)if(this.u=a,this.F=a=
|
10
|
-
this.format(a),"function"===typeof this.method)this.method.call(this.target[0]||d[0],a,c,d);else this.target[this.method](a,c,d)};k.prototype.q=function(a){this.g=new r(c.extend({},a,this.g instanceof r?this.g.r:this.g))};k.prototype.J=function(a){this.B=a};k.prototype.I=function(a){this.t=a};k.prototype.format=function(a){return this.g.L(a)};k.prototype.A=function(a){return this.g.w(a)};k.prototype.p.prototype=k.prototype;c.Link=k})(window.jQuery||window.Zepto);/*
|
11
|
-
|
12
|
-
$.fn.noUiSlider - WTFPL - refreshless.com/nouislider/ */
|
13
|
-
(function(c){function m(e){return"number"===typeof e&&!isNaN(e)&&isFinite(e)}function r(e){return c.isArray(e)?e:[e]}function k(e,b){e.addClass(b);setTimeout(function(){e.removeClass(b)},300)}function u(e,b){return 100*b/(e[1]-e[0])}function A(e,b){if(b>=e.d.slice(-1)[0])return 100;for(var a=1,c,f,d;b>=e.d[a];)a++;c=e.d[a-1];f=e.d[a];d=e.c[a-1];c=[c,f];return d+u(c,0>c[0]?b+Math.abs(c[0]):b-c[0])/(100/(e.c[a]-d))}function a(e,b){if(100<=b)return e.d.slice(-1)[0];for(var a=1,c,f,d;b>=e.c[a];)a++;c=
|
14
|
-
e.d[a-1];f=e.d[a];d=e.c[a-1];c=[c,f];return 100/(e.c[a]-d)*(b-d)*(c[1]-c[0])/100+c[0]}function h(a,b){for(var c=1,g;(a.dir?100-b:b)>=a.c[c];)c++;if(a.m)return g=a.c[c-1],c=a.c[c],b-g>(c-g)/2?c:g;a.h[c-1]?(g=a.h[c-1],c=a.c[c-1]+Math.round((b-a.c[c-1])/g)*g):c=b;return c}function d(a,b){if(!m(b))throw Error("noUiSlider: 'step' is not numeric.");a.h[0]=b}function n(a,b){if("object"!==typeof b||c.isArray(b))throw Error("noUiSlider: 'range' is not an object.");if(void 0===b.min||void 0===b.max)throw Error("noUiSlider: Missing 'min' or 'max' in 'range'.");
|
15
|
-
c.each(b,function(b,g){var d;"number"===typeof g&&(g=[g]);if(!c.isArray(g))throw Error("noUiSlider: 'range' contains invalid value.");d="min"===b?0:"max"===b?100:parseFloat(b);if(!m(d)||!m(g[0]))throw Error("noUiSlider: 'range' value isn't numeric.");a.c.push(d);a.d.push(g[0]);d?a.h.push(isNaN(g[1])?!1:g[1]):isNaN(g[1])||(a.h[0]=g[1])});c.each(a.h,function(b,c){if(!c)return!0;a.h[b]=u([a.d[b],a.d[b+1]],c)/(100/(a.c[b+1]-a.c[b]))})}function E(a,b){"number"===typeof b&&(b=[b]);if(!c.isArray(b)||!b.length||
|
16
|
-
2<b.length)throw Error("noUiSlider: 'start' option is incorrect.");a.b=b.length;a.start=b}function I(a,b){a.m=b;if("boolean"!==typeof b)throw Error("noUiSlider: 'snap' option must be a boolean.");}function J(a,b){if("lower"===b&&1===a.b)a.i=1;else if("upper"===b&&1===a.b)a.i=2;else if(!0===b&&2===a.b)a.i=3;else if(!1===b)a.i=0;else throw Error("noUiSlider: 'connect' option doesn't match handle count.");}function D(a,b){switch(b){case "horizontal":a.k=0;break;case "vertical":a.k=1;break;default:throw Error("noUiSlider: 'orientation' option is invalid.");
|
17
|
-
}}function K(a,b){if(2<a.c.length)throw Error("noUiSlider: 'margin' option is only supported on linear sliders.");a.margin=u(a.d,b);if(!m(b))throw Error("noUiSlider: 'margin' option must be numeric.");}function L(a,b){switch(b){case "ltr":a.dir=0;break;case "rtl":a.dir=1;a.i=[0,2,1,3][a.i];break;default:throw Error("noUiSlider: 'direction' option was not recognized.");}}function M(a,b){if("string"!==typeof b)throw Error("noUiSlider: 'behaviour' must be a string containing options.");var c=0<=b.indexOf("snap");
|
18
|
-
a.n={s:0<=b.indexOf("tap")||c,extend:0<=b.indexOf("extend"),v:0<=b.indexOf("drag"),fixed:0<=b.indexOf("fixed"),m:c}}function N(a,b,d){a.o=[b.lower,b.upper];a.g=b.format;c.each(a.o,function(a,e){if(!c.isArray(e))throw Error("noUiSlider: 'serialization."+(a?"upper":"lower")+"' must be an array.");c.each(e,function(){if(!(this instanceof c.Link))throw Error("noUiSlider: 'serialization."+(a?"upper":"lower")+"' can only contain Link instances.");this.I(a);this.J(d);this.q(b.format)})});a.dir&&1<a.b&&a.o.reverse()}
|
19
|
-
function O(a,b){var f={c:[],d:[],h:[!1],margin:0},g;g={step:{e:!1,f:d},start:{e:!0,f:E},connect:{e:!0,f:J},direction:{e:!0,f:L},range:{e:!0,f:n},snap:{e:!1,f:I},orientation:{e:!1,f:D},margin:{e:!1,f:K},behaviour:{e:!0,f:M},serialization:{e:!0,f:N}};a=c.extend({connect:!1,direction:"ltr",behaviour:"tap",orientation:"horizontal"},a);a.serialization=c.extend({lower:[],upper:[],format:{}},a.serialization);c.each(g,function(c,d){if(void 0===a[c]){if(d.e)throw Error("noUiSlider: '"+c+"' is required.");
|
20
|
-
return!0}d.f(f,a[c],b)});f.style=f.k?"top":"left";return f}function P(a,b){var d=c("<div><div/></div>").addClass(f[2]),g=["-lower","-upper"];a.dir&&g.reverse();d.children().addClass(f[3]+" "+f[3]+g[b]);return d}function Q(a,b){b.j&&(b=new c.Link({target:c(b.j).clone().appendTo(a),method:b.method,format:b.g},!0));return b}function R(a,b){var d,f=[];for(d=0;d<a.b;d++){var k=f,h=d,m=a.o[d],n=b[d].children(),r=a.g,s=void 0,v=[],s=new c.Link({},!0);s.q(r);v.push(s);for(s=0;s<m.length;s++)v.push(Q(n,m[s]));
|
21
|
-
k[h]=v}return f}function S(a,b,c){switch(a){case 1:b.addClass(f[7]);c[0].addClass(f[6]);break;case 3:c[1].addClass(f[6]);case 2:c[0].addClass(f[7]);case 0:b.addClass(f[6])}}function T(a,b){var c,d=[];for(c=0;c<a.b;c++)d.push(P(a,c).appendTo(b));return d}function U(a,b){b.addClass([f[0],f[8+a.dir],f[4+a.k]].join(" "));return c("<div/>").appendTo(b).addClass(f[1])}function V(d,b,m){function g(){return t[["width","height"][b.k]]()}function n(a){var b,c=[q.val()];for(b=0;b<a.length;b++)q.trigger(a[b],
|
22
|
-
c)}function u(d,p,e){var g=d[0]!==l[0][0]?1:0,H=x[0]+b.margin,k=x[1]-b.margin;e&&1<l.length&&(p=g?Math.max(p,H):Math.min(p,k));100>p&&(p=h(b,p));p=Math.max(Math.min(parseFloat(p.toFixed(7)),100),0);if(p===x[g])return 1===l.length?!1:p===H||p===k?0:!1;d.css(b.style,p+"%");d.is(":first-child")&&d.toggleClass(f[17],50<p);x[g]=p;b.dir&&(p=100-p);c(y[g]).each(function(){this.write(a(b,p),d.children(),q)});return!0}function B(a,b,c){c||k(q,f[14]);u(a,b,!1);n(["slide","set","change"])}function w(a,c,d,e){a=
|
23
|
-
a.replace(/\s/g,".nui ")+".nui";c.on(a,function(a){var c=q.attr("disabled");if(q.hasClass(f[14])||void 0!==c&&null!==c)return!1;a.preventDefault();var c=0===a.type.indexOf("touch"),p=0===a.type.indexOf("mouse"),F=0===a.type.indexOf("pointer"),g,k,l=a;0===a.type.indexOf("MSPointer")&&(F=!0);a.originalEvent&&(a=a.originalEvent);c&&(g=a.changedTouches[0].pageX,k=a.changedTouches[0].pageY);if(p||F)F||void 0!==window.pageXOffset||(window.pageXOffset=document.documentElement.scrollLeft,window.pageYOffset=
|
24
|
-
document.documentElement.scrollTop),g=a.clientX+window.pageXOffset,k=a.clientY+window.pageYOffset;l.C=[g,k];l.cursor=p;a=l;a.l=a.C[b.k];d(a,e)})}function C(a,c){var b=c.b||l,d,e=!1,e=100*(a.l-c.start)/g(),f=b[0][0]!==l[0][0]?1:0;var k=c.D;d=e+k[0];e+=k[1];1<b.length?(0>d&&(e+=Math.abs(d)),100<e&&(d-=e-100),d=[Math.max(Math.min(d,100),0),Math.max(Math.min(e,100),0)]):d=[d,e];e=u(b[0],d[f],1===b.length);1<b.length&&(e=u(b[1],d[f?0:1],!1)||e);e&&n(["slide"])}function s(a){c("."+f[15]).removeClass(f[15]);
|
25
|
-
a.cursor&&c("body").css("cursor","").off(".nui");G.off(".nui");q.removeClass(f[12]);n(["set","change"])}function v(a,b){1===b.b.length&&b.b[0].children().addClass(f[15]);a.stopPropagation();w(z.move,G,C,{start:a.l,b:b.b,D:[x[0],x[l.length-1]]});w(z.end,G,s,null);a.cursor&&(c("body").css("cursor",c(a.target).css("cursor")),1<l.length&&q.addClass(f[12]),c("body").on("selectstart.nui",!1))}function D(a){var d=a.l,e=0;a.stopPropagation();c.each(l,function(){e+=this.offset()[b.style]});e=d<e/2||1===l.length?
|
26
|
-
0:1;d-=t.offset()[b.style];d=100*d/g();B(l[e],d,b.n.m);b.n.m&&v(a,{b:[l[e]]})}function E(a){var c=(a=a.l<t.offset()[b.style])?0:100;a=a?0:l.length-1;B(l[a],c,!1)}var q=c(d),x=[-1,-1],t,y,l;if(q.hasClass(f[0]))throw Error("Slider was already initialized.");t=U(b,q);l=T(b,t);y=R(b,l);S(b.i,q,l);(function(a){var b;if(!a.fixed)for(b=0;b<l.length;b++)w(z.start,l[b].children(),v,{b:[l[b]]});a.s&&w(z.start,t,D,{b:l});a.extend&&(q.addClass(f[16]),a.s&&w(z.start,q,E,{b:l}));a.v&&(b=t.find("."+f[7]).addClass(f[10]),
|
27
|
-
a.fixed&&(b=b.add(t.children().not(b).children())),w(z.start,b,v,{b:l}))})(b.n);d.vSet=function(){var a=Array.prototype.slice.call(arguments,0),d,e,g,h,m,s,t=r(a[0]);"object"===typeof a[1]?(d=a[1].set,e=a[1].link,g=a[1].update,h=a[1].animate):!0===a[1]&&(d=!0);b.dir&&1<b.b&&t.reverse();h&&k(q,f[14]);a=1<l.length?3:1;1===t.length&&(a=1);for(m=0;m<a;m++)h=e||y[m%2][0],h=h.A(t[m%2]),!1!==h&&(h=A(b,h),b.dir&&(h=100-h),!0!==u(l[m%2],h,!0)&&c(y[m%2]).each(function(a){if(!a)return s=this.u,!0;this.write(s,
|
28
|
-
l[m%2].children(),q,g)}));!0===d&&n(["set"]);return this};d.vGet=function(){var a,c=[];for(a=0;a<b.b;a++)c[a]=y[a][0].F;return 1===c.length?c[0]:b.dir?c.reverse():c};d.destroy=function(){c.each(y,function(){c.each(this,function(){this.target&&this.target.off(".nui")})});c(this).off(".nui").removeClass(f.join(" ")).empty();return m};q.val(b.start)}function W(a){if(!this.length)throw Error("noUiSlider: Can't initialize slider on empty selection.");var b=O(a,this);return this.each(function(){V(this,
|
29
|
-
b,a)})}function X(a){return this.each(function(){var b=c(this).val(),d=this.destroy(),f=c.extend({},d,a);c(this).noUiSlider(f);d.start===f.start&&c(this).val(b)})}function B(){return this[0][arguments.length?"vSet":"vGet"].apply(this[0],arguments)}var G=c(document),C=c.fn.val,z=window.navigator.pointerEnabled?{start:"pointerdown",move:"pointermove",end:"pointerup"}:window.navigator.msPointerEnabled?{start:"MSPointerDown",move:"MSPointerMove",end:"MSPointerUp"}:{start:"mousedown touchstart",move:"mousemove touchmove",
|
30
|
-
end:"mouseup touchend"},f="noUi-target noUi-base noUi-origin noUi-handle noUi-horizontal noUi-vertical noUi-background noUi-connect noUi-ltr noUi-rtl noUi-dragable noUi-state-drag noUi-state-tap noUi-active noUi-extended noUi-stacking".split(" ");c.fn.val=function(){var a=arguments,b=c(this[0]);return arguments.length?this.each(function(){(c(this).hasClass(f[0])?B:C).apply(c(this),a)}):(b.hasClass(f[0])?B:C).call(b)};c.noUiSlider={Link:c.Link};c.fn.noUiSlider=function(a,b){return(b?X:W).call(this,
|
31
|
-
a)}})(window.jQuery||window.Zepto);
|
@@ -1,165 +0,0 @@
|
|
1
|
-
|
2
|
-
/* Functional styling;
|
3
|
-
* These styles are required for noUiSlider to function.
|
4
|
-
* You don't need to change these rules to apply your design.
|
5
|
-
*/
|
6
|
-
.noUi-target,
|
7
|
-
.noUi-target * {
|
8
|
-
-webkit-touch-callout: none;
|
9
|
-
-webkit-user-select: none;
|
10
|
-
-ms-touch-action: none;
|
11
|
-
-ms-user-select: none;
|
12
|
-
-moz-user-select: none;
|
13
|
-
-moz-box-sizing: border-box;
|
14
|
-
box-sizing: border-box;
|
15
|
-
}
|
16
|
-
.noUi-base {
|
17
|
-
width: 100%;
|
18
|
-
height: 100%;
|
19
|
-
position: relative;
|
20
|
-
}
|
21
|
-
.noUi-origin {
|
22
|
-
position: absolute;
|
23
|
-
right: 0;
|
24
|
-
top: 0;
|
25
|
-
left: 0;
|
26
|
-
bottom: 0;
|
27
|
-
}
|
28
|
-
.noUi-handle {
|
29
|
-
position: relative;
|
30
|
-
z-index: 1;
|
31
|
-
}
|
32
|
-
.noUi-stacking .noUi-handle {
|
33
|
-
/* This class is applied to the lower origin when
|
34
|
-
its values is > 50%. */
|
35
|
-
z-index: 10;
|
36
|
-
}
|
37
|
-
.noUi-stacking + .noUi-origin {
|
38
|
-
/* Fix stacking order in IE7, which incorrectly
|
39
|
-
creates a new context for the origins. */
|
40
|
-
*z-index: -1;
|
41
|
-
}
|
42
|
-
.noUi-state-tap .noUi-origin {
|
43
|
-
-webkit-transition: left 0.3s, top 0.3s;
|
44
|
-
transition: left 0.3s, top 0.3s;
|
45
|
-
}
|
46
|
-
.noUi-state-drag * {
|
47
|
-
cursor: inherit !important;
|
48
|
-
}
|
49
|
-
|
50
|
-
/* Slider size and handle placement;
|
51
|
-
*/
|
52
|
-
.noUi-horizontal {
|
53
|
-
height: 18px;
|
54
|
-
}
|
55
|
-
.noUi-horizontal .noUi-handle {
|
56
|
-
width: 34px;
|
57
|
-
height: 28px;
|
58
|
-
left: -17px;
|
59
|
-
top: -6px;
|
60
|
-
}
|
61
|
-
.noUi-horizontal.noUi-extended {
|
62
|
-
padding: 0 15px;
|
63
|
-
}
|
64
|
-
.noUi-horizontal.noUi-extended .noUi-origin {
|
65
|
-
right: -15px;
|
66
|
-
}
|
67
|
-
.noUi-vertical {
|
68
|
-
width: 18px;
|
69
|
-
}
|
70
|
-
.noUi-vertical .noUi-handle {
|
71
|
-
width: 28px;
|
72
|
-
height: 34px;
|
73
|
-
left: -6px;
|
74
|
-
top: -17px;
|
75
|
-
}
|
76
|
-
.noUi-vertical.noUi-extended {
|
77
|
-
padding: 15px 0;
|
78
|
-
}
|
79
|
-
.noUi-vertical.noUi-extended .noUi-origin {
|
80
|
-
bottom: -15px;
|
81
|
-
}
|
82
|
-
|
83
|
-
/* Styling;
|
84
|
-
*/
|
85
|
-
.noUi-background {
|
86
|
-
background: #FAFAFA;
|
87
|
-
box-shadow: inset 0 1px 1px #f0f0f0;
|
88
|
-
}
|
89
|
-
.noUi-connect {
|
90
|
-
background: #3FB8AF;
|
91
|
-
box-shadow: inset 0 0 3px rgba(51,51,51,0.45);
|
92
|
-
-webkit-transition: background 450ms;
|
93
|
-
transition: background 450ms;
|
94
|
-
}
|
95
|
-
.noUi-origin {
|
96
|
-
border-radius: 2px;
|
97
|
-
}
|
98
|
-
.noUi-target {
|
99
|
-
border-radius: 4px;
|
100
|
-
border: 1px solid #D3D3D3;
|
101
|
-
box-shadow: inset 0 1px 1px #F0F0F0, 0 3px 6px -5px #BBB;
|
102
|
-
}
|
103
|
-
.noUi-target.noUi-connect {
|
104
|
-
box-shadow: inset 0 0 3px rgba(51,51,51,0.45), 0 3px 6px -5px #BBB;
|
105
|
-
}
|
106
|
-
|
107
|
-
/* Handles and cursors;
|
108
|
-
*/
|
109
|
-
.noUi-dragable {
|
110
|
-
cursor: w-resize;
|
111
|
-
}
|
112
|
-
.noUi-vertical .noUi-dragable {
|
113
|
-
cursor: n-resize;
|
114
|
-
}
|
115
|
-
.noUi-handle {
|
116
|
-
border: 1px solid #D9D9D9;
|
117
|
-
border-radius: 3px;
|
118
|
-
background: #FFF;
|
119
|
-
cursor: default;
|
120
|
-
box-shadow: inset 0 0 1px #FFF,
|
121
|
-
inset 0 1px 7px #EBEBEB,
|
122
|
-
0 3px 6px -3px #BBB;
|
123
|
-
}
|
124
|
-
.noUi-active {
|
125
|
-
box-shadow: inset 0 0 1px #FFF,
|
126
|
-
inset 0 1px 7px #DDD,
|
127
|
-
0 3px 6px -3px #BBB;
|
128
|
-
}
|
129
|
-
|
130
|
-
/* Handle stripes;
|
131
|
-
*/
|
132
|
-
.noUi-handle:before,
|
133
|
-
.noUi-handle:after {
|
134
|
-
content: "";
|
135
|
-
display: block;
|
136
|
-
position: absolute;
|
137
|
-
height: 14px;
|
138
|
-
width: 1px;
|
139
|
-
background: #E8E7E6;
|
140
|
-
left: 14px;
|
141
|
-
top: 6px;
|
142
|
-
}
|
143
|
-
.noUi-handle:after {
|
144
|
-
left: 17px;
|
145
|
-
}
|
146
|
-
.noUi-vertical .noUi-handle:before,
|
147
|
-
.noUi-vertical .noUi-handle:after {
|
148
|
-
width: 14px;
|
149
|
-
height: 1px;
|
150
|
-
left: 6px;
|
151
|
-
top: 14px;
|
152
|
-
}
|
153
|
-
.noUi-vertical .noUi-handle:after {
|
154
|
-
top: 17px;
|
155
|
-
}
|
156
|
-
|
157
|
-
/* Disabled state;
|
158
|
-
*/
|
159
|
-
[disabled].noUi-connect,
|
160
|
-
[disabled] .noUi-connect {
|
161
|
-
background: #B8B8B8;
|
162
|
-
}
|
163
|
-
[disabled] .noUi-handle {
|
164
|
-
cursor: not-allowed;
|
165
|
-
}
|