aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/genenetwork22
-rw-r--r--etc/default_settings.py2
-rw-r--r--wqflask/wqflask/heatmap/heatmap.py83
-rw-r--r--wqflask/wqflask/marker_regression/qtlreaper_mapping.py4
-rw-r--r--wqflask/wqflask/marker_regression/run_mapping.py5
-rw-r--r--wqflask/wqflask/static/new/javascript/dataset_menu_structure.json142
-rw-r--r--wqflask/wqflask/static/new/javascript/get_traits_from_collection.js74
-rw-r--r--wqflask/wqflask/static/new/javascript/network_graph.js17
-rw-r--r--wqflask/wqflask/static/new/packages/nvd3/nv.d3.css641
-rw-r--r--wqflask/wqflask/static/new/packages/nvd3/nv.d3.js13363
-rw-r--r--wqflask/wqflask/static/new/packages/nvd3/nv.d3.min.css1
-rw-r--r--wqflask/wqflask/static/new/packages/nvd3/nv.d3.min.js8
-rw-r--r--wqflask/wqflask/static/packages/DT_bootstrap/DT_bootstrap.css179
-rw-r--r--wqflask/wqflask/static/packages/DT_bootstrap/DT_bootstrap.js159
l---------wqflask/wqflask/static/packages/DT_bootstrap/images1
-rwxr-xr-xwqflask/wqflask/templates/index_page_orig.html2
-rw-r--r--wqflask/wqflask/templates/show_trait.html2
-rw-r--r--wqflask/wqflask/user_manager.py5
18 files changed, 203 insertions, 14487 deletions
diff --git a/bin/genenetwork2 b/bin/genenetwork2
index 7c875274..1c538e86 100755
--- a/bin/genenetwork2
+++ b/bin/genenetwork2
@@ -25,7 +25,7 @@
# webserver) run from the base-dir with settings file and add that
# script with a -c switch, e.g.
#
-# env GN2_PROFILE=/usr/local/guix-profiles/gn-latest-20181119 TMPDIR=/export/local/home/zas1024/gn2-zach/tmp WEBSERVER_MODE=DEBUG LOG_LEVEL=DEBUG SERVER_PORT=5002 GENENETWORK_FILES=/export/local/home/zas1024/gn2-zach/genotype_files SQL_URI=mysql://webqtlout:webqtlout@lily.uthsc.edu/db_webqtl ./bin/genenetwork2 ./etc/default_settings.py -c ./maintenance/gen_select_dataset.py
+# env GN2_PROFILE=/usr/local/guix-profiles/gn-latest-20190905 TMPDIR=/export/local/home/zas1024/gn2-zach/tmp WEBSERVER_MODE=DEBUG LOG_LEVEL=DEBUG SERVER_PORT=5002 GENENETWORK_FILES=/export/local/home/zas1024/gn2-zach/genotype_files SQL_URI=mysql://webqtlout:webqtlout@lily.uthsc.edu/db_webqtl ./bin/genenetwork2 ./etc/default_settings.py -c ./maintenance/gen_select_dataset.py
#
# To run any script in the environment
#
diff --git a/etc/default_settings.py b/etc/default_settings.py
index a16ac3ad..75f84dc4 100644
--- a/etc/default_settings.py
+++ b/etc/default_settings.py
@@ -91,5 +91,5 @@ JS_GN_PATH = os.environ['HOME']+"/genenetwork/javascript"
# ---- GN2 Executables (overwrite for testing only)
# PLINK_COMMAND = str.strip(os.popen("which plink2").read())
# GEMMA_COMMAND = str.strip(os.popen("which gemma").read())
-REAPER_COMMAND = HOME + "/gn2-zach/rust-qtlreaper/target/release/qtlreaper"
+REAPER_COMMAND = os.environ['GN2_PROFILE'] + "/bin/qtlreaper"
# GEMMA_WRAPPER_COMMAND = str.strip(os.popen("which gemma-wrapper").read())
diff --git a/wqflask/wqflask/heatmap/heatmap.py b/wqflask/wqflask/heatmap/heatmap.py
index 37454dfb..e82aa0ef 100644
--- a/wqflask/wqflask/heatmap/heatmap.py
+++ b/wqflask/wqflask/heatmap/heatmap.py
@@ -10,6 +10,7 @@ import datetime
import time
import pp
import math
+import random
import collections
import resource
@@ -23,9 +24,11 @@ import reaper
from base.trait import GeneralTrait
from base import data_set
from base import species
+from base import webqtlConfig
from utility import helper_functions
from utility import Plot, Bunch
from utility import temp_data
+from utility.tools import flat_files, REAPER_COMMAND, TEMPDIR
from MySQLdb import escape_string as escape
@@ -119,10 +122,15 @@ class Heatmap(object):
for trait_db in self.trait_list:
self.dataset.group.get_markers()
this_trait = trait_db[0]
- #this_db = trait_db[1]
- genotype = self.dataset.group.read_genotype_file(use_reaper=True)
+
+ genotype = self.dataset.group.read_genotype_file(use_reaper=False)
samples, values, variances, sample_aliases = this_trait.export_informative()
+ if self.dataset.group.genofile != None:
+ genofile_name = self.dataset.group.genofile[:-5]
+ else:
+ genofile_name = self.dataset.group.name
+
trimmed_samples = []
trimmed_values = []
for i in range(0, len(samples)):
@@ -130,14 +138,73 @@ class Heatmap(object):
trimmed_samples.append(str(samples[i]))
trimmed_values.append(values[i])
- reaper_results = genotype.regression(strains = trimmed_samples,
- trait = trimmed_values)
+ trait_filename = str(this_trait.name) + "_" + str(self.dataset.name) + "_pheno"
+ gen_pheno_txt_file(trimmed_samples, trimmed_values, trait_filename)
+
+ output_filename = self.dataset.group.name + "_GWA_" + ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6))
+
+ reaper_command = REAPER_COMMAND + ' --geno {0}/{1}.geno --traits {2}/gn2/{3}.txt -n 1000 -o {4}{5}.txt'.format(flat_files('genotype'),
+ genofile_name,
+ TEMPDIR,
+ trait_filename,
+ webqtlConfig.GENERATED_IMAGE_DIR,
+ output_filename)
+
+ os.system(reaper_command)
+
+ reaper_results = parse_reaper_output(output_filename)
- lrs_values = [float(qtl.lrs) for qtl in reaper_results]
+ lrs_values = [float(qtl['lrs_value']) for qtl in reaper_results]
self.trait_results[this_trait.name] = []
for qtl in reaper_results:
- if qtl.additive > 0:
- self.trait_results[this_trait.name].append(-float(qtl.lrs))
+ if qtl['additive'] > 0:
+ self.trait_results[this_trait.name].append(-float(qtl['lrs_value']))
else:
- self.trait_results[this_trait.name].append(float(qtl.lrs))
+ self.trait_results[this_trait.name].append(float(qtl['lrs_value']))
+
+def gen_pheno_txt_file(samples, vals, filename):
+ """Generates phenotype file for GEMMA"""
+
+ with open("{0}/gn2/{1}.txt".format(TEMPDIR, filename), "w") as outfile:
+ outfile.write("Trait\t")
+
+ filtered_sample_list = []
+ filtered_vals_list = []
+ for i, sample in enumerate(samples):
+ if vals[i] != "x":
+ filtered_sample_list.append(sample)
+ filtered_vals_list.append(str(vals[i]))
+
+ samples_string = "\t".join(filtered_sample_list)
+ outfile.write(samples_string + "\n")
+ outfile.write("T1\t")
+ values_string = "\t".join(filtered_vals_list)
+ outfile.write(values_string)
+
+def parse_reaper_output(gwa_filename):
+ included_markers = []
+ p_values = []
+ marker_obs = []
+
+ with open("{}{}.txt".format(webqtlConfig.GENERATED_IMAGE_DIR, gwa_filename)) as output_file:
+ for line in output_file:
+ if line.startswith("ID\t"):
+ continue
+ else:
+ marker = {}
+ marker['name'] = line.split("\t")[1]
+ try:
+ marker['chr'] = int(line.split("\t")[2])
+ except:
+ marker['chr'] = line.split("\t")[2]
+ marker['cM'] = float(line.split("\t")[3])
+ marker['Mb'] = float(line.split("\t")[4])
+ if float(line.split("\t")[7]) != 1:
+ marker['p_value'] = float(line.split("\t")[7])
+ marker['lrs_value'] = float(line.split("\t")[5])
+ marker['lod_score'] = marker['lrs_value'] / 4.61
+ marker['additive'] = float(line.split("\t")[6])
+ marker_obs.append(marker)
+
+ return marker_obs \ No newline at end of file
diff --git a/wqflask/wqflask/marker_regression/qtlreaper_mapping.py b/wqflask/wqflask/marker_regression/qtlreaper_mapping.py
index bbc8b513..50e6bd7e 100644
--- a/wqflask/wqflask/marker_regression/qtlreaper_mapping.py
+++ b/wqflask/wqflask/marker_regression/qtlreaper_mapping.py
@@ -18,7 +18,7 @@ def run_reaper(this_trait, this_dataset, samples, vals, json_data, num_perm, boo
genofile_name = this_dataset.group.name
trait_filename = str(this_trait.name) + "_" + str(this_dataset.name) + "_pheno"
- gen_pheno_txt_file(this_dataset, genofile_name, samples, vals, trait_filename)
+ gen_pheno_txt_file(samples, vals, trait_filename)
output_filename = this_dataset.group.name + "_GWA_" + ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6))
bootstrap_filename = None
@@ -61,7 +61,7 @@ def run_reaper(this_trait, this_dataset, samples, vals, json_data, num_perm, boo
return marker_obs, permu_vals, suggestive, significant, bootstrap_vals, [output_filename, permu_filename, bootstrap_filename]
-def gen_pheno_txt_file(this_dataset, genofile_name, samples, vals, trait_filename):
+def gen_pheno_txt_file(samples, vals, trait_filename):
"""Generates phenotype file for GEMMA"""
with open("{}/gn2/{}.txt".format(TEMPDIR, trait_filename), "w") as outfile:
diff --git a/wqflask/wqflask/marker_regression/run_mapping.py b/wqflask/wqflask/marker_regression/run_mapping.py
index 56d901fc..7c526f33 100644
--- a/wqflask/wqflask/marker_regression/run_mapping.py
+++ b/wqflask/wqflask/marker_regression/run_mapping.py
@@ -54,6 +54,11 @@ class RunMapping(object):
self.temp_uuid = temp_uuid #needed to pass temp_uuid to gn1 mapping code (marker_regression_gn1.py)
+ #ZS: Needed to zoom in or remap temp traits like PCA traits
+ if "temp_trait" in start_vars:
+ self.temp_trait = "True"
+ self.group = self.dataset.group.name
+
self.json_data = {}
self.json_data['lodnames'] = ['lod.hk']
diff --git a/wqflask/wqflask/static/new/javascript/dataset_menu_structure.json b/wqflask/wqflask/static/new/javascript/dataset_menu_structure.json
index 6531f5a0..492d4313 100644
--- a/wqflask/wqflask/static/new/javascript/dataset_menu_structure.json
+++ b/wqflask/wqflask/static/new/javascript/dataset_menu_structure.json
@@ -117,14 +117,14 @@
"Barley1 Leaf MAS 5.0 SCRI (Dec06)"
],
[
- "126",
- "B30_K_1206_Rn",
- "Barley1 Leaf gcRMAn SCRI (Dec06)"
- ],
- [
"125",
"B30_K_1206_R",
"Barley1 Leaf gcRMA SCRI (Dec06)"
+ ],
+ [
+ "126",
+ "B30_K_1206_Rn",
+ "Barley1 Leaf gcRMAn SCRI (Dec06)"
]
],
"Phenotypes": [
@@ -1623,14 +1623,14 @@
"NCI Mammary LMT miRNA v2 (Apr09) RMA"
],
[
- "37",
- "MA_M_0704_R",
- "NCI Mammary mRNA M430 (July04) RMA"
- ],
- [
"36",
"MA_M_0704_M",
"NCI Mammary mRNA M430 (July04) MAS5"
+ ],
+ [
+ "37",
+ "MA_M_0704_R",
+ "NCI Mammary mRNA M430 (July04) RMA"
]
]
},
@@ -1698,14 +1698,14 @@
],
"Liver mRNA": [
[
- "39",
- "LVF2_M_0704_R",
- "(B6 x BTBR)F2-ob/ob Liver mRNA M430 (Jul04) RMA"
- ],
- [
"38",
"LVF2_M_0704_M",
"(B6 x BTBR)F2-ob/ob Liver mRNA M430 (Jul04) MAS5"
+ ],
+ [
+ "39",
+ "LVF2_M_0704_R",
+ "(B6 x BTBR)F2-ob/ob Liver mRNA M430 (Jul04) RMA"
]
],
"Phenotypes": [
@@ -1728,6 +1728,11 @@
"B6D2F2": {
"Brain mRNA": [
[
+ "78",
+ "BRF2_M_0805_P",
+ "OHSU/VA B6D2F2 Brain mRNA M430 (Aug05) PDNN"
+ ],
+ [
"77",
"BRF2_M_0805_R",
"OHSU/VA B6D2F2 Brain mRNA M430 (Aug05) RMA"
@@ -1738,24 +1743,19 @@
"OHSU/VA B6D2F2 Brain mRNA M430 (Aug05) MAS5"
],
[
- "78",
- "BRF2_M_0805_P",
- "OHSU/VA B6D2F2 Brain mRNA M430 (Aug05) PDNN"
- ],
- [
"33",
"BRF2_M_0304_P",
"OHSU/VA B6D2F2 Brain mRNA M430A (Mar04) PDNN"
],
[
- "32",
- "BRF2_M_0304_R",
- "OHSU/VA B6D2F2 Brain mRNA M430A (Mar04) RMA"
- ],
- [
"31",
"BRF2_M_0304_M",
"OHSU/VA B6D2F2 Brain mRNA M430A (Mar04) MAS5"
+ ],
+ [
+ "32",
+ "BRF2_M_0304_R",
+ "OHSU/VA B6D2F2 Brain mRNA M430A (Mar04) RMA"
]
],
"Genotypes": [
@@ -1834,6 +1834,11 @@
],
"Striatum mRNA": [
[
+ "83",
+ "SA_M2_0905_M",
+ "OHSU/VA B6D2F2 Striatum M430v2 (Sep05) MAS5"
+ ],
+ [
"85",
"SA_M2_0905_P",
"OHSU/VA B6D2F2 Striatum M430v2 (Sep05) PDNN"
@@ -1842,11 +1847,6 @@
"84",
"SA_M2_0905_R",
"OHSU/VA B6D2F2 Striatum M430v2 (Sep05) RMA"
- ],
- [
- "83",
- "SA_M2_0905_M",
- "OHSU/VA B6D2F2 Striatum M430v2 (Sep05) MAS5"
]
]
},
@@ -2122,16 +2122,16 @@
"INIA Brain mRNA M430 (Jun06) RMA"
],
[
- "102",
- "IBR_M_0106_R",
- "INIA Brain mRNA M430 (Jan06) RMA"
- ],
- [
"101",
"IBR_M_0106_P",
"INIA Brain mRNA M430 (Jan06) PDNN"
],
[
+ "102",
+ "IBR_M_0106_R",
+ "INIA Brain mRNA M430 (Jan06) RMA"
+ ],
+ [
"95",
"BR_U_1105_P",
"UTHSC Brain mRNA U74Av2 (Nov05) PDNN"
@@ -2551,16 +2551,16 @@
],
"Kidney mRNA": [
[
- "239",
- "MA_M2F_0706_R",
- "Mouse kidney M430v2 Female (Aug06) RMA"
- ],
- [
"240",
"MA_M2M_0706_R",
"Mouse kidney M430v2 Male (Aug06) RMA"
],
[
+ "239",
+ "MA_M2F_0706_R",
+ "Mouse kidney M430v2 Female (Aug06) RMA"
+ ],
+ [
"118",
"MA_M2_0806_R",
"Mouse kidney M430v2 Sex Balanced (Aug06) RMA"
@@ -2571,28 +2571,28 @@
"Mouse Kidney M430v2 Sex Balanced (Aug06) PDNN"
],
[
- "116",
- "MA_M2_0706_P",
- "Mouse Kidney M430v2 (Jul06) PDNN"
- ],
- [
"115",
"MA_M2_0706_R",
"Mouse Kidney M430v2 (Jul06) RMA"
+ ],
+ [
+ "116",
+ "MA_M2_0706_P",
+ "Mouse Kidney M430v2 (Jul06) PDNN"
]
],
"Liver Metabolome": [
[
- "836",
- "UTHSC-ETHZ-EPFL_LivPMetExtAHFD0817",
- "UTHSC/ETHZ/EPFL BXD Liver Polar Metabolites Extraction, HFD Cohorts (Jul 2017) log2"
- ],
- [
"835",
"UTHSC-ETHZ-EPFL_LivPMetExtACD0817",
"UTHSC/ETHZ/EPFL BXD Liver Polar Metabolites Extraction, Chow Diet Cohorts (Jul 2017) log2"
],
[
+ "836",
+ "UTHSC-ETHZ-EPFL_LivPMetExtAHFD0817",
+ "UTHSC/ETHZ/EPFL BXD Liver Polar Metabolites Extraction, HFD Cohorts (Jul 2017) log2"
+ ],
+ [
"473",
"EPFL-LISP_LivPMetCDHFD1213",
"EPFL/LISP BXD Liver Polar Metabolites CD+HFD (Jun14)"
@@ -2845,16 +2845,16 @@
],
"Neocortex mRNA": [
[
- "375",
- "DevNeocortex_ILM6.2P14RInv_1111",
- "BIDMC/UTHSC Dev Neocortex P14 ILMv6.2 (Nov11) RankInv"
- ],
- [
"374",
"DevNeocortex_ILM6.2P3RInv_1111",
"BIDMC/UTHSC Dev Neocortex P3 ILMv6.2 (Nov11) RankInv"
],
[
+ "375",
+ "DevNeocortex_ILM6.2P14RInv_1111",
+ "BIDMC/UTHSC Dev Neocortex P14 ILMv6.2 (Nov11) RankInv"
+ ],
+ [
"284",
"HQFNeoc_1210v2_RankInv",
"HQF BXD Neocortex ILM6v1.1 (Dec10v2) RankInv"
@@ -3110,6 +3110,11 @@
],
"Ventral Tegmental Area mRNA": [
[
+ "228",
+ "VCUSal_0609_R",
+ "VCU BXD VTA Sal M430 2.0 (Jun09) RMA"
+ ],
+ [
"230",
"VCUEtvsSal_0609_R",
"VCU BXD VTA Et vs Sal M430 2.0 (Jun09) RMA"
@@ -3118,11 +3123,6 @@
"229",
"VCUEtOH_0609_R",
"VCU BXD VTA EtOH M430 2.0 (Jun09) RMA"
- ],
- [
- "228",
- "VCUSal_0609_R",
- "VCU BXD VTA Sal M430 2.0 (Jun09) RMA"
]
]
},
@@ -3264,7 +3264,7 @@
[
"808",
"UCSD_CFW_HIP_RNA-Seq_0117",
- "UCSD CFW Hippocampus (Jan17) RNA-Seq"
+ "UCSD CFW Hippocampus RNA-Seq (Jan17) FPKM Quantile"
]
],
"Phenotypes": [
@@ -3463,14 +3463,14 @@
],
"Hippocampus mRNA": [
[
- "100",
- "HC_M2CB_1205_R",
- "Hippocampus Consortium M430v2 CXB (Dec05) RMA"
- ],
- [
"99",
"HC_M2CB_1205_P",
"Hippocampus Consortium M430v2 CXB (Dec05) PDNN"
+ ],
+ [
+ "100",
+ "HC_M2CB_1205_R",
+ "Hippocampus Consortium M430v2 CXB (Dec05) RMA"
]
],
"Liver mRNA": [
@@ -3675,14 +3675,14 @@
],
"Hippocampus mRNA": [
[
- "273",
- "UMUTAffyExon_0209_RMA_MDP",
- "UMUTAffy Hippocampus Exon (Feb09) RMA MDP"
- ],
- [
"272",
"HC_M2_0606_MDP",
"Hippocampus Consortium M430v2 (Jun06) RMA MDP"
+ ],
+ [
+ "273",
+ "UMUTAffyExon_0209_RMA_MDP",
+ "UMUTAffy Hippocampus Exon (Feb09) RMA MDP"
]
],
"Liver mRNA": [
diff --git a/wqflask/wqflask/static/new/javascript/get_traits_from_collection.js b/wqflask/wqflask/static/new/javascript/get_traits_from_collection.js
index d89264c6..a34394a1 100644
--- a/wqflask/wqflask/static/new/javascript/get_traits_from_collection.js
+++ b/wqflask/wqflask/static/new/javascript/get_traits_from_collection.js
@@ -42,23 +42,27 @@ $('#trait_table').dataTable( {
} );
$('#collection_table').dataTable( {
- "createdRow": function ( row, data, index ) {
- if ($('td', row).eq(1).text().length > 40) {
- $('td', row).eq(1).text($('td', row).eq(1).text().substring(0, 40));
- $('td', row).eq(1).text($('td', row).eq(1).text() + '...')
- }
- if ($('td', row).eq(3).text().length > 50) {
- $('td', row).eq(3).text($('td', row).eq(3).text().substring(0, 50));
- $('td', row).eq(3).text($('td', row).eq(3).text() + '...')
- }
- },
- "order": [[0, "asc" ]],
- "sDom": "ZRtr",
- "iDisplayLength": -1,
- "autoWidth": true,
- "bSortClasses": false,
- "paging": false,
- "orderClasses": true
+ "createdRow": function ( row, data, index ) {
+ if ($('td', row).eq(2).text().length > 40) {
+ $('td', row).eq(2).text($('td', row).eq(2).text().substring(0, 40));
+ $('td', row).eq(2).text($('td', row).eq(2).text() + '...')
+ }
+ if ($('td', row).eq(4).text().length > 50) {
+ $('td', row).eq(4).text($('td', row).eq(4).text().substring(0, 50));
+ $('td', row).eq(4).text($('td', row).eq(4).text() + '...')
+ }
+ },
+ "columnDefs": [ {
+ "targets": 0,
+ "orderable": false
+ } ],
+ "order": [[1, "asc" ]],
+ "sDom": "ZRtr",
+ "iDisplayLength": -1,
+ "autoWidth": true,
+ "bSortClasses": false,
+ "paging": false,
+ "orderClasses": true
} );
collection_click = function() {
@@ -364,37 +368,29 @@ color_by_trait = function(trait_sample_data, textStatus, jqXHR) {
process_traits = function(trait_data, textStatus, jqXHR) {
var the_html, trait, _i, _len;
console.log('in process_traits with trait_data:', trait_data);
- the_html = "<button id='back_to_collections' class='btn btn-default'>";
+ the_html = "<button id='back_to_collections' class='btn btn-inverse btn-small'>";
the_html += "<i class='icon-white icon-arrow-left'></i> Back </button>";
- if ($('.corr_compute').length){
- the_html += " <button id='submit' class='btn btn-primary btn-small'> Submit </button>";
- }
- if ($('#scatterplot2').length){
- the_html += " Please click the row of the trait you wish to select as a cofactor.";
- }
- the_html += "<table id='collection_table' class='table table-hover'>";
- if ($('.corr_compute').length){
- the_html += "<thead><tr><th></th><th>Record</th><th>Data Set</th><th>Description</th><th>Mean</th></tr></thead>";
- } else {
- the_html += "<thead><tr><th>Record</th><th>Data Set</th><th>Description</th></tr></thead>";
- }
+ the_html += " <button id='submit' class='btn btn-primary btn-small'> Submit </button>";
+ the_html += "<table id='collection_table' style='padding-top: 10px;' class='table table-hover'>";
+ the_html += "<thead><tr><th></th><th>Record</th><th>Data Set</th><th>Description</th></tr></thead>";
the_html += "<tbody>";
for (_i = 0, _len = trait_data.length; _i < _len; _i++) {
trait = trait_data[_i];
the_html += "<tr class='trait_line'>";
- if ($('.corr_compute').length){
- the_html += "<td class='select_trait'><input type='checkbox' name='selectCheck' class='checkbox edit_sample_checkbox'></td>";
+ the_html += "<td class='select_trait'><input type='checkbox' name='selectCheck' class='checkbox edit_sample_checkbox'></td>";
+ if ("abbreviation" in trait) {
+ the_html += "<td class='trait' data-display_name='" + trait.name + " - " + trait.abbreviation + "'>" + trait.name + "</td>";
+ } else if ("symbol" in trait) {
+ the_html += "<td class='trait' data-display_name='" + trait.name + " - " + trait.symbol + "'>" + trait.name + "</td>";
+ } else {
+ the_html += "<td class='trait' data-display_name='" + trait.name + "'>" + trait.name + "</td>";
}
- the_html += "<td class='trait'>" + trait.name + "</td>";
- the_html += "<td class='dataset'>" + trait.dataset + "</td>";
- the_html += "<td>" + trait.description + "</td>";
+ the_html += "<td class='dataset' data-dataset='" + trait.dataset + "'>" + trait.dataset_name + "</td>";
+ the_html += "<td class='description'>" + trait.description + "</td>";
}
the_html += "</tbody>";
the_html += "</table>";
- the_html += "<div id=\"collection_list_html\" style=\"display: none;\">"
- the_html += collection_list
- the_html += "</div>"
- the_html += "<script type='text/javascript' src='/static/new/javascript/get_traits_from_collection.js'></script>"
+ the_html += "<script type='text/javascript' src='/static/new/javascript/get_covariates_from_collection.js'></script>"
$("#collections_holder").html(the_html);
return $('#collections_holder').colorbox.resize();
};
diff --git a/wqflask/wqflask/static/new/javascript/network_graph.js b/wqflask/wqflask/static/new/javascript/network_graph.js
index bc02181f..4d507a18 100644
--- a/wqflask/wqflask/static/new/javascript/network_graph.js
+++ b/wqflask/wqflask/static/new/javascript/network_graph.js
@@ -144,7 +144,7 @@ window.onload=function() {
cy.layout({ name: $('select[name=layout_select]').val(),
fit: true, // whether to fit the viewport to the graph
padding: 25 // the padding on fit
- });
+ }).run();
});
$('#pos_slide').change(function() {
@@ -157,7 +157,7 @@ window.onload=function() {
cy.layout({ name: $('select[name=layout_select]').val(),
fit: true, // whether to fit the viewport to the graph
padding: 25 // the padding on fit
- });
+ }).run();
});
@@ -168,7 +168,7 @@ window.onload=function() {
cy.layout({ name: $('select[name=layout_select]').val(),
fit: true, // whether to fit the viewport to the graph
padding: 25 // the padding on fit
- });
+ }).run();
});
$('select[name=focus_select]').change(function() {
@@ -180,7 +180,7 @@ window.onload=function() {
cy.layout({ name: $('select[name=layout_select]').val(),
fit: true, // whether to fit the viewport to the graph
padding: 25 // the padding on fit
- });
+ }).run();
});
$('select[name=layout_select]').change(function() {
@@ -188,7 +188,7 @@ window.onload=function() {
cy.layout({ name: layout_type,
fit: true, // whether to fit the viewport to the graph
padding: 25 // the padding on fit
- });
+ }).run();
});
$('select[name=font_size]').change(function() {
@@ -219,7 +219,7 @@ window.onload=function() {
cy.layout({ name: $('select[name=layout_select]').val(),
fit: true, // whether to fit the viewport to the graph
padding: 25 // the padding on fit
- });
+ }).run();
});
$('select[name=edge_width]').change(function() {
@@ -243,7 +243,7 @@ window.onload=function() {
cy.layout({ name: $('select[name=layout_select]').val(),
fit: true, // whether to fit the viewport to the graph
padding: 25 // the padding on fit
- });
+ }).run();
});
$("a#image_link").click(function(e) {
@@ -251,9 +251,6 @@ window.onload=function() {
$(this).attr('href', pngData);
$(this).attr('download', 'network_graph.png');
-
- console.log("TESTING:", image_link)
-
});
diff --git a/wqflask/wqflask/static/new/packages/nvd3/nv.d3.css b/wqflask/wqflask/static/new/packages/nvd3/nv.d3.css
deleted file mode 100644
index 593d3889..00000000
--- a/wqflask/wqflask/static/new/packages/nvd3/nv.d3.css
+++ /dev/null
@@ -1,641 +0,0 @@
-/* nvd3 version 1.8.1 (https://github.com/novus/nvd3) 2015-05-25 */
-.nvd3 .nv-axis {
- pointer-events:none;
- opacity: 1;
-}
-
-.nvd3 .nv-axis path {
- fill: none;
- stroke: #000;
- stroke-opacity: .75;
- shape-rendering: crispEdges;
-}
-
-.nvd3 .nv-axis path.domain {
- stroke-opacity: .75;
-}
-
-.nvd3 .nv-axis.nv-x path.domain {
- stroke-opacity: 1;
-}
-
-.nvd3 .nv-axis line {
- fill: none;
- stroke: #e5e5e5;
- shape-rendering: crispEdges;
-}
-
-.nvd3 .nv-axis .zero line,
- /*this selector may not be necessary*/ .nvd3 .nv-axis line.zero {
- stroke-opacity: .75;
-}
-
-.nvd3 .nv-axis .nv-axisMaxMin text {
- font-weight: bold;
-}
-
-.nvd3 .x .nv-axis .nv-axisMaxMin text,
-.nvd3 .x2 .nv-axis .nv-axisMaxMin text,
-.nvd3 .x3 .nv-axis .nv-axisMaxMin text {
- text-anchor: middle
-}
-
-.nvd3 .nv-axis.nv-disabled {
- opacity: 0;
-}
-
-.nvd3 .nv-bars rect {
- fill-opacity: .75;
-
- transition: fill-opacity 250ms linear;
- -moz-transition: fill-opacity 250ms linear;
- -webkit-transition: fill-opacity 250ms linear;
-}
-
-.nvd3 .nv-bars rect.hover {
- fill-opacity: 1;
-}
-
-.nvd3 .nv-bars .hover rect {
- fill: lightblue;
-}
-
-.nvd3 .nv-bars text {
- fill: rgba(0,0,0,0);
-}
-
-.nvd3 .nv-bars .hover text {
- fill: rgba(0,0,0,1);
-}
-
-.nvd3 .nv-multibar .nv-groups rect,
-.nvd3 .nv-multibarHorizontal .nv-groups rect,
-.nvd3 .nv-discretebar .nv-groups rect {
- stroke-opacity: 0;
-
- transition: fill-opacity 250ms linear;
- -moz-transition: fill-opacity 250ms linear;
- -webkit-transition: fill-opacity 250ms linear;
-}
-
-.nvd3 .nv-multibar .nv-groups rect:hover,
-.nvd3 .nv-multibarHorizontal .nv-groups rect:hover,
-.nvd3 .nv-candlestickBar .nv-ticks rect:hover,
-.nvd3 .nv-discretebar .nv-groups rect:hover {
- fill-opacity: 1;
-}
-
-.nvd3 .nv-discretebar .nv-groups text,
-.nvd3 .nv-multibarHorizontal .nv-groups text {
- font-weight: bold;
- fill: rgba(0,0,0,1);
- stroke: rgba(0,0,0,0);
-}
-
-/* boxplot CSS */
-.nvd3 .nv-boxplot circle {
- fill-opacity: 0.5;
-}
-
-.nvd3 .nv-boxplot circle:hover {
- fill-opacity: 1;
-}
-
-.nvd3 .nv-boxplot rect:hover {
- fill-opacity: 1;
-}
-
-.nvd3 line.nv-boxplot-median {
- stroke: black;
-}
-
-.nv-boxplot-tick:hover {
- stroke-width: 2.5px;
-}
-/* bullet */
-.nvd3.nv-bullet { font: 10px sans-serif; }
-.nvd3.nv-bullet .nv-measure { fill-opacity: .8; }
-.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; }
-.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; }
-.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; }
-.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; }
-.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; }
-.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; }
-.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; }
-.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; }
-.nvd3.nv-bullet .nv-subtitle { fill: #999; }
-
-
-.nvd3.nv-bullet .nv-range {
- fill: #bababa;
- fill-opacity: .4;
-}
-.nvd3.nv-bullet .nv-range:hover {
- fill-opacity: .7;
-}
-
-.nvd3.nv-candlestickBar .nv-ticks .nv-tick {
- stroke-width: 1px;
-}
-
-.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover {
- stroke-width: 2px;
-}
-
-.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect {
- stroke: #2ca02c;
- fill: #2ca02c;
-}
-
-.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect {
- stroke: #d62728;
- fill: #d62728;
-}
-
-.with-transitions .nv-candlestickBar .nv-ticks .nv-tick {
- transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
- -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
- -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
-
-}
-
-.nvd3.nv-candlestickBar .nv-ticks line {
- stroke: #333;
-}
-
-
-.nvd3 .nv-legend .nv-disabled rect {
- /*fill-opacity: 0;*/
-}
-
-.nvd3 .nv-check-box .nv-box {
- fill-opacity:0;
- stroke-width:2;
-}
-
-.nvd3 .nv-check-box .nv-check {
- fill-opacity:0;
- stroke-width:4;
-}
-
-.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check {
- fill-opacity:0;
- stroke-opacity:0;
-}
-
-.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check {
- opacity: 0;
-}
-
-/* line plus bar */
-.nvd3.nv-linePlusBar .nv-bar rect {
- fill-opacity: .75;
-}
-
-.nvd3.nv-linePlusBar .nv-bar rect:hover {
- fill-opacity: 1;
-}
-.nvd3 .nv-groups path.nv-line {
- fill: none;
-}
-
-.nvd3 .nv-groups path.nv-area {
- stroke: none;
-}
-
-.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point {
- fill-opacity: 0;
- stroke-opacity: 0;
-}
-
-.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point {
- fill-opacity: .5 !important;
- stroke-opacity: .5 !important;
-}
-
-
-.with-transitions .nvd3 .nv-groups .nv-point {
- transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
- -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
- -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
-
-}
-
-.nvd3.nv-scatter .nv-groups .nv-point.hover,
-.nvd3 .nv-groups .nv-point.hover {
- stroke-width: 7px;
- fill-opacity: .95 !important;
- stroke-opacity: .95 !important;
-}
-
-
-.nvd3 .nv-point-paths path {
- stroke: #aaa;
- stroke-opacity: 0;
- fill: #eee;
- fill-opacity: 0;
-}
-
-
-
-.nvd3 .nv-indexLine {
- cursor: ew-resize;
-}
-
-/********************
- * SVG CSS
- */
-
-/********************
- Default CSS for an svg element nvd3 used
-*/
-svg.nvd3-svg {
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -ms-user-select: none;
- -moz-user-select: none;
- user-select: none;
- display: block;
- width:100%;
- height:100%;
-}
-
-/********************
- Box shadow and border radius styling
-*/
-.nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip {
- -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
- -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
- box-shadow: 0 5px 10px rgba(0,0,0,.2);
-
- -webkit-border-radius: 5px;
- -moz-border-radius: 5px;
- border-radius: 5px;
-}
-
-
-.nvd3 text {
- font: normal 14px Arial;
-}
-
-.nvd3 .title {
- font: bold 14px Arial;
-}
-
-.nvd3 .nv-background {
- fill: white;
- fill-opacity: 0;
-}
-
-.nvd3.nv-noData {
- font-size: 18px;
- font-weight: bold;
-}
-
-
-/**********
-* Brush
-*/
-
-.nv-brush .extent {
- fill-opacity: .125;
- shape-rendering: crispEdges;
-}
-
-.nv-brush .resize path {
- fill: #eee;
- stroke: #666;
-}
-
-
-/**********
-* Legend
-*/
-
-.nvd3 .nv-legend .nv-series {
- cursor: pointer;
-}
-
-.nvd3 .nv-legend .nv-disabled circle {
- fill-opacity: 0;
-}
-
-/* focus */
-.nvd3 .nv-brush .extent {
- fill-opacity: 0 !important;
-}
-
-.nvd3 .nv-brushBackground rect {
- stroke: #000;
- stroke-width: .4;
- fill: #fff;
- fill-opacity: .7;
-}
-
-
-.nvd3.nv-ohlcBar .nv-ticks .nv-tick {
- stroke-width: 1px;
-}
-
-.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover {
- stroke-width: 2px;
-}
-
-.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive {
- stroke: #2ca02c;
-}
-
-.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative {
- stroke: #d62728;
-}
-
-
-.nvd3 .background path {
- fill: none;
- stroke: #EEE;
- stroke-opacity: .4;
- shape-rendering: crispEdges;
-}
-
-.nvd3 .foreground path {
- fill: none;
- stroke-opacity: .7;
-}
-
-.nvd3 .nv-parallelCoordinates-brush .extent
-{
- fill: #fff;
- fill-opacity: .6;
- stroke: gray;
- shape-rendering: crispEdges;
-}
-
-.nvd3 .nv-parallelCoordinates .hover {
- fill-opacity: 1;
- stroke-width: 3px;
-}
-
-
-.nvd3 .missingValuesline line {
- fill: none;
- stroke: black;
- stroke-width: 1;
- stroke-opacity: 1;
- stroke-dasharray: 5, 5;
-}
-.nvd3.nv-pie path {
- stroke-opacity: 0;
- transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
- -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
- -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
-
-}
-
-.nvd3.nv-pie .nv-pie-title {
- font-size: 24px;
- fill: rgba(19, 196, 249, 0.59);
-}
-
-.nvd3.nv-pie .nv-slice text {
- stroke: #000;
- stroke-width: 0;
-}
-
-.nvd3.nv-pie path {
- stroke: #fff;
- stroke-width: 1px;
- stroke-opacity: 1;
-}
-
-.nvd3.nv-pie .hover path {
- fill-opacity: .7;
-}
-.nvd3.nv-pie .nv-label {
- pointer-events: none;
-}
-.nvd3.nv-pie .nv-label rect {
- fill-opacity: 0;
- stroke-opacity: 0;
-}
-
-/* scatter */
-.nvd3 .nv-groups .nv-point.hover {
- stroke-width: 20px;
- stroke-opacity: .5;
-}
-
-.nvd3 .nv-scatter .nv-point.hover {
- fill-opacity: 1;
-}
-.nv-noninteractive {
- pointer-events: none;
-}
-
-.nv-distx, .nv-disty {
- pointer-events: none;
-}
-
-/* sparkline */
-.nvd3.nv-sparkline path {
- fill: none;
-}
-
-.nvd3.nv-sparklineplus g.nv-hoverValue {
- pointer-events: none;
-}
-
-.nvd3.nv-sparklineplus .nv-hoverValue line {
- stroke: #333;
- stroke-width: 1.5px;
-}
-
-.nvd3.nv-sparklineplus,
-.nvd3.nv-sparklineplus g {
- pointer-events: all;
-}
-
-.nvd3 .nv-hoverArea {
- fill-opacity: 0;
- stroke-opacity: 0;
-}
-
-.nvd3.nv-sparklineplus .nv-xValue,
-.nvd3.nv-sparklineplus .nv-yValue {
- stroke-width: 0;
- font-size: .9em;
- font-weight: normal;
-}
-
-.nvd3.nv-sparklineplus .nv-yValue {
- stroke: #f66;
-}
-
-.nvd3.nv-sparklineplus .nv-maxValue {
- stroke: #2ca02c;
- fill: #2ca02c;
-}
-
-.nvd3.nv-sparklineplus .nv-minValue {
- stroke: #d62728;
- fill: #d62728;
-}
-
-.nvd3.nv-sparklineplus .nv-currentValue {
- font-weight: bold;
- font-size: 1.1em;
-}
-/* stacked area */
-.nvd3.nv-stackedarea path.nv-area {
- fill-opacity: .7;
- stroke-opacity: 0;
- transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
- -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
- -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
-}
-
-.nvd3.nv-stackedarea path.nv-area.hover {
- fill-opacity: .9;
-}
-
-
-.nvd3.nv-stackedarea .nv-groups .nv-point {
- stroke-opacity: 0;
- fill-opacity: 0;
-}
-
-
-.nvtooltip {
- position: absolute;
- background-color: rgba(255,255,255,1.0);
- color: rgba(0,0,0,1.0);
- padding: 1px;
- border: 1px solid rgba(0,0,0,.2);
- z-index: 10000;
- display: block;
-
- font-family: Arial;
- font-size: 13px;
- text-align: left;
- pointer-events: none;
-
- white-space: nowrap;
-
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-
-.nvtooltip {
- background: rgba(255,255,255, 0.8);
- border: 1px solid rgba(0,0,0,0.5);
- border-radius: 4px;
-}
-
-/*Give tooltips that old fade in transition by
- putting a "with-transitions" class on the container div.
-*/
-.nvtooltip.with-transitions, .with-transitions .nvtooltip {
- transition: opacity 50ms linear;
- -moz-transition: opacity 50ms linear;
- -webkit-transition: opacity 50ms linear;
-
- transition-delay: 200ms;
- -moz-transition-delay: 200ms;
- -webkit-transition-delay: 200ms;
-}
-
-.nvtooltip.x-nvtooltip,
-.nvtooltip.y-nvtooltip {
- padding: 8px;
-}
-
-.nvtooltip h3 {
- margin: 0;
- padding: 4px 14px;
- line-height: 18px;
- font-weight: normal;
- background-color: rgba(247,247,247,0.75);
- color: rgba(0,0,0,1.0);
- text-align: center;
-
- border-bottom: 1px solid #ebebeb;
-
- -webkit-border-radius: 5px 5px 0 0;
- -moz-border-radius: 5px 5px 0 0;
- border-radius: 5px 5px 0 0;
-}
-
-.nvtooltip p {
- margin: 0;
- padding: 5px 14px;
- text-align: center;
-}
-
-.nvtooltip span {
- display: inline-block;
- margin: 2px 0;
-}
-
-.nvtooltip table {
- margin: 6px;
- border-spacing:0;
-}
-
-
-.nvtooltip table td {
- padding: 2px 9px 2px 0;
- vertical-align: middle;
-}
-
-.nvtooltip table td.key {
- font-weight:normal;
-}
-.nvtooltip table td.value {
- text-align: right;
- font-weight: bold;
-}
-
-.nvtooltip table tr.highlight td {
- padding: 1px 9px 1px 0;
- border-bottom-style: solid;
- border-bottom-width: 1px;
- border-top-style: solid;
- border-top-width: 1px;
-}
-
-.nvtooltip table td.legend-color-guide div {
- width: 8px;
- height: 8px;
- vertical-align: middle;
-}
-
-.nvtooltip table td.legend-color-guide div {
- width: 12px;
- height: 12px;
- border: 1px solid #999;
-}
-
-.nvtooltip .footer {
- padding: 3px;
- text-align: center;
-}
-
-.nvtooltip-pending-removal {
- pointer-events: none;
- display: none;
-}
-
-
-/****
-Interactive Layer
-*/
-.nvd3 .nv-interactiveGuideLine {
- pointer-events:none;
-}
-.nvd3 line.nv-guideline {
- stroke: #ccc;
-} \ No newline at end of file
diff --git a/wqflask/wqflask/static/new/packages/nvd3/nv.d3.js b/wqflask/wqflask/static/new/packages/nvd3/nv.d3.js
deleted file mode 100644
index f64a6c14..00000000
--- a/wqflask/wqflask/static/new/packages/nvd3/nv.d3.js
+++ /dev/null
@@ -1,13363 +0,0 @@
-/* nvd3 version 1.8.1 (https://github.com/novus/nvd3) 2015-05-25 */
-(function(){
-
-// set up main nv object
-var nv = {};
-
-// the major global objects under the nv namespace
-nv.dev = false; //set false when in production
-nv.tooltip = nv.tooltip || {}; // For the tooltip system
-nv.utils = nv.utils || {}; // Utility subsystem
-nv.models = nv.models || {}; //stores all the possible models/components
-nv.charts = {}; //stores all the ready to use charts
-nv.logs = {}; //stores some statistics and potential error messages
-nv.dom = {}; //DOM manipulation functions
-
-nv.dispatch = d3.dispatch('render_start', 'render_end');
-
-// Function bind polyfill
-// Needed ONLY for phantomJS as it's missing until version 2.0 which is unreleased as of this comment
-// https://github.com/ariya/phantomjs/issues/10522
-// http://kangax.github.io/compat-table/es5/#Function.prototype.bind
-// phantomJS is used for running the test suite
-if (!Function.prototype.bind) {
- Function.prototype.bind = function (oThis) {
- if (typeof this !== "function") {
- // closest thing possible to the ECMAScript 5 internal IsCallable function
- throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
- }
-
- var aArgs = Array.prototype.slice.call(arguments, 1),
- fToBind = this,
- fNOP = function () {},
- fBound = function () {
- return fToBind.apply(this instanceof fNOP && oThis
- ? this
- : oThis,
- aArgs.concat(Array.prototype.slice.call(arguments)));
- };
-
- fNOP.prototype = this.prototype;
- fBound.prototype = new fNOP();
- return fBound;
- };
-}
-
-// Development render timers - disabled if dev = false
-if (nv.dev) {
- nv.dispatch.on('render_start', function(e) {
- nv.logs.startTime = +new Date();
- });
-
- nv.dispatch.on('render_end', function(e) {
- nv.logs.endTime = +new Date();
- nv.logs.totalTime = nv.logs.endTime - nv.logs.startTime;
- nv.log('total', nv.logs.totalTime); // used for development, to keep track of graph generation times
- });
-}
-
-// Logs all arguments, and returns the last so you can test things in place
-// Note: in IE8 console.log is an object not a function, and if modernizr is used
-// then calling Function.prototype.bind with with anything other than a function
-// causes a TypeError to be thrown.
-nv.log = function() {
- if (nv.dev && window.console && console.log && console.log.apply)
- console.log.apply(console, arguments);
- else if (nv.dev && window.console && typeof console.log == "function" && Function.prototype.bind) {
- var log = Function.prototype.bind.call(console.log, console);
- log.apply(console, arguments);
- }
- return arguments[arguments.length - 1];
-};
-
-// print console warning, should be used by deprecated functions
-nv.deprecated = function(name, info) {
- if (console && console.warn) {
- console.warn('nvd3 warning: `' + name + '` has been deprecated. ', info || '');
- }
-};
-
-// The nv.render function is used to queue up chart rendering
-// in non-blocking async functions.
-// When all queued charts are done rendering, nv.dispatch.render_end is invoked.
-nv.render = function render(step) {
- // number of graphs to generate in each timeout loop
- step = step || 1;
-
- nv.render.active = true;
- nv.dispatch.render_start();
-
- var renderLoop = function() {
- var chart, graph;
-
- for (var i = 0; i < step && (graph = nv.render.queue[i]); i++) {
- chart = graph.generate();
- if (typeof graph.callback == typeof(Function)) graph.callback(chart);
- }
-
- nv.render.queue.splice(0, i);
-
- if (nv.render.queue.length) {
- setTimeout(renderLoop);
- }
- else {
- nv.dispatch.render_end();
- nv.render.active = false;
- }
- };
-
- setTimeout(renderLoop);
-};
-
-nv.render.active = false;
-nv.render.queue = [];
-
-/*
-Adds a chart to the async rendering queue. This method can take arguments in two forms:
-nv.addGraph({
- generate: <Function>
- callback: <Function>
-})
-
-or
-
-nv.addGraph(<generate Function>, <callback Function>)
-
-The generate function should contain code that creates the NVD3 model, sets options
-on it, adds data to an SVG element, and invokes the chart model. The generate function
-should return the chart model. See examples/lineChart.html for a usage example.
-
-The callback function is optional, and it is called when the generate function completes.
-*/
-nv.addGraph = function(obj) {
- if (typeof arguments[0] === typeof(Function)) {
- obj = {generate: arguments[0], callback: arguments[1]};
- }
-
- nv.render.queue.push(obj);
-
- if (!nv.render.active) {
- nv.render();
- }
-};
-
-// Node/CommonJS exports
-if (typeof(module) !== 'undefined' && typeof(exports) !== 'undefined') {
- module.exports = nv;
-}
-
-if (typeof(window) !== 'undefined') {
- window.nv = nv;
-}
-/* Facade for queueing DOM write operations
- * with Fastdom (https://github.com/wilsonpage/fastdom)
- * if available.
- * This could easily be extended to support alternate
- * implementations in the future.
- */
-nv.dom.write = function(callback) {
- if (window.fastdom !== undefined) {
- return fastdom.write(callback);
- }
- return callback();
-};
-
-/* Facade for queueing DOM read operations
- * with Fastdom (https://github.com/wilsonpage/fastdom)
- * if available.
- * This could easily be extended to support alternate
- * implementations in the future.
- */
-nv.dom.read = function(callback) {
- if (window.fastdom !== undefined) {
- return fastdom.read(callback);
- }
- return callback();
-};/* Utility class to handle creation of an interactive layer.
- This places a rectangle on top of the chart. When you mouse move over it, it sends a dispatch
- containing the X-coordinate. It can also render a vertical line where the mouse is located.
-
- dispatch.elementMousemove is the important event to latch onto. It is fired whenever the mouse moves over
- the rectangle. The dispatch is given one object which contains the mouseX/Y location.
- It also has 'pointXValue', which is the conversion of mouseX to the x-axis scale.
- */
-nv.interactiveGuideline = function() {
- "use strict";
-
- var tooltip = nv.models.tooltip();
- tooltip.duration(0).hideDelay(0)._isInteractiveLayer(true).hidden(false);
-
- //Public settings
- var width = null;
- var height = null;
-
- //Please pass in the bounding chart's top and left margins
- //This is important for calculating the correct mouseX/Y positions.
- var margin = {left: 0, top: 0}
- , xScale = d3.scale.linear()
- , dispatch = d3.dispatch('elementMousemove', 'elementMouseout', 'elementClick', 'elementDblclick')
- , showGuideLine = true;
- //Must pass in the bounding chart's <svg> container.
- //The mousemove event is attached to this container.
- var svgContainer = null;
-
- // check if IE by looking for activeX
- var isMSIE = "ActiveXObject" in window;
-
-
- function layer(selection) {
- selection.each(function(data) {
- var container = d3.select(this);
- var availableWidth = (width || 960), availableHeight = (height || 400);
- var wrap = container.selectAll("g.nv-wrap.nv-interactiveLineLayer")
- .data([data]);
- var wrapEnter = wrap.enter()
- .append("g").attr("class", " nv-wrap nv-interactiveLineLayer");
- wrapEnter.append("g").attr("class","nv-interactiveGuideLine");
-
- if (!svgContainer) {
- return;
- }
-
- function mouseHandler() {
- var d3mouse = d3.mouse(this);
- var mouseX = d3mouse[0];
- var mouseY = d3mouse[1];
- var subtractMargin = true;
- var mouseOutAnyReason = false;
- if (isMSIE) {
- /*
- D3.js (or maybe SVG.getScreenCTM) has a nasty bug in Internet Explorer 10.
- d3.mouse() returns incorrect X,Y mouse coordinates when mouse moving
- over a rect in IE 10.
- However, d3.event.offsetX/Y also returns the mouse coordinates
- relative to the triggering <rect>. So we use offsetX/Y on IE.
- */
- mouseX = d3.event.offsetX;
- mouseY = d3.event.offsetY;
-
- /*
- On IE, if you attach a mouse event listener to the <svg> container,
- it will actually trigger it for all the child elements (like <path>, <circle>, etc).
- When this happens on IE, the offsetX/Y is set to where ever the child element
- is located.
- As a result, we do NOT need to subtract margins to figure out the mouse X/Y
- position under this scenario. Removing the line below *will* cause
- the interactive layer to not work right on IE.
- */
- if(d3.event.target.tagName !== "svg") {
- subtractMargin = false;
- }
-
- if (d3.event.target.className.baseVal.match("nv-legend")) {
- mouseOutAnyReason = true;
- }
-
- }
-
- if(subtractMargin) {
- mouseX -= margin.left;
- mouseY -= margin.top;
- }
-
- /* If mouseX/Y is outside of the chart's bounds,
- trigger a mouseOut event.
- */
- if (mouseX < 0 || mouseY < 0
- || mouseX > availableWidth || mouseY > availableHeight
- || (d3.event.relatedTarget && d3.event.relatedTarget.ownerSVGElement === undefined)
- || mouseOutAnyReason
- ) {
-
- if (isMSIE) {
- if (d3.event.relatedTarget
- && d3.event.relatedTarget.ownerSVGElement === undefined
- && (d3.event.relatedTarget.className === undefined
- || d3.event.relatedTarget.className.match(tooltip.nvPointerEventsClass))) {
-
- return;
- }
- }
- dispatch.elementMouseout({
- mouseX: mouseX,
- mouseY: mouseY
- });
- layer.renderGuideLine(null); //hide the guideline
- tooltip.hidden(true);
- return;
- } else {
- tooltip.hidden(false);
- }
-
- var pointXValue = xScale.invert(mouseX);
- dispatch.elementMousemove({
- mouseX: mouseX,
- mouseY: mouseY,
- pointXValue: pointXValue
- });
-
- //If user double clicks the layer, fire a elementDblclick
- if (d3.event.type === "dblclick") {
- dispatch.elementDblclick({
- mouseX: mouseX,
- mouseY: mouseY,
- pointXValue: pointXValue
- });
- }
-
- // if user single clicks the layer, fire elementClick
- if (d3.event.type === 'click') {
- dispatch.elementClick({
- mouseX: mouseX,
- mouseY: mouseY,
- pointXValue: pointXValue
- });
- }
- }
-
- svgContainer
- .on("touchmove",mouseHandler)
- .on("mousemove",mouseHandler, true)
- .on("mouseout" ,mouseHandler,true)
- .on("dblclick" ,mouseHandler)
- .on("click", mouseHandler)
- ;
-
- layer.guideLine = null;
- //Draws a vertical guideline at the given X postion.
- layer.renderGuideLine = function(x) {
- if (!showGuideLine) return;
- if (layer.guideLine && layer.guideLine.attr("x1") === x) return;
- nv.dom.write(function() {
- var line = wrap.select(".nv-interactiveGuideLine")
- .selectAll("line")
- .data((x != null) ? [nv.utils.NaNtoZero(x)] : [], String);
- line.enter()
- .append("line")
- .attr("class", "nv-guideline")
- .attr("x1", function(d) { return d;})
- .attr("x2", function(d) { return d;})
- .attr("y1", availableHeight)
- .attr("y2",0);
- line.exit().remove();
- });
- }
- });
- }
-
- layer.dispatch = dispatch;
- layer.tooltip = tooltip;
-
- layer.margin = function(_) {
- if (!arguments.length) return margin;
- margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
- margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
- return layer;
- };
-
- layer.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return layer;
- };
-
- layer.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return layer;
- };
-
- layer.xScale = function(_) {
- if (!arguments.length) return xScale;
- xScale = _;
- return layer;
- };
-
- layer.showGuideLine = function(_) {
- if (!arguments.length) return showGuideLine;
- showGuideLine = _;
- return layer;
- };
-
- layer.svgContainer = function(_) {
- if (!arguments.length) return svgContainer;
- svgContainer = _;
- return layer;
- };
-
- return layer;
-};
-
-/* Utility class that uses d3.bisect to find the index in a given array, where a search value can be inserted.
- This is different from normal bisectLeft; this function finds the nearest index to insert the search value.
-
- For instance, lets say your array is [1,2,3,5,10,30], and you search for 28.
- Normal d3.bisectLeft will return 4, because 28 is inserted after the number 10. But interactiveBisect will return 5
- because 28 is closer to 30 than 10.
-
- Unit tests can be found in: interactiveBisectTest.html
-
- Has the following known issues:
- * Will not work if the data points move backwards (ie, 10,9,8,7, etc) or if the data points are in random order.
- * Won't work if there are duplicate x coordinate values.
- */
-nv.interactiveBisect = function (values, searchVal, xAccessor) {
- "use strict";
- if (! (values instanceof Array)) {
- return null;
- }
- var _xAccessor;
- if (typeof xAccessor !== 'function') {
- _xAccessor = function(d) {
- return d.x;
- }
- } else {
- _xAccessor = xAccessor;
- }
- var _cmp = function(d, v) {
- // Accessors are no longer passed the index of the element along with
- // the element itself when invoked by d3.bisector.
- //
- // Starting at D3 v3.4.4, d3.bisector() started inspecting the
- // function passed to determine if it should consider it an accessor
- // or a comparator. This meant that accessors that take two arguments
- // (expecting an index as the second parameter) are treated as
- // comparators where the second argument is the search value against
- // which the first argument is compared.
- return _xAccessor(d) - v;
- };
-
- var bisect = d3.bisector(_cmp).left;
- var index = d3.max([0, bisect(values,searchVal) - 1]);
- var currentValue = _xAccessor(values[index]);
-
- if (typeof currentValue === 'undefined') {
- currentValue = index;
- }
-
- if (currentValue === searchVal) {
- return index; //found exact match
- }
-
- var nextIndex = d3.min([index+1, values.length - 1]);
- var nextValue = _xAccessor(values[nextIndex]);
-
- if (typeof nextValue === 'undefined') {
- nextValue = nextIndex;
- }
-
- if (Math.abs(nextValue - searchVal) >= Math.abs(currentValue - searchVal)) {
- return index;
- } else {
- return nextIndex
- }
-};
-
-/*
- Returns the index in the array "values" that is closest to searchVal.
- Only returns an index if searchVal is within some "threshold".
- Otherwise, returns null.
- */
-nv.nearestValueIndex = function (values, searchVal, threshold) {
- "use strict";
- var yDistMax = Infinity, indexToHighlight = null;
- values.forEach(function(d,i) {
- var delta = Math.abs(searchVal - d);
- if ( d != null && delta <= yDistMax && delta < threshold) {
- yDistMax = delta;
- indexToHighlight = i;
- }
- });
- return indexToHighlight;
-};
-/* Tooltip rendering model for nvd3 charts.
- window.nv.models.tooltip is the updated,new way to render tooltips.
-
- window.nv.tooltip.show is the old tooltip code.
- window.nv.tooltip.* also has various helper methods.
- */
-(function() {
- "use strict";
-
- /* Model which can be instantiated to handle tooltip rendering.
- Example usage:
- var tip = nv.models.tooltip().gravity('w').distance(23)
- .data(myDataObject);
-
- tip(); //just invoke the returned function to render tooltip.
- */
- nv.models.tooltip = function() {
-
- /*
- Tooltip data. If data is given in the proper format, a consistent tooltip is generated.
- Example Format of data:
- {
- key: "Date",
- value: "August 2009",
- series: [
- {key: "Series 1", value: "Value 1", color: "#000"},
- {key: "Series 2", value: "Value 2", color: "#00f"}
- ]
- }
- */
- var data = null;
- var gravity = 'w' //Can be 'n','s','e','w'. Determines how tooltip is positioned.
- , distance = 25 //Distance to offset tooltip from the mouse location.
- , snapDistance = 0 //Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect)
- , fixedTop = null //If not null, this fixes the top position of the tooltip.
- , classes = null //Attaches additional CSS classes to the tooltip DIV that is created.
- , chartContainer = null //Parent dom element of the SVG that holds the chart.
- , hidden = true // start off hidden, toggle with hide/show functions below
- , hideDelay = 400 // delay before the tooltip hides after calling hide()
- , tooltip = null // d3 select of tooltipElem below
- , tooltipElem = null //actual DOM element representing the tooltip.
- , position = {left: null, top: null} //Relative position of the tooltip inside chartContainer.
- , offset = {left: 0, top: 0} //Offset of tooltip against the pointer
- , enabled = true //True -> tooltips are rendered. False -> don't render tooltips.
- , duration = 100 // duration for tooltip movement
- , headerEnabled = true
- ;
-
- // set to true by interactive layer to adjust tooltip positions
- // eventually we should probably fix interactive layer to get the position better.
- // for now this is needed if you want to set chartContainer for normal tooltips, else it "fixes" it to broken
- var isInteractiveLayer = false;
-
- //Generates a unique id when you create a new tooltip() object
- var id = "nvtooltip-" + Math.floor(Math.random() * 100000);
-
- //CSS class to specify whether element should not have mouse events.
- var nvPointerEventsClass = "nv-pointer-events-none";
-
- //Format function for the tooltip values column
- var valueFormatter = function(d,i) {
- return d;
- };
-
- //Format function for the tooltip header value.
- var headerFormatter = function(d) {
- return d;
- };
-
- var keyFormatter = function(d, i) {
- return d;
- };
-
- //By default, the tooltip model renders a beautiful table inside a DIV.
- //You can override this function if a custom tooltip is desired.
- var contentGenerator = function(d) {
- if (d === null) {
- return '';
- }
-
- var table = d3.select(document.createElement("table"));
- if (headerEnabled) {
- var theadEnter = table.selectAll("thead")
- .data([d])
- .enter().append("thead");
-
- theadEnter.append("tr")
- .append("td")
- .attr("colspan", 3)
- .append("strong")
- .classed("x-value", true)
- .html(headerFormatter(d.value));
- }
-
- var tbodyEnter = table.selectAll("tbody")
- .data([d])
- .enter().append("tbody");
-
- var trowEnter = tbodyEnter.selectAll("tr")
- .data(function(p) { return p.series})
- .enter()
- .append("tr")
- .classed("highlight", function(p) { return p.highlight});
-
- trowEnter.append("td")
- .classed("legend-color-guide",true)
- .append("div")
- .style("background-color", function(p) { return p.color});
-
- trowEnter.append("td")
- .classed("key",true)
- .html(function(p, i) {return keyFormatter(p.key, i)});
-
- trowEnter.append("td")
- .classed("value",true)
- .html(function(p, i) { return valueFormatter(p.value, i) });
-
-
- trowEnter.selectAll("td").each(function(p) {
- if (p.highlight) {
- var opacityScale = d3.scale.linear().domain([0,1]).range(["#fff",p.color]);
- var opacity = 0.6;
- d3.select(this)
- .style("border-bottom-color", opacityScale(opacity))
- .style("border-top-color", opacityScale(opacity))
- ;
- }
- });
-
- var html = table.node().outerHTML;
- if (d.footer !== undefined)
- html += "<div class='footer'>" + d.footer + "</div>";
- return html;
-
- };
-
- var dataSeriesExists = function(d) {
- if (d && d.series) {
- if (d.series instanceof Array) {
- return !!d.series.length;
- }
- // if object, it's okay just convert to array of the object
- if (d.series instanceof Object) {
- d.series = [d.series];
- return true;
- }
- }
- return false;
- };
-
- var calcTooltipPosition = function(pos) {
- if (!tooltipElem) return;
-
- nv.dom.read(function() {
- var height = parseInt(tooltipElem.offsetHeight, 10),
- width = parseInt(tooltipElem.offsetWidth, 10),
- windowWidth = nv.utils.windowSize().width,
- windowHeight = nv.utils.windowSize().height,
- scrollTop = window.pageYOffset,
- scrollLeft = window.pageXOffset,
- left, top;
-
- windowHeight = window.innerWidth >= document.body.scrollWidth ? windowHeight : windowHeight - 16;
- windowWidth = window.innerHeight >= document.body.scrollHeight ? windowWidth : windowWidth - 16;
-
-
- //Helper functions to find the total offsets of a given DOM element.
- //Looks up the entire ancestry of an element, up to the first relatively positioned element.
- var tooltipTop = function ( Elem ) {
- var offsetTop = top;
- do {
- if( !isNaN( Elem.offsetTop ) ) {
- offsetTop += (Elem.offsetTop);
- }
- Elem = Elem.offsetParent;
- } while( Elem );
- return offsetTop;
- };
- var tooltipLeft = function ( Elem ) {
- var offsetLeft = left;
- do {
- if( !isNaN( Elem.offsetLeft ) ) {
- offsetLeft += (Elem.offsetLeft);
- }
- Elem = Elem.offsetParent;
- } while( Elem );
- return offsetLeft;
- };
-
- // calculate position based on gravity
- var tLeft, tTop;
- switch (gravity) {
- case 'e':
- left = pos[0] - width - distance;
- top = pos[1] - (height / 2);
- tLeft = tooltipLeft(tooltipElem);
- tTop = tooltipTop(tooltipElem);
- if (tLeft < scrollLeft) left = pos[0] + distance > scrollLeft ? pos[0] + distance : scrollLeft - tLeft + left;
- if (tTop < scrollTop) top = scrollTop - tTop + top;
- if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;
- break;
- case 'w':
- left = pos[0] + distance;
- top = pos[1] - (height / 2);
- tLeft = tooltipLeft(tooltipElem);
- tTop = tooltipTop(tooltipElem);
- if (tLeft + width > windowWidth) left = pos[0] - width - distance;
- if (tTop < scrollTop) top = scrollTop + 5;
- if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;
- break;
- case 'n':
- left = pos[0] - (width / 2) - 5;
- top = pos[1] + distance;
- tLeft = tooltipLeft(tooltipElem);
- tTop = tooltipTop(tooltipElem);
- if (tLeft < scrollLeft) left = scrollLeft + 5;
- if (tLeft + width > windowWidth) left = left - width/2 + 5;
- if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;
- break;
- case 's':
- left = pos[0] - (width / 2);
- top = pos[1] - height - distance;
- tLeft = tooltipLeft(tooltipElem);
- tTop = tooltipTop(tooltipElem);
- if (tLeft < scrollLeft) left = scrollLeft + 5;
- if (tLeft + width > windowWidth) left = left - width/2 + 5;
- if (scrollTop > tTop) top = scrollTop;
- break;
- case 'none':
- left = pos[0];
- top = pos[1] - distance;
- tLeft = tooltipLeft(tooltipElem);
- tTop = tooltipTop(tooltipElem);
- break;
- }
-
- // adjust tooltip offsets
- left -= offset.left;
- top -= offset.top;
-
- // using tooltip.style('transform') returns values un-usable for tween
- var box = tooltipElem.getBoundingClientRect();
- var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
- var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
- var old_translate = 'translate(' + (box.left + scrollLeft) + 'px, ' + (box.top + scrollTop) + 'px)';
- var new_translate = 'translate(' + left + 'px, ' + top + 'px)';
- var translateInterpolator = d3.interpolateString(old_translate, new_translate);
-
- var is_hidden = tooltip.style('opacity') < 0.1;
-
- // delay hiding a bit to avoid flickering
- if (hidden) {
- tooltip
- .transition()
- .delay(hideDelay)
- .duration(0)
- .style('opacity', 0);
- } else {
- tooltip
- .interrupt() // cancel running transitions
- .transition()
- .duration(is_hidden ? 0 : duration)
- // using tween since some versions of d3 can't auto-tween a translate on a div
- .styleTween('transform', function (d) {
- return translateInterpolator;
- }, 'important')
- // Safari has its own `-webkit-transform` and does not support `transform`
- // transform tooltip without transition only in Safari
- .style('-webkit-transform', new_translate)
- .style('opacity', 1);
- }
-
-
-
- });
- };
-
- //In situations where the chart is in a 'viewBox', re-position the tooltip based on how far chart is zoomed.
- function convertViewBoxRatio() {
- if (chartContainer) {
- var svg = d3.select(chartContainer);
- if (svg.node().tagName !== "svg") {
- svg = svg.select("svg");
- }
- var viewBox = (svg.node()) ? svg.attr('viewBox') : null;
- if (viewBox) {
- viewBox = viewBox.split(' ');
- var ratio = parseInt(svg.style('width'), 10) / viewBox[2];
-
- position.left = position.left * ratio;
- position.top = position.top * ratio;
- }
- }
- }
-
- //Creates new tooltip container, or uses existing one on DOM.
- function initTooltip() {
- if (!tooltip) {
- var body;
- if (chartContainer) {
- body = chartContainer;
- } else {
- body = document.body;
- }
- //Create new tooltip div if it doesn't exist on DOM.
- tooltip = d3.select(body).append("div")
- .attr("class", "nvtooltip " + (classes ? classes : "xy-tooltip"))
- .attr("id", id);
- tooltip.style("top", 0).style("left", 0);
- tooltip.style('opacity', 0);
- tooltip.selectAll("div, table, td, tr").classed(nvPointerEventsClass, true);
- tooltip.classed(nvPointerEventsClass, true);
- tooltipElem = tooltip.node();
- }
- }
-
- //Draw the tooltip onto the DOM.
- function nvtooltip() {
- if (!enabled) return;
- if (!dataSeriesExists(data)) return;
-
- convertViewBoxRatio();
-
- var left = position.left;
- var top = (fixedTop !== null) ? fixedTop : position.top;
-
- nv.dom.write(function () {
- initTooltip();
- // generate data and set it into tooltip
- // Bonus - If you override contentGenerator and return falsey you can use something like
- // React or Knockout to bind the data for your tooltip
- var newContent = contentGenerator(data);
- if (newContent) {
- tooltipElem.innerHTML = newContent;
- }
-
- if (chartContainer && isInteractiveLayer) {
- nv.dom.read(function() {
- var svgComp = chartContainer.getElementsByTagName("svg")[0];
- var svgOffset = {left:0,top:0};
- if (svgComp) {
- var svgBound = svgComp.getBoundingClientRect();
- var chartBound = chartContainer.getBoundingClientRect();
- var svgBoundTop = svgBound.top;
-
- //Defensive code. Sometimes, svgBoundTop can be a really negative
- // number, like -134254. That's a bug.
- // If such a number is found, use zero instead. FireFox bug only
- if (svgBoundTop < 0) {
- var containerBound = chartContainer.getBoundingClientRect();
- svgBoundTop = (Math.abs(svgBoundTop) > containerBound.height) ? 0 : svgBoundTop;
- }
- svgOffset.top = Math.abs(svgBoundTop - chartBound.top);
- svgOffset.left = Math.abs(svgBound.left - chartBound.left);
- }
- //If the parent container is an overflow <div> with scrollbars, subtract the scroll offsets.
- //You need to also add any offset between the <svg> element and its containing <div>
- //Finally, add any offset of the containing <div> on the whole page.
- left += chartContainer.offsetLeft + svgOffset.left - 2*chartContainer.scrollLeft;
- top += chartContainer.offsetTop + svgOffset.top - 2*chartContainer.scrollTop;
-
- if (snapDistance && snapDistance > 0) {
- top = Math.floor(top/snapDistance) * snapDistance;
- }
- calcTooltipPosition([left,top]);
- });
- } else {
- calcTooltipPosition([left,top]);
- }
- });
-
- return nvtooltip;
- }
-
- nvtooltip.nvPointerEventsClass = nvPointerEventsClass;
- nvtooltip.options = nv.utils.optionsFunc.bind(nvtooltip);
-
- nvtooltip._options = Object.create({}, {
- // simple read/write options
- duration: {get: function(){return duration;}, set: function(_){duration=_;}},
- gravity: {get: function(){return gravity;}, set: function(_){gravity=_;}},
- distance: {get: function(){return distance;}, set: function(_){distance=_;}},
- snapDistance: {get: function(){return snapDistance;}, set: function(_){snapDistance=_;}},
- classes: {get: function(){return classes;}, set: function(_){classes=_;}},
- chartContainer: {get: function(){return chartContainer;}, set: function(_){chartContainer=_;}},
- fixedTop: {get: function(){return fixedTop;}, set: function(_){fixedTop=_;}},
- enabled: {get: function(){return enabled;}, set: function(_){enabled=_;}},
- hideDelay: {get: function(){return hideDelay;}, set: function(_){hideDelay=_;}},
- contentGenerator: {get: function(){return contentGenerator;}, set: function(_){contentGenerator=_;}},
- valueFormatter: {get: function(){return valueFormatter;}, set: function(_){valueFormatter=_;}},
- headerFormatter: {get: function(){return headerFormatter;}, set: function(_){headerFormatter=_;}},
- keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}},
- headerEnabled: {get: function(){return headerEnabled;}, set: function(_){headerEnabled=_;}},
-
- // internal use only, set by interactive layer to adjust position.
- _isInteractiveLayer: {get: function(){return isInteractiveLayer;}, set: function(_){isInteractiveLayer=!!_;}},
-
- // options with extra logic
- position: {get: function(){return position;}, set: function(_){
- position.left = _.left !== undefined ? _.left : position.left;
- position.top = _.top !== undefined ? _.top : position.top;
- }},
- offset: {get: function(){return offset;}, set: function(_){
- offset.left = _.left !== undefined ? _.left : offset.left;
- offset.top = _.top !== undefined ? _.top : offset.top;
- }},
- hidden: {get: function(){return hidden;}, set: function(_){
- if (hidden != _) {
- hidden = !!_;
- nvtooltip();
- }
- }},
- data: {get: function(){return data;}, set: function(_){
- // if showing a single data point, adjust data format with that
- if (_.point) {
- _.value = _.point.x;
- _.series = _.series || {};
- _.series.value = _.point.y;
- _.series.color = _.point.color || _.series.color;
- }
- data = _;
- }},
-
- // read only properties
- tooltipElem: {get: function(){return tooltipElem;}, set: function(_){}},
- id: {get: function(){return id;}, set: function(_){}}
- });
-
- nv.utils.initOptions(nvtooltip);
- return nvtooltip;
- };
-
-})();
-
-
-/*
-Gets the browser window size
-
-Returns object with height and width properties
- */
-nv.utils.windowSize = function() {
- // Sane defaults
- var size = {width: 640, height: 480};
-
- // Most recent browsers use
- if (window.innerWidth && window.innerHeight) {
- size.width = window.innerWidth;
- size.height = window.innerHeight;
- return (size);
- }
-
- // IE can use depending on mode it is in
- if (document.compatMode=='CSS1Compat' &&
- document.documentElement &&
- document.documentElement.offsetWidth ) {
-
- size.width = document.documentElement.offsetWidth;
- size.height = document.documentElement.offsetHeight;
- return (size);
- }
-
- // Earlier IE uses Doc.body
- if (document.body && document.body.offsetWidth) {
- size.width = document.body.offsetWidth;
- size.height = document.body.offsetHeight;
- return (size);
- }
-
- return (size);
-};
-
-/*
-Binds callback function to run when window is resized
- */
-nv.utils.windowResize = function(handler) {
- if (window.addEventListener) {
- window.addEventListener('resize', handler);
- } else {
- nv.log("ERROR: Failed to bind to window.resize with: ", handler);
- }
- // return object with clear function to remove the single added callback.
- return {
- callback: handler,
- clear: function() {
- window.removeEventListener('resize', handler);
- }
- }
-};
-
-
-/*
-Backwards compatible way to implement more d3-like coloring of graphs.
-Can take in nothing, an array, or a function/scale
-To use a normal scale, get the range and pass that because we must be able
-to take two arguments and use the index to keep backward compatibility
-*/
-nv.utils.getColor = function(color) {
- //if you pass in nothing, get default colors back
- if (color === undefined) {
- return nv.utils.defaultColor();
-
- //if passed an array, turn it into a color scale
- // use isArray, instanceof fails if d3 range is created in an iframe
- } else if(Array.isArray(color)) {
- var color_scale = d3.scale.ordinal().range(color);
- return function(d, i) {
- var key = i === undefined ? d : i;
- return d.color || color_scale(key);
- };
-
- //if passed a function or scale, return it, or whatever it may be
- //external libs, such as angularjs-nvd3-directives use this
- } else {
- //can't really help it if someone passes rubbish as color
- return color;
- }
-};
-
-
-/*
-Default color chooser uses a color scale of 20 colors from D3
- https://github.com/mbostock/d3/wiki/Ordinal-Scales#categorical-colors
- */
-nv.utils.defaultColor = function() {
- // get range of the scale so we'll turn it into our own function.
- return nv.utils.getColor(d3.scale.category20().range());
-};
-
-
-/*
-Returns a color function that takes the result of 'getKey' for each series and
-looks for a corresponding color from the dictionary
-*/
-nv.utils.customTheme = function(dictionary, getKey, defaultColors) {
- // use default series.key if getKey is undefined
- getKey = getKey || function(series) { return series.key };
- defaultColors = defaultColors || d3.scale.category20().range();
-
- // start at end of default color list and walk back to index 0
- var defIndex = defaultColors.length;
-
- return function(series, index) {
- var key = getKey(series);
- if (typeof dictionary[key] === 'function') {
- return dictionary[key]();
- } else if (dictionary[key] !== undefined) {
- return dictionary[key];
- } else {
- // no match in dictionary, use a default color
- if (!defIndex) {
- // used all the default colors, start over
- defIndex = defaultColors.length;
- }
- defIndex = defIndex - 1;
- return defaultColors[defIndex];
- }
- };
-};
-
-
-/*
-From the PJAX example on d3js.org, while this is not really directly needed
-it's a very cool method for doing pjax, I may expand upon it a little bit,
-open to suggestions on anything that may be useful
-*/
-nv.utils.pjax = function(links, content) {
-
- var load = function(href) {
- d3.html(href, function(fragment) {
- var target = d3.select(content).node();
- target.parentNode.replaceChild(
- d3.select(fragment).select(content).node(),
- target);
- nv.utils.pjax(links, content);
- });
- };
-
- d3.selectAll(links).on("click", function() {
- history.pushState(this.href, this.textContent, this.href);
- load(this.href);
- d3.event.preventDefault();
- });
-
- d3.select(window).on("popstate", function() {
- if (d3.event.state) {
- load(d3.event.state);
- }
- });
-};
-
-
-/*
-For when we want to approximate the width in pixels for an SVG:text element.
-Most common instance is when the element is in a display:none; container.
-Forumla is : text.length * font-size * constant_factor
-*/
-nv.utils.calcApproxTextWidth = function (svgTextElem) {
- if (typeof svgTextElem.style === 'function'
- && typeof svgTextElem.text === 'function') {
-
- var fontSize = parseInt(svgTextElem.style("font-size").replace("px",""), 10);
- var textLength = svgTextElem.text().length;
- return textLength * fontSize * 0.5;
- }
- return 0;
-};
-
-
-/*
-Numbers that are undefined, null or NaN, convert them to zeros.
-*/
-nv.utils.NaNtoZero = function(n) {
- if (typeof n !== 'number'
- || isNaN(n)
- || n === null
- || n === Infinity
- || n === -Infinity) {
-
- return 0;
- }
- return n;
-};
-
-/*
-Add a way to watch for d3 transition ends to d3
-*/
-d3.selection.prototype.watchTransition = function(renderWatch){
- var args = [this].concat([].slice.call(arguments, 1));
- return renderWatch.transition.apply(renderWatch, args);
-};
-
-
-/*
-Helper object to watch when d3 has rendered something
-*/
-nv.utils.renderWatch = function(dispatch, duration) {
- if (!(this instanceof nv.utils.renderWatch)) {
- return new nv.utils.renderWatch(dispatch, duration);
- }
-
- var _duration = duration !== undefined ? duration : 250;
- var renderStack = [];
- var self = this;
-
- this.models = function(models) {
- models = [].slice.call(arguments, 0);
- models.forEach(function(model){
- model.__rendered = false;
- (function(m){
- m.dispatch.on('renderEnd', function(arg){
- m.__rendered = true;
- self.renderEnd('model');
- });
- })(model);
-
- if (renderStack.indexOf(model) < 0) {
- renderStack.push(model);
- }
- });
- return this;
- };
-
- this.reset = function(duration) {
- if (duration !== undefined) {
- _duration = duration;
- }
- renderStack = [];
- };
-
- this.transition = function(selection, args, duration) {
- args = arguments.length > 1 ? [].slice.call(arguments, 1) : [];
-
- if (args.length > 1) {
- duration = args.pop();
- } else {
- duration = _duration !== undefined ? _duration : 250;
- }
- selection.__rendered = false;
-
- if (renderStack.indexOf(selection) < 0) {
- renderStack.push(selection);
- }
-
- if (duration === 0) {
- selection.__rendered = true;
- selection.delay = function() { return this; };
- selection.duration = function() { return this; };
- return selection;
- } else {
- if (selection.length === 0) {
- selection.__rendered = true;
- } else if (selection.every( function(d){ return !d.length; } )) {
- selection.__rendered = true;
- } else {
- selection.__rendered = false;
- }
-
- var n = 0;
- return selection
- .transition()
- .duration(duration)
- .each(function(){ ++n; })
- .each('end', function(d, i) {
- if (--n === 0) {
- selection.__rendered = true;
- self.renderEnd.apply(this, args);
- }
- });
- }
- };
-
- this.renderEnd = function() {
- if (renderStack.every( function(d){ return d.__rendered; } )) {
- renderStack.forEach( function(d){ d.__rendered = false; });
- dispatch.renderEnd.apply(this, arguments);
- }
- }
-
-};
-
-
-/*
-Takes multiple objects and combines them into the first one (dst)
-example: nv.utils.deepExtend({a: 1}, {a: 2, b: 3}, {c: 4});
-gives: {a: 2, b: 3, c: 4}
-*/
-nv.utils.deepExtend = function(dst){
- var sources = arguments.length > 1 ? [].slice.call(arguments, 1) : [];
- sources.forEach(function(source) {
- for (var key in source) {
- var isArray = dst[key] instanceof Array;
- var isObject = typeof dst[key] === 'object';
- var srcObj = typeof source[key] === 'object';
-
- if (isObject && !isArray && srcObj) {
- nv.utils.deepExtend(dst[key], source[key]);
- } else {
- dst[key] = source[key];
- }
- }
- });
-};
-
-
-/*
-state utility object, used to track d3 states in the models
-*/
-nv.utils.state = function(){
- if (!(this instanceof nv.utils.state)) {
- return new nv.utils.state();
- }
- var state = {};
- var _self = this;
- var _setState = function(){};
- var _getState = function(){ return {}; };
- var init = null;
- var changed = null;
-
- this.dispatch = d3.dispatch('change', 'set');
-
- this.dispatch.on('set', function(state){
- _setState(state, true);
- });
-
- this.getter = function(fn){
- _getState = fn;
- return this;
- };
-
- this.setter = function(fn, callback) {
- if (!callback) {
- callback = function(){};
- }
- _setState = function(state, update){
- fn(state);
- if (update) {
- callback();
- }
- };
- return this;
- };
-
- this.init = function(state){
- init = init || {};
- nv.utils.deepExtend(init, state);
- };
-
- var _set = function(){
- var settings = _getState();
-
- if (JSON.stringify(settings) === JSON.stringify(state)) {
- return false;
- }
-
- for (var key in settings) {
- if (state[key] === undefined) {
- state[key] = {};
- }
- state[key] = settings[key];
- changed = true;
- }
- return true;
- };
-
- this.update = function(){
- if (init) {
- _setState(init, false);
- init = null;
- }
- if (_set.call(this)) {
- this.dispatch.change(state);
- }
- };
-
-};
-
-
-/*
-Snippet of code you can insert into each nv.models.* to give you the ability to
-do things like:
-chart.options({
- showXAxis: true,
- tooltips: true
-});
-
-To enable in the chart:
-chart.options = nv.utils.optionsFunc.bind(chart);
-*/
-nv.utils.optionsFunc = function(args) {
- if (args) {
- d3.map(args).forEach((function(key,value) {
- if (typeof this[key] === "function") {
- this[key](value);
- }
- }).bind(this));
- }
- return this;
-};
-
-
-/*
-numTicks: requested number of ticks
-data: the chart data
-
-returns the number of ticks to actually use on X axis, based on chart data
-to avoid duplicate ticks with the same value
-*/
-nv.utils.calcTicksX = function(numTicks, data) {
- // find max number of values from all data streams
- var numValues = 1;
- var i = 0;
- for (i; i < data.length; i += 1) {
- var stream_len = data[i] && data[i].values ? data[i].values.length : 0;
- numValues = stream_len > numValues ? stream_len : numValues;
- }
- nv.log("Requested number of ticks: ", numTicks);
- nv.log("Calculated max values to be: ", numValues);
- // make sure we don't have more ticks than values to avoid duplicates
- numTicks = numTicks > numValues ? numTicks = numValues - 1 : numTicks;
- // make sure we have at least one tick
- numTicks = numTicks < 1 ? 1 : numTicks;
- // make sure it's an integer
- numTicks = Math.floor(numTicks);
- nv.log("Calculating tick count as: ", numTicks);
- return numTicks;
-};
-
-
-/*
-returns number of ticks to actually use on Y axis, based on chart data
-*/
-nv.utils.calcTicksY = function(numTicks, data) {
- // currently uses the same logic but we can adjust here if needed later
- return nv.utils.calcTicksX(numTicks, data);
-};
-
-
-/*
-Add a particular option from an options object onto chart
-Options exposed on a chart are a getter/setter function that returns chart
-on set to mimic typical d3 option chaining, e.g. svg.option1('a').option2('b');
-
-option objects should be generated via Object.create() to provide
-the option of manipulating data via get/set functions.
-*/
-nv.utils.initOption = function(chart, name) {
- // if it's a call option, just call it directly, otherwise do get/set
- if (chart._calls && chart._calls[name]) {
- chart[name] = chart._calls[name];
- } else {
- chart[name] = function (_) {
- if (!arguments.length) return chart._options[name];
- chart._overrides[name] = true;
- chart._options[name] = _;
- return chart;
- };
- // calling the option as _option will ignore if set by option already
- // so nvd3 can set options internally but the stop if set manually
- chart['_' + name] = function(_) {
- if (!arguments.length) return chart._options[name];
- if (!chart._overrides[name]) {
- chart._options[name] = _;
- }
- return chart;
- }
- }
-};
-
-
-/*
-Add all options in an options object to the chart
-*/
-nv.utils.initOptions = function(chart) {
- chart._overrides = chart._overrides || {};
- var ops = Object.getOwnPropertyNames(chart._options || {});
- var calls = Object.getOwnPropertyNames(chart._calls || {});
- ops = ops.concat(calls);
- for (var i in ops) {
- nv.utils.initOption(chart, ops[i]);
- }
-};
-
-
-/*
-Inherit options from a D3 object
-d3.rebind makes calling the function on target actually call it on source
-Also use _d3options so we can track what we inherit for documentation and chained inheritance
-*/
-nv.utils.inheritOptionsD3 = function(target, d3_source, oplist) {
- target._d3options = oplist.concat(target._d3options || []);
- oplist.unshift(d3_source);
- oplist.unshift(target);
- d3.rebind.apply(this, oplist);
-};
-
-
-/*
-Remove duplicates from an array
-*/
-nv.utils.arrayUnique = function(a) {
- return a.sort().filter(function(item, pos) {
- return !pos || item != a[pos - 1];
- });
-};
-
-
-/*
-Keeps a list of custom symbols to draw from in addition to d3.svg.symbol
-Necessary since d3 doesn't let you extend its list -_-
-Add new symbols by doing nv.utils.symbols.set('name', function(size){...});
-*/
-nv.utils.symbolMap = d3.map();
-
-
-/*
-Replaces d3.svg.symbol so that we can look both there and our own map
- */
-nv.utils.symbol = function() {
- var type,
- size = 64;
- function symbol(d,i) {
- var t = type.call(this,d,i);
- var s = size.call(this,d,i);
- if (d3.svg.symbolTypes.indexOf(t) !== -1) {
- return d3.svg.symbol().type(t).size(s)();
- } else {
- return nv.utils.symbolMap.get(t)(s);
- }
- }
- symbol.type = function(_) {
- if (!arguments.length) return type;
- type = d3.functor(_);
- return symbol;
- };
- symbol.size = function(_) {
- if (!arguments.length) return size;
- size = d3.functor(_);
- return symbol;
- };
- return symbol;
-};
-
-
-/*
-Inherit option getter/setter functions from source to target
-d3.rebind makes calling the function on target actually call it on source
-Also track via _inherited and _d3options so we can track what we inherit
-for documentation generation purposes and chained inheritance
-*/
-nv.utils.inheritOptions = function(target, source) {
- // inherit all the things
- var ops = Object.getOwnPropertyNames(source._options || {});
- var calls = Object.getOwnPropertyNames(source._calls || {});
- var inherited = source._inherited || [];
- var d3ops = source._d3options || [];
- var args = ops.concat(calls).concat(inherited).concat(d3ops);
- args.unshift(source);
- args.unshift(target);
- d3.rebind.apply(this, args);
- // pass along the lists to keep track of them, don't allow duplicates
- target._inherited = nv.utils.arrayUnique(ops.concat(calls).concat(inherited).concat(ops).concat(target._inherited || []));
- target._d3options = nv.utils.arrayUnique(d3ops.concat(target._d3options || []));
-};
-
-
-/*
-Runs common initialize code on the svg before the chart builds
-*/
-nv.utils.initSVG = function(svg) {
- svg.classed({'nvd3-svg':true});
-};
-
-
-/*
-Sanitize and provide default for the container height.
-*/
-nv.utils.sanitizeHeight = function(height, container) {
- return (height || parseInt(container.style('height'), 10) || 400);
-};
-
-
-/*
-Sanitize and provide default for the container width.
-*/
-nv.utils.sanitizeWidth = function(width, container) {
- return (width || parseInt(container.style('width'), 10) || 960);
-};
-
-
-/*
-Calculate the available height for a chart.
-*/
-nv.utils.availableHeight = function(height, container, margin) {
- return nv.utils.sanitizeHeight(height, container) - margin.top - margin.bottom;
-};
-
-/*
-Calculate the available width for a chart.
-*/
-nv.utils.availableWidth = function(width, container, margin) {
- return nv.utils.sanitizeWidth(width, container) - margin.left - margin.right;
-};
-
-/*
-Clear any rendered chart components and display a chart's 'noData' message
-*/
-nv.utils.noData = function(chart, container) {
- var opt = chart.options(),
- margin = opt.margin(),
- noData = opt.noData(),
- data = (noData == null) ? ["No Data Available."] : [noData],
- height = nv.utils.availableHeight(opt.height(), container, margin),
- width = nv.utils.availableWidth(opt.width(), container, margin),
- x = margin.left + width/2,
- y = margin.top + height/2;
-
- //Remove any previously created chart components
- container.selectAll('g').remove();
-
- var noDataText = container.selectAll('.nv-noData').data(data);
-
- noDataText.enter().append('text')
- .attr('class', 'nvd3 nv-noData')
- .attr('dy', '-.7em')
- .style('text-anchor', 'middle');
-
- noDataText
- .attr('x', x)
- .attr('y', y)
- .text(function(t){ return t; });
-};
-
-nv.models.axis = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var axis = d3.svg.axis();
- var scale = d3.scale.linear();
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 75 //only used for tickLabel currently
- , height = 60 //only used for tickLabel currently
- , axisLabelText = null
- , showMaxMin = false //TODO: showMaxMin should be disabled on all ordinal scaled axes
- , rotateLabels = 0
- , rotateYLabel = true
- , staggerLabels = false
- , isOrdinal = false
- , ticks = null
- , axisLabelDistance = 0
- , duration = 250
- , dispatch = d3.dispatch('renderEnd')
- ;
- axis
- .scale(scale)
- .orient('bottom')
- .tickFormat(function(d) { return d })
- ;
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var scale0;
- var renderWatch = nv.utils.renderWatch(dispatch, duration);
-
- function chart(selection) {
- renderWatch.reset();
- selection.each(function(data) {
- var container = d3.select(this);
- nv.utils.initSVG(container);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-axis').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-axis');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- if (ticks !== null)
- axis.ticks(ticks);
- else if (axis.orient() == 'top' || axis.orient() == 'bottom')
- axis.ticks(Math.abs(scale.range()[1] - scale.range()[0]) / 100);
-
- //TODO: consider calculating width/height based on whether or not label is added, for reference in charts using this component
- g.watchTransition(renderWatch, 'axis').call(axis);
-
- scale0 = scale0 || axis.scale();
-
- var fmt = axis.tickFormat();
- if (fmt == null) {
- fmt = scale0.tickFormat();
- }
-
- var axisLabel = g.selectAll('text.nv-axislabel')
- .data([axisLabelText || null]);
- axisLabel.exit().remove();
-
- var xLabelMargin;
- var axisMaxMin;
- var w;
- switch (axis.orient()) {
- case 'top':
- axisLabel.enter().append('text').attr('class', 'nv-axislabel');
- if (scale.range().length < 2) {
- w = 0;
- } else if (scale.range().length === 2) {
- w = scale.range()[1];
- } else {
- w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]);
- }
- axisLabel
- .attr('text-anchor', 'middle')
- .attr('y', 0)
- .attr('x', w/2);
- if (showMaxMin) {
- axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
- .data(scale.domain());
- axisMaxMin.enter().append('g').attr('class',function(d,i){
- return ['nv-axisMaxMin','nv-axisMaxMin-x',(i == 0 ? 'nv-axisMin-x':'nv-axisMax-x')].join(' ')
- }).append('text');
- axisMaxMin.exit().remove();
- axisMaxMin
- .attr('transform', function(d,i) {
- return 'translate(' + nv.utils.NaNtoZero(scale(d)) + ',0)'
- })
- .select('text')
- .attr('dy', '-0.5em')
- .attr('y', -axis.tickPadding())
- .attr('text-anchor', 'middle')
- .text(function(d,i) {
- var v = fmt(d);
- return ('' + v).match('NaN') ? '' : v;
- });
- axisMaxMin.watchTransition(renderWatch, 'min-max top')
- .attr('transform', function(d,i) {
- return 'translate(' + nv.utils.NaNtoZero(scale.range()[i]) + ',0)'
- });
- }
- break;
- case 'bottom':
- xLabelMargin = axisLabelDistance + 36;
- var maxTextWidth = 30;
- var textHeight = 0;
- var xTicks = g.selectAll('g').select("text");
- var rotateLabelsRule = '';
- if (rotateLabels%360) {
- //Calculate the longest xTick width
- xTicks.each(function(d,i){
- var box = this.getBoundingClientRect();
- var width = box.width;
- textHeight = box.height;
- if(width > maxTextWidth) maxTextWidth = width;
- });
- rotateLabelsRule = 'rotate(' + rotateLabels + ' 0,' + (textHeight/2 + axis.tickPadding()) + ')';
- //Convert to radians before calculating sin. Add 30 to margin for healthy padding.
- var sin = Math.abs(Math.sin(rotateLabels*Math.PI/180));
- xLabelMargin = (sin ? sin*maxTextWidth : maxTextWidth)+30;
- //Rotate all xTicks
- xTicks
- .attr('transform', rotateLabelsRule)
- .style('text-anchor', rotateLabels%360 > 0 ? 'start' : 'end');
- }
- axisLabel.enter().append('text').attr('class', 'nv-axislabel');
- if (scale.range().length < 2) {
- w = 0;
- } else if (scale.range().length === 2) {
- w = scale.range()[1];
- } else {
- w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]);
- }
- axisLabel
- .attr('text-anchor', 'middle')
- .attr('y', xLabelMargin)
- .attr('x', w/2);
- if (showMaxMin) {
- //if (showMaxMin && !isOrdinal) {
- axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
- //.data(scale.domain())
- .data([scale.domain()[0], scale.domain()[scale.domain().length - 1]]);
- axisMaxMin.enter().append('g').attr('class',function(d,i){
- return ['nv-axisMaxMin','nv-axisMaxMin-x',(i == 0 ? 'nv-axisMin-x':'nv-axisMax-x')].join(' ')
- }).append('text');
- axisMaxMin.exit().remove();
- axisMaxMin
- .attr('transform', function(d,i) {
- return 'translate(' + nv.utils.NaNtoZero((scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0))) + ',0)'
- })
- .select('text')
- .attr('dy', '.71em')
- .attr('y', axis.tickPadding())
- .attr('transform', rotateLabelsRule)
- .style('text-anchor', rotateLabels ? (rotateLabels%360 > 0 ? 'start' : 'end') : 'middle')
- .text(function(d,i) {
- var v = fmt(d);
- return ('' + v).match('NaN') ? '' : v;
- });
- axisMaxMin.watchTransition(renderWatch, 'min-max bottom')
- .attr('transform', function(d,i) {
- return 'translate(' + nv.utils.NaNtoZero((scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0))) + ',0)'
- });
- }
- if (staggerLabels)
- xTicks
- .attr('transform', function(d,i) {
- return 'translate(0,' + (i % 2 == 0 ? '0' : '12') + ')'
- });
-
- break;
- case 'right':
- axisLabel.enter().append('text').attr('class', 'nv-axislabel');
- axisLabel
- .style('text-anchor', rotateYLabel ? 'middle' : 'begin')
- .attr('transform', rotateYLabel ? 'rotate(90)' : '')
- .attr('y', rotateYLabel ? (-Math.max(margin.right, width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
- .attr('x', rotateYLabel ? (d3.max(scale.range()) / 2) : axis.tickPadding());
- if (showMaxMin) {
- axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
- .data(scale.domain());
- axisMaxMin.enter().append('g').attr('class',function(d,i){
- return ['nv-axisMaxMin','nv-axisMaxMin-y',(i == 0 ? 'nv-axisMin-y':'nv-axisMax-y')].join(' ')
- }).append('text')
- .style('opacity', 0);
- axisMaxMin.exit().remove();
- axisMaxMin
- .attr('transform', function(d,i) {
- return 'translate(0,' + nv.utils.NaNtoZero(scale(d)) + ')'
- })
- .select('text')
- .attr('dy', '.32em')
- .attr('y', 0)
- .attr('x', axis.tickPadding())
- .style('text-anchor', 'start')
- .text(function(d, i) {
- var v = fmt(d);
- return ('' + v).match('NaN') ? '' : v;
- });
- axisMaxMin.watchTransition(renderWatch, 'min-max right')
- .attr('transform', function(d,i) {
- return 'translate(0,' + nv.utils.NaNtoZero(scale.range()[i]) + ')'
- })
- .select('text')
- .style('opacity', 1);
- }
- break;
- case 'left':
- /*
- //For dynamically placing the label. Can be used with dynamically-sized chart axis margins
- var yTicks = g.selectAll('g').select("text");
- yTicks.each(function(d,i){
- var labelPadding = this.getBoundingClientRect().width + axis.tickPadding() + 16;
- if(labelPadding > width) width = labelPadding;
- });
- */
- axisLabel.enter().append('text').attr('class', 'nv-axislabel');
- axisLabel
- .style('text-anchor', rotateYLabel ? 'middle' : 'end')
- .attr('transform', rotateYLabel ? 'rotate(-90)' : '')
- .attr('y', rotateYLabel ? (-Math.max(margin.left, width) + 25 - (axisLabelDistance || 0)) : -10)
- .attr('x', rotateYLabel ? (-d3.max(scale.range()) / 2) : -axis.tickPadding());
- if (showMaxMin) {
- axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
- .data(scale.domain());
- axisMaxMin.enter().append('g').attr('class',function(d,i){
- return ['nv-axisMaxMin','nv-axisMaxMin-y',(i == 0 ? 'nv-axisMin-y':'nv-axisMax-y')].join(' ')
- }).append('text')
- .style('opacity', 0);
- axisMaxMin.exit().remove();
- axisMaxMin
- .attr('transform', function(d,i) {
- return 'translate(0,' + nv.utils.NaNtoZero(scale0(d)) + ')'
- })
- .select('text')
- .attr('dy', '.32em')
- .attr('y', 0)
- .attr('x', -axis.tickPadding())
- .attr('text-anchor', 'end')
- .text(function(d,i) {
- var v = fmt(d);
- return ('' + v).match('NaN') ? '' : v;
- });
- axisMaxMin.watchTransition(renderWatch, 'min-max right')
- .attr('transform', function(d,i) {
- return 'translate(0,' + nv.utils.NaNtoZero(scale.range()[i]) + ')'
- })
- .select('text')
- .style('opacity', 1);
- }
- break;
- }
- axisLabel.text(function(d) { return d });
-
- if (showMaxMin && (axis.orient() === 'left' || axis.orient() === 'right')) {
- //check if max and min overlap other values, if so, hide the values that overlap
- g.selectAll('g') // the g's wrapping each tick
- .each(function(d,i) {
- d3.select(this).select('text').attr('opacity', 1);
- if (scale(d) < scale.range()[1] + 10 || scale(d) > scale.range()[0] - 10) { // 10 is assuming text height is 16... if d is 0, leave it!
- if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL
- d3.select(this).attr('opacity', 0);
-
- d3.select(this).select('text').attr('opacity', 0); // Don't remove the ZERO line!!
- }
- });
-
- //if Max and Min = 0 only show min, Issue #281
- if (scale.domain()[0] == scale.domain()[1] && scale.domain()[0] == 0) {
- wrap.selectAll('g.nv-axisMaxMin').style('opacity', function (d, i) {
- return !i ? 1 : 0
- });
- }
- }
-
- if (showMaxMin && (axis.orient() === 'top' || axis.orient() === 'bottom')) {
- var maxMinRange = [];
- wrap.selectAll('g.nv-axisMaxMin')
- .each(function(d,i) {
- try {
- if (i) // i== 1, max position
- maxMinRange.push(scale(d) - this.getBoundingClientRect().width - 4); //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case)
- else // i==0, min position
- maxMinRange.push(scale(d) + this.getBoundingClientRect().width + 4)
- }catch (err) {
- if (i) // i== 1, max position
- maxMinRange.push(scale(d) - 4); //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case)
- else // i==0, min position
- maxMinRange.push(scale(d) + 4);
- }
- });
- // the g's wrapping each tick
- g.selectAll('g').each(function(d, i) {
- if (scale(d) < maxMinRange[0] || scale(d) > maxMinRange[1]) {
- if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL
- d3.select(this).remove();
- else
- d3.select(this).select('text').remove(); // Don't remove the ZERO line!!
- }
- });
- }
-
- //Highlight zero tick line
- g.selectAll('.tick')
- .filter(function (d) {
- /*
- The filter needs to return only ticks at or near zero.
- Numbers like 0.00001 need to count as zero as well,
- and the arithmetic trick below solves that.
- */
- return !parseFloat(Math.round(d * 100000) / 1000000) && (d !== undefined)
- })
- .classed('zero', true);
-
- //store old scales for use in transitions on update
- scale0 = scale.copy();
-
- });
-
- renderWatch.renderEnd('axis immediate');
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.axis = axis;
- chart.dispatch = dispatch;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- axisLabelDistance: {get: function(){return axisLabelDistance;}, set: function(_){axisLabelDistance=_;}},
- staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}},
- rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}},
- rotateYLabel: {get: function(){return rotateYLabel;}, set: function(_){rotateYLabel=_;}},
- showMaxMin: {get: function(){return showMaxMin;}, set: function(_){showMaxMin=_;}},
- axisLabel: {get: function(){return axisLabelText;}, set: function(_){axisLabelText=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- ticks: {get: function(){return ticks;}, set: function(_){ticks=_;}},
- width: {get: function(){return width;}, set: function(_){width=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration=_;
- renderWatch.reset(duration);
- }},
- scale: {get: function(){return scale;}, set: function(_){
- scale = _;
- axis.scale(scale);
- isOrdinal = typeof scale.rangeBands === 'function';
- nv.utils.inheritOptionsD3(chart, scale, ['domain', 'range', 'rangeBand', 'rangeBands']);
- }}
- });
-
- nv.utils.initOptions(chart);
- nv.utils.inheritOptionsD3(chart, axis, ['orient', 'tickValues', 'tickSubdivide', 'tickSize', 'tickPadding', 'tickFormat']);
- nv.utils.inheritOptionsD3(chart, scale, ['domain', 'range', 'rangeBand', 'rangeBands']);
-
- return chart;
-};
-nv.models.boxPlot = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 960
- , height = 500
- , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
- , x = d3.scale.ordinal()
- , y = d3.scale.linear()
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , color = nv.utils.defaultColor()
- , container = null
- , xDomain
- , yDomain
- , xRange
- , yRange
- , dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
- , duration = 250
- , maxBoxWidth = null
- ;
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0;
- var renderWatch = nv.utils.renderWatch(dispatch, duration);
-
- function chart(selection) {
- renderWatch.reset();
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom;
-
- container = d3.select(this);
- nv.utils.initSVG(container);
-
- // Setup Scales
- x .domain(xDomain || data.map(function(d,i) { return getX(d,i); }))
- .rangeBands(xRange || [0, availableWidth], .1);
-
- // if we know yDomain, no need to calculate
- var yData = []
- if (!yDomain) {
- // (y-range is based on quartiles, whiskers and outliers)
-
- // lower values
- var yMin = d3.min(data.map(function(d) {
- var min_arr = [];
-
- min_arr.push(d.values.Q1);
- if (d.values.hasOwnProperty('whisker_low') && d.values.whisker_low !== null) { min_arr.push(d.values.whisker_low); }
- if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { min_arr = min_arr.concat(d.values.outliers); }
-
- return d3.min(min_arr);
- }));
-
- // upper values
- var yMax = d3.max(data.map(function(d) {
- var max_arr = [];
-
- max_arr.push(d.values.Q3);
- if (d.values.hasOwnProperty('whisker_high') && d.values.whisker_high !== null) { max_arr.push(d.values.whisker_high); }
- if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { max_arr = max_arr.concat(d.values.outliers); }
-
- return d3.max(max_arr);
- }));
-
- yData = [ yMin, yMax ] ;
- }
-
- y.domain(yDomain || yData);
- y.range(yRange || [availableHeight, 0]);
-
- //store old scales if they exist
- x0 = x0 || x;
- y0 = y0 || y.copy().range([y(0),y(0)]);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap');
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- var boxplots = wrap.selectAll('.nv-boxplot').data(function(d) { return d });
- var boxEnter = boxplots.enter().append('g').style('stroke-opacity', 1e-6).style('fill-opacity', 1e-6);
- boxplots
- .attr('class', 'nv-boxplot')
- .attr('transform', function(d,i,j) { return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05) + ', 0)'; })
- .classed('hover', function(d) { return d.hover });
- boxplots
- .watchTransition(renderWatch, 'nv-boxplot: boxplots')
- .style('stroke-opacity', 1)
- .style('fill-opacity', .75)
- .delay(function(d,i) { return i * duration / data.length })
- .attr('transform', function(d,i) {
- return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05) + ', 0)';
- });
- boxplots.exit().remove();
-
- // ----- add the SVG elements for each boxPlot -----
-
- // conditionally append whisker lines
- boxEnter.each(function(d,i) {
- var box = d3.select(this);
-
- ['low', 'high'].forEach(function(key) {
- if (d.values.hasOwnProperty('whisker_' + key) && d.values['whisker_' + key] !== null) {
- box.append('line')
- .style('stroke', (d.color) ? d.color : color(d,i))
- .attr('class', 'nv-boxplot-whisker nv-boxplot-' + key);
-
- box.append('line')
- .style('stroke', (d.color) ? d.color : color(d,i))
- .attr('class', 'nv-boxplot-tick nv-boxplot-' + key);
- }
- });
- });
-
- // outliers
- // TODO: support custom colors here
- var outliers = boxplots.selectAll('.nv-boxplot-outlier').data(function(d) {
- if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { return d.values.outliers; }
- else { return []; }
- });
- outliers.enter().append('circle')
- .style('fill', function(d,i,j) { return color(d,j) }).style('stroke', function(d,i,j) { return color(d,j) })
- .on('mouseover', function(d,i,j) {
- d3.select(this).classed('hover', true);
- dispatch.elementMouseover({
- series: { key: d, color: color(d,j) },
- e: d3.event
- });
- })
- .on('mouseout', function(d,i,j) {
- d3.select(this).classed('hover', false);
- dispatch.elementMouseout({
- series: { key: d, color: color(d,j) },
- e: d3.event
- });
- })
- .on('mousemove', function(d,i) {
- dispatch.elementMousemove({e: d3.event});
- });
-
- outliers.attr('class', 'nv-boxplot-outlier');
- outliers
- .watchTransition(renderWatch, 'nv-boxplot: nv-boxplot-outlier')
- .attr('cx', x.rangeBand() * .45)
- .attr('cy', function(d,i,j) { return y(d); })
- .attr('r', '3');
- outliers.exit().remove();
-
- var box_width = function() { return (maxBoxWidth === null ? x.rangeBand() * .9 : Math.min(75, x.rangeBand() * .9)); };
- var box_left = function() { return x.rangeBand() * .45 - box_width()/2; };
- var box_right = function() { return x.rangeBand() * .45 + box_width()/2; };
-
- // update whisker lines and ticks
- ['low', 'high'].forEach(function(key) {
- var endpoint = (key === 'low') ? 'Q1' : 'Q3';
-
- boxplots.select('line.nv-boxplot-whisker.nv-boxplot-' + key)
- .watchTransition(renderWatch, 'nv-boxplot: boxplots')
- .attr('x1', x.rangeBand() * .45 )
- .attr('y1', function(d,i) { return y(d.values['whisker_' + key]); })
- .attr('x2', x.rangeBand() * .45 )
- .attr('y2', function(d,i) { return y(d.values[endpoint]); });
-
- boxplots.select('line.nv-boxplot-tick.nv-boxplot-' + key)
- .watchTransition(renderWatch, 'nv-boxplot: boxplots')
- .attr('x1', box_left )
- .attr('y1', function(d,i) { return y(d.values['whisker_' + key]); })
- .attr('x2', box_right )
- .attr('y2', function(d,i) { return y(d.values['whisker_' + key]); });
- });
-
- ['low', 'high'].forEach(function(key) {
- boxEnter.selectAll('.nv-boxplot-' + key)
- .on('mouseover', function(d,i,j) {
- d3.select(this).classed('hover', true);
- dispatch.elementMouseover({
- series: { key: d.values['whisker_' + key], color: color(d,j) },
- e: d3.event
- });
- })
- .on('mouseout', function(d,i,j) {
- d3.select(this).classed('hover', false);
- dispatch.elementMouseout({
- series: { key: d.values['whisker_' + key], color: color(d,j) },
- e: d3.event
- });
- })
- .on('mousemove', function(d,i) {
- dispatch.elementMousemove({e: d3.event});
- });
- });
-
- // boxes
- boxEnter.append('rect')
- .attr('class', 'nv-boxplot-box')
- // tooltip events
- .on('mouseover', function(d,i) {
- d3.select(this).classed('hover', true);
- dispatch.elementMouseover({
- key: d.label,
- value: d.label,
- series: [
- { key: 'Q3', value: d.values.Q3, color: d.color || color(d,i) },
- { key: 'Q2', value: d.values.Q2, color: d.color || color(d,i) },
- { key: 'Q1', value: d.values.Q1, color: d.color || color(d,i) }
- ],
- data: d,
- index: i,
- e: d3.event
- });
- })
- .on('mouseout', function(d,i) {
- d3.select(this).classed('hover', false);
- dispatch.elementMouseout({
- key: d.label,
- value: d.label,
- series: [
- { key: 'Q3', value: d.values.Q3, color: d.color || color(d,i) },
- { key: 'Q2', value: d.values.Q2, color: d.color || color(d,i) },
- { key: 'Q1', value: d.values.Q1, color: d.color || color(d,i) }
- ],
- data: d,
- index: i,
- e: d3.event
- });
- })
- .on('mousemove', function(d,i) {
- dispatch.elementMousemove({e: d3.event});
- });
-
- // box transitions
- boxplots.select('rect.nv-boxplot-box')
- .watchTransition(renderWatch, 'nv-boxplot: boxes')
- .attr('y', function(d,i) { return y(d.values.Q3); })
- .attr('width', box_width)
- .attr('x', box_left )
-
- .attr('height', function(d,i) { return Math.abs(y(d.values.Q3) - y(d.values.Q1)) || 1 })
- .style('fill', function(d,i) { return d.color || color(d,i) })
- .style('stroke', function(d,i) { return d.color || color(d,i) });
-
- // median line
- boxEnter.append('line').attr('class', 'nv-boxplot-median');
-
- boxplots.select('line.nv-boxplot-median')
- .watchTransition(renderWatch, 'nv-boxplot: boxplots line')
- .attr('x1', box_left)
- .attr('y1', function(d,i) { return y(d.values.Q2); })
- .attr('x2', box_right)
- .attr('y2', function(d,i) { return y(d.values.Q2); });
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
- });
-
- renderWatch.renderEnd('nv-boxplot immediate');
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- maxBoxWidth: {get: function(){return maxBoxWidth;}, set: function(_){maxBoxWidth=_;}},
- x: {get: function(){return getX;}, set: function(_){getX=_;}},
- y: {get: function(){return getY;}, set: function(_){getY=_;}},
- xScale: {get: function(){return x;}, set: function(_){x=_;}},
- yScale: {get: function(){return y;}, set: function(_){y=_;}},
- xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
- yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
- xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},
- yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},
- id: {get: function(){return id;}, set: function(_){id=_;}},
- // rectClass: {get: function(){return rectClass;}, set: function(_){rectClass=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- }}
- });
-
- nv.utils.initOptions(chart);
-
- return chart;
-};
-nv.models.boxPlotChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var boxplot = nv.models.boxPlot()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- ;
-
- var margin = {top: 15, right: 10, bottom: 50, left: 60}
- , width = null
- , height = null
- , color = nv.utils.getColor()
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = false
- , staggerLabels = false
- , tooltip = nv.models.tooltip()
- , x
- , y
- , noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'beforeUpdate', 'renderEnd')
- , duration = 250
- ;
-
- xAxis
- .orient('bottom')
- .showMaxMin(false)
- .tickFormat(function(d) { return d })
- ;
- yAxis
- .orient((rightAlignYAxis) ? 'right' : 'left')
- .tickFormat(d3.format(',.1f'))
- ;
-
- tooltip.duration(0);
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var renderWatch = nv.utils.renderWatch(dispatch, duration);
-
- function chart(selection) {
- renderWatch.reset();
- renderWatch.models(boxplot);
- if (showXAxis) renderWatch.models(xAxis);
- if (showYAxis) renderWatch.models(yAxis);
-
- selection.each(function(data) {
- var container = d3.select(this),
- that = this;
- nv.utils.initSVG(container);
- var availableWidth = (width || parseInt(container.style('width')) || 960)
- - margin.left - margin.right,
- availableHeight = (height || parseInt(container.style('height')) || 400)
- - margin.top - margin.bottom;
-
- chart.update = function() {
- dispatch.beforeUpdate();
- container.transition().duration(duration).call(chart);
- };
- chart.container = this;
-
- // Display No Data message if there's nothing to show. (quartiles required at minimum)
- if (!data || !data.length ||
- !data.filter(function(d) { return d.values.hasOwnProperty("Q1") && d.values.hasOwnProperty("Q2") && d.values.hasOwnProperty("Q3"); }).length) {
- var noDataText = container.selectAll('.nv-noData').data([noData]);
-
- noDataText.enter().append('text')
- .attr('class', 'nvd3 nv-noData')
- .attr('dy', '-.7em')
- .style('text-anchor', 'middle');
-
- noDataText
- .attr('x', margin.left + availableWidth / 2)
- .attr('y', margin.top + availableHeight / 2)
- .text(function(d) { return d });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- // Setup Scales
- x = boxplot.xScale();
- y = boxplot.yScale().clamp(true);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-boxPlotWithAxes').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-boxPlotWithAxes').append('g');
- var defsEnter = gEnter.append('defs');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis')
- .append('g').attr('class', 'nv-zeroLine')
- .append('line');
-
- gEnter.append('g').attr('class', 'nv-barsWrap');
-
- g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- // Main Chart Component(s)
- boxplot
- .width(availableWidth)
- .height(availableHeight);
-
- var barsWrap = g.select('.nv-barsWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
-
- barsWrap.transition().call(boxplot);
-
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-x-label-clip-' + boxplot.id())
- .append('rect');
-
- g.select('#nv-x-label-clip-' + boxplot.id() + ' rect')
- .attr('width', x.rangeBand() * (staggerLabels ? 2 : 1))
- .attr('height', 16)
- .attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 ));
-
- // Setup Axes
- if (showXAxis) {
- xAxis
- .scale(x)
- .ticks( nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis').attr('transform', 'translate(0,' + y.range()[0] + ')');
- g.select('.nv-x.nv-axis').call(xAxis);
-
- var xTicks = g.select('.nv-x.nv-axis').selectAll('g');
- if (staggerLabels) {
- xTicks
- .selectAll('text')
- .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' })
- }
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- .ticks( Math.floor(availableHeight/36) ) // can't use nv.utils.calcTicksY with Object data
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis').call(yAxis);
- }
-
- // Zero line
- g.select(".nv-zeroLine line")
- .attr("x1",0)
- .attr("x2",availableWidth)
- .attr("y1", y(0))
- .attr("y2", y(0))
- ;
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
- });
-
- renderWatch.renderEnd('nv-boxplot chart immediate');
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- boxplot.dispatch.on('elementMouseover.tooltip', function(evt) {
- tooltip.data(evt).hidden(false);
- });
-
- boxplot.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.data(evt).hidden(true);
- });
-
- boxplot.dispatch.on('elementMousemove.tooltip', function(evt) {
- tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
- });
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.boxplot = boxplot;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.tooltip = tooltip;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}},
- showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
- showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
- tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}},
- tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- boxplot.duration(duration);
- xAxis.duration(duration);
- yAxis.duration(duration);
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- boxplot.color(color);
- }},
- rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- }}
- });
-
- nv.utils.inheritOptions(chart, boxplot);
- nv.utils.initOptions(chart);
-
- return chart;
-}
-// Chart design based on the recommendations of Stephen Few. Implementation
-// based on the work of Clint Ivy, Jamie Love, and Jason Davies.
-// http://projects.instantcognition.com/protovis/bulletchart/
-
-nv.models.bullet = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , orient = 'left' // TODO top & bottom
- , reverse = false
- , ranges = function(d) { return d.ranges }
- , markers = function(d) { return d.markers ? d.markers : [0] }
- , measures = function(d) { return d.measures }
- , rangeLabels = function(d) { return d.rangeLabels ? d.rangeLabels : [] }
- , markerLabels = function(d) { return d.markerLabels ? d.markerLabels : [] }
- , measureLabels = function(d) { return d.measureLabels ? d.measureLabels : [] }
- , forceX = [0] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
- , width = 380
- , height = 30
- , container = null
- , tickFormat = null
- , color = nv.utils.getColor(['#1f77b4'])
- , dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove')
- ;
-
- function chart(selection) {
- selection.each(function(d, i) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom;
-
- container = d3.select(this);
- nv.utils.initSVG(container);
-
- var rangez = ranges.call(this, d, i).slice().sort(d3.descending),
- markerz = markers.call(this, d, i).slice().sort(d3.descending),
- measurez = measures.call(this, d, i).slice().sort(d3.descending),
- rangeLabelz = rangeLabels.call(this, d, i).slice(),
- markerLabelz = markerLabels.call(this, d, i).slice(),
- measureLabelz = measureLabels.call(this, d, i).slice();
-
- // Setup Scales
- // Compute the new x-scale.
- var x1 = d3.scale.linear()
- .domain( d3.extent(d3.merge([forceX, rangez])) )
- .range(reverse ? [availableWidth, 0] : [0, availableWidth]);
-
- // Retrieve the old x-scale, if this is an update.
- var x0 = this.__chart__ || d3.scale.linear()
- .domain([0, Infinity])
- .range(x1.range());
-
- // Stash the new scale.
- this.__chart__ = x1;
-
- var rangeMin = d3.min(rangez), //rangez[2]
- rangeMax = d3.max(rangez), //rangez[0]
- rangeAvg = rangez[1];
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-bullet').data([d]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bullet');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('rect').attr('class', 'nv-range nv-rangeMax');
- gEnter.append('rect').attr('class', 'nv-range nv-rangeAvg');
- gEnter.append('rect').attr('class', 'nv-range nv-rangeMin');
- gEnter.append('rect').attr('class', 'nv-measure');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0)
- w1 = function(d) { return Math.abs(x1(d) - x1(0)) };
- var xp0 = function(d) { return d < 0 ? x0(d) : x0(0) },
- xp1 = function(d) { return d < 0 ? x1(d) : x1(0) };
-
- g.select('rect.nv-rangeMax')
- .attr('height', availableHeight)
- .attr('width', w1(rangeMax > 0 ? rangeMax : rangeMin))
- .attr('x', xp1(rangeMax > 0 ? rangeMax : rangeMin))
- .datum(rangeMax > 0 ? rangeMax : rangeMin)
-
- g.select('rect.nv-rangeAvg')
- .attr('height', availableHeight)
- .attr('width', w1(rangeAvg))
- .attr('x', xp1(rangeAvg))
- .datum(rangeAvg)
-
- g.select('rect.nv-rangeMin')
- .attr('height', availableHeight)
- .attr('width', w1(rangeMax))
- .attr('x', xp1(rangeMax))
- .attr('width', w1(rangeMax > 0 ? rangeMin : rangeMax))
- .attr('x', xp1(rangeMax > 0 ? rangeMin : rangeMax))
- .datum(rangeMax > 0 ? rangeMin : rangeMax)
-
- g.select('rect.nv-measure')
- .style('fill', color)
- .attr('height', availableHeight / 3)
- .attr('y', availableHeight / 3)
- .attr('width', measurez < 0 ?
- x1(0) - x1(measurez[0])
- : x1(measurez[0]) - x1(0))
- .attr('x', xp1(measurez))
- .on('mouseover', function() {
- dispatch.elementMouseover({
- value: measurez[0],
- label: measureLabelz[0] || 'Current',
- color: d3.select(this).style("fill")
- })
- })
- .on('mousemove', function() {
- dispatch.elementMousemove({
- value: measurez[0],
- label: measureLabelz[0] || 'Current',
- color: d3.select(this).style("fill")
- })
- })
- .on('mouseout', function() {
- dispatch.elementMouseout({
- value: measurez[0],
- label: measureLabelz[0] || 'Current',
- color: d3.select(this).style("fill")
- })
- });
-
- var h3 = availableHeight / 6;
-
- var markerData = markerz.map( function(marker, index) {
- return {value: marker, label: markerLabelz[index]}
- });
- gEnter
- .selectAll("path.nv-markerTriangle")
- .data(markerData)
- .enter()
- .append('path')
- .attr('class', 'nv-markerTriangle')
- .attr('transform', function(d) { return 'translate(' + x1(d.value) + ',' + (availableHeight / 2) + ')' })
- .attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z')
- .on('mouseover', function(d) {
- dispatch.elementMouseover({
- value: d.value,
- label: d.label || 'Previous',
- color: d3.select(this).style("fill"),
- pos: [x1(d.value), availableHeight/2]
- })
-
- })
- .on('mousemove', function(d) {
- dispatch.elementMousemove({
- value: d.value,
- label: d.label || 'Previous',
- color: d3.select(this).style("fill")
- })
- })
- .on('mouseout', function(d, i) {
- dispatch.elementMouseout({
- value: d.value,
- label: d.label || 'Previous',
- color: d3.select(this).style("fill")
- })
- });
-
- wrap.selectAll('.nv-range')
- .on('mouseover', function(d,i) {
- var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum");
- dispatch.elementMouseover({
- value: d,
- label: label,
- color: d3.select(this).style("fill")
- })
- })
- .on('mousemove', function() {
- dispatch.elementMousemove({
- value: measurez[0],
- label: measureLabelz[0] || 'Previous',
- color: d3.select(this).style("fill")
- })
- })
- .on('mouseout', function(d,i) {
- var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum");
- dispatch.elementMouseout({
- value: d,
- label: label,
- color: d3.select(this).style("fill")
- })
- });
- });
-
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- ranges: {get: function(){return ranges;}, set: function(_){ranges=_;}}, // ranges (bad, satisfactory, good)
- markers: {get: function(){return markers;}, set: function(_){markers=_;}}, // markers (previous, goal)
- measures: {get: function(){return measures;}, set: function(_){measures=_;}}, // measures (actual, forecast)
- forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}},
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- tickFormat: {get: function(){return tickFormat;}, set: function(_){tickFormat=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- orient: {get: function(){return orient;}, set: function(_){ // left, right, top, bottom
- orient = _;
- reverse = orient == 'right' || orient == 'bottom';
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }}
- });
-
- nv.utils.initOptions(chart);
- return chart;
-};
-
-
-
-// Chart design based on the recommendations of Stephen Few. Implementation
-// based on the work of Clint Ivy, Jamie Love, and Jason Davies.
-// http://projects.instantcognition.com/protovis/bulletchart/
-nv.models.bulletChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var bullet = nv.models.bullet();
- var tooltip = nv.models.tooltip();
-
- var orient = 'left' // TODO top & bottom
- , reverse = false
- , margin = {top: 5, right: 40, bottom: 20, left: 120}
- , ranges = function(d) { return d.ranges }
- , markers = function(d) { return d.markers ? d.markers : [0] }
- , measures = function(d) { return d.measures }
- , width = null
- , height = 55
- , tickFormat = null
- , ticks = null
- , noData = null
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
- ;
-
- tooltip.duration(0).headerEnabled(false);
-
- function chart(selection) {
- selection.each(function(d, i) {
- var container = d3.select(this);
- nv.utils.initSVG(container);
-
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = height - margin.top - margin.bottom,
- that = this;
-
- chart.update = function() { chart(selection) };
- chart.container = this;
-
- // Display No Data message if there's nothing to show.
- if (!d || !ranges.call(this, d, i)) {
- nv.utils.noData(chart, container)
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- var rangez = ranges.call(this, d, i).slice().sort(d3.descending),
- markerz = markers.call(this, d, i).slice().sort(d3.descending),
- measurez = measures.call(this, d, i).slice().sort(d3.descending);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-bulletChart').data([d]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bulletChart');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-bulletWrap');
- gEnter.append('g').attr('class', 'nv-titles');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- // Compute the new x-scale.
- var x1 = d3.scale.linear()
- .domain([0, Math.max(rangez[0], markerz[0], measurez[0])]) // TODO: need to allow forceX and forceY, and xDomain, yDomain
- .range(reverse ? [availableWidth, 0] : [0, availableWidth]);
-
- // Retrieve the old x-scale, if this is an update.
- var x0 = this.__chart__ || d3.scale.linear()
- .domain([0, Infinity])
- .range(x1.range());
-
- // Stash the new scale.
- this.__chart__ = x1;
-
- var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0)
- w1 = function(d) { return Math.abs(x1(d) - x1(0)) };
-
- var title = gEnter.select('.nv-titles').append('g')
- .attr('text-anchor', 'end')
- .attr('transform', 'translate(-6,' + (height - margin.top - margin.bottom) / 2 + ')');
- title.append('text')
- .attr('class', 'nv-title')
- .text(function(d) { return d.title; });
-
- title.append('text')
- .attr('class', 'nv-subtitle')
- .attr('dy', '1em')
- .text(function(d) { return d.subtitle; });
-
- bullet
- .width(availableWidth)
- .height(availableHeight)
-
- var bulletWrap = g.select('.nv-bulletWrap');
- d3.transition(bulletWrap).call(bullet);
-
- // Compute the tick format.
- var format = tickFormat || x1.tickFormat( availableWidth / 100 );
-
- // Update the tick groups.
- var tick = g.selectAll('g.nv-tick')
- .data(x1.ticks( ticks ? ticks : (availableWidth / 50) ), function(d) {
- return this.textContent || format(d);
- });
-
- // Initialize the ticks with the old scale, x0.
- var tickEnter = tick.enter().append('g')
- .attr('class', 'nv-tick')
- .attr('transform', function(d) { return 'translate(' + x0(d) + ',0)' })
- .style('opacity', 1e-6);
-
- tickEnter.append('line')
- .attr('y1', availableHeight)
- .attr('y2', availableHeight * 7 / 6);
-
- tickEnter.append('text')
- .attr('text-anchor', 'middle')
- .attr('dy', '1em')
- .attr('y', availableHeight * 7 / 6)
- .text(format);
-
- // Transition the updating ticks to the new scale, x1.
- var tickUpdate = d3.transition(tick)
- .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' })
- .style('opacity', 1);
-
- tickUpdate.select('line')
- .attr('y1', availableHeight)
- .attr('y2', availableHeight * 7 / 6);
-
- tickUpdate.select('text')
- .attr('y', availableHeight * 7 / 6);
-
- // Transition the exiting ticks to the new scale, x1.
- d3.transition(tick.exit())
- .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' })
- .style('opacity', 1e-6)
- .remove();
- });
-
- d3.timer.flush();
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- bullet.dispatch.on('elementMouseover.tooltip', function(evt) {
- evt['series'] = {
- key: evt.label,
- value: evt.value,
- color: evt.color
- };
- tooltip.data(evt).hidden(false);
- });
-
- bullet.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true);
- });
-
- bullet.dispatch.on('elementMousemove.tooltip', function(evt) {
- tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
- });
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.bullet = bullet;
- chart.dispatch = dispatch;
- chart.tooltip = tooltip;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- ranges: {get: function(){return ranges;}, set: function(_){ranges=_;}}, // ranges (bad, satisfactory, good)
- markers: {get: function(){return markers;}, set: function(_){markers=_;}}, // markers (previous, goal)
- measures: {get: function(){return measures;}, set: function(_){measures=_;}}, // measures (actual, forecast)
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- tickFormat: {get: function(){return tickFormat;}, set: function(_){tickFormat=_;}},
- ticks: {get: function(){return ticks;}, set: function(_){ticks=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- orient: {get: function(){return orient;}, set: function(_){ // left, right, top, bottom
- orient = _;
- reverse = orient == 'right' || orient == 'bottom';
- }}
- });
-
- nv.utils.inheritOptions(chart, bullet);
- nv.utils.initOptions(chart);
-
- return chart;
-};
-
-
-
-nv.models.candlestickBar = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = null
- , height = null
- , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
- , container
- , x = d3.scale.linear()
- , y = d3.scale.linear()
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , getOpen = function(d) { return d.open }
- , getClose = function(d) { return d.close }
- , getHigh = function(d) { return d.high }
- , getLow = function(d) { return d.low }
- , forceX = []
- , forceY = []
- , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart
- , clipEdge = true
- , color = nv.utils.defaultColor()
- , interactive = false
- , xDomain
- , yDomain
- , xRange
- , yRange
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove')
- ;
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- function chart(selection) {
- selection.each(function(data) {
- container = d3.select(this);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- nv.utils.initSVG(container);
-
- // Width of the candlestick bars.
- var barWidth = (availableWidth / data[0].values.length) * .45;
-
- // Setup Scales
- x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ));
-
- if (padData)
- x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);
- else
- x.range(xRange || [5 + barWidth / 2, availableWidth - barWidth / 2 - 5]);
-
- y.domain(yDomain || [
- d3.min(data[0].values.map(getLow).concat(forceY)),
- d3.max(data[0].values.map(getHigh).concat(forceY))
- ]
- ).range(yRange || [availableHeight, 0]);
-
- // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
- if (x.domain()[0] === x.domain()[1])
- x.domain()[0] ?
- x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])
- : x.domain([-1,1]);
-
- if (y.domain()[0] === y.domain()[1])
- y.domain()[0] ?
- y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])
- : y.domain([-1,1]);
-
- // Setup containers and skeleton of chart
- var wrap = d3.select(this).selectAll('g.nv-wrap.nv-candlestickBar').data([data[0].values]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-candlestickBar');
- var defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-ticks');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- container
- .on('click', function(d,i) {
- dispatch.chartClick({
- data: d,
- index: i,
- pos: d3.event,
- id: id
- });
- });
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-chart-clip-path-' + id)
- .append('rect');
-
- wrap.select('#nv-chart-clip-path-' + id + ' rect')
- .attr('width', availableWidth)
- .attr('height', availableHeight);
-
- g .attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : '');
-
- var ticks = wrap.select('.nv-ticks').selectAll('.nv-tick')
- .data(function(d) { return d });
- ticks.exit().remove();
-
- // The colors are currently controlled by CSS.
- var tickGroups = ticks.enter().append('g')
- .attr('class', function(d, i, j) { return (getOpen(d, i) > getClose(d, i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i});
-
- var lines = tickGroups.append('line')
- .attr('class', 'nv-candlestick-lines')
- .attr('transform', function(d, i) { return 'translate(' + x(getX(d, i)) + ',0)'; })
- .attr('x1', 0)
- .attr('y1', function(d, i) { return y(getHigh(d, i)); })
- .attr('x2', 0)
- .attr('y2', function(d, i) { return y(getLow(d, i)); });
-
- var rects = tickGroups.append('rect')
- .attr('class', 'nv-candlestick-rects nv-bars')
- .attr('transform', function(d, i) {
- return 'translate(' + (x(getX(d, i)) - barWidth/2) + ','
- + (y(getY(d, i)) - (getOpen(d, i) > getClose(d, i) ? (y(getClose(d, i)) - y(getOpen(d, i))) : 0))
- + ')';
- })
- .attr('x', 0)
- .attr('y', 0)
- .attr('width', barWidth)
- .attr('height', function(d, i) {
- var open = getOpen(d, i);
- var close = getClose(d, i);
- return open > close ? y(close) - y(open) : y(open) - y(close);
- });
-
- container.selectAll('.nv-candlestick-lines').transition()
- .attr('transform', function(d, i) { return 'translate(' + x(getX(d, i)) + ',0)'; })
- .attr('x1', 0)
- .attr('y1', function(d, i) { return y(getHigh(d, i)); })
- .attr('x2', 0)
- .attr('y2', function(d, i) { return y(getLow(d, i)); });
-
- container.selectAll('.nv-candlestick-rects').transition()
- .attr('transform', function(d, i) {
- return 'translate(' + (x(getX(d, i)) - barWidth/2) + ','
- + (y(getY(d, i)) - (getOpen(d, i) > getClose(d, i) ? (y(getClose(d, i)) - y(getOpen(d, i))) : 0))
- + ')';
- })
- .attr('x', 0)
- .attr('y', 0)
- .attr('width', barWidth)
- .attr('height', function(d, i) {
- var open = getOpen(d, i);
- var close = getClose(d, i);
- return open > close ? y(close) - y(open) : y(open) - y(close);
- });
- });
-
- return chart;
- }
-
-
- //Create methods to allow outside functions to highlight a specific bar.
- chart.highlightPoint = function(pointIndex, isHoverOver) {
- chart.clearHighlights();
- container.select(".nv-candlestickBar .nv-tick-0-" + pointIndex)
- .classed("hover", isHoverOver)
- ;
- };
-
- chart.clearHighlights = function() {
- container.select(".nv-candlestickBar .nv-tick.hover")
- .classed("hover", false)
- ;
- };
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- xScale: {get: function(){return x;}, set: function(_){x=_;}},
- yScale: {get: function(){return y;}, set: function(_){y=_;}},
- xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
- yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
- xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},
- yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},
- forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}},
- forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},
- padData: {get: function(){return padData;}, set: function(_){padData=_;}},
- clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
- id: {get: function(){return id;}, set: function(_){id=_;}},
- interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}},
-
- x: {get: function(){return getX;}, set: function(_){getX=_;}},
- y: {get: function(){return getY;}, set: function(_){getY=_;}},
- open: {get: function(){return getOpen();}, set: function(_){getOpen=_;}},
- close: {get: function(){return getClose();}, set: function(_){getClose=_;}},
- high: {get: function(){return getHigh;}, set: function(_){getHigh=_;}},
- low: {get: function(){return getLow;}, set: function(_){getLow=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top != undefined ? _.top : margin.top;
- margin.right = _.right != undefined ? _.right : margin.right;
- margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom;
- margin.left = _.left != undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }}
- });
-
- nv.utils.initOptions(chart);
- return chart;
-};
-
-nv.models.cumulativeLineChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var lines = nv.models.line()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- , controls = nv.models.legend()
- , interactiveLayer = nv.interactiveGuideline()
- , tooltip = nv.models.tooltip()
- ;
-
- var margin = {top: 30, right: 30, bottom: 50, left: 60}
- , color = nv.utils.defaultColor()
- , width = null
- , height = null
- , showLegend = true
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = false
- , showControls = true
- , useInteractiveGuideline = false
- , rescaleY = true
- , x //can be accessed via chart.xScale()
- , y //can be accessed via chart.yScale()
- , id = lines.id()
- , state = nv.utils.state()
- , defaultState = null
- , noData = null
- , average = function(d) { return d.average }
- , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd')
- , transitionDuration = 250
- , duration = 250
- , noErrorCheck = false //if set to TRUE, will bypass an error check in the indexify function.
- ;
-
- state.index = 0;
- state.rescaleY = rescaleY;
-
- xAxis.orient('bottom').tickPadding(7);
- yAxis.orient((rightAlignYAxis) ? 'right' : 'left');
-
- tooltip.valueFormatter(function(d, i) {
- return yAxis.tickFormat()(d, i);
- }).headerFormatter(function(d, i) {
- return xAxis.tickFormat()(d, i);
- });
-
- controls.updateState(false);
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var dx = d3.scale.linear()
- , index = {i: 0, x: 0}
- , renderWatch = nv.utils.renderWatch(dispatch, duration)
- ;
-
- var stateGetter = function(data) {
- return function(){
- return {
- active: data.map(function(d) { return !d.disabled }),
- index: index.i,
- rescaleY: rescaleY
- };
- }
- };
-
- var stateSetter = function(data) {
- return function(state) {
- if (state.index !== undefined)
- index.i = state.index;
- if (state.rescaleY !== undefined)
- rescaleY = state.rescaleY;
- if (state.active !== undefined)
- data.forEach(function(series,i) {
- series.disabled = !state.active[i];
- });
- }
- };
-
- function chart(selection) {
- renderWatch.reset();
- renderWatch.models(lines);
- if (showXAxis) renderWatch.models(xAxis);
- if (showYAxis) renderWatch.models(yAxis);
- selection.each(function(data) {
- var container = d3.select(this);
- nv.utils.initSVG(container);
- container.classed('nv-chart-' + id, true);
- var that = this;
-
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- chart.update = function() {
- if (duration === 0)
- container.call(chart);
- else
- container.transition().duration(duration).call(chart)
- };
- chart.container = this;
-
- state
- .setter(stateSetter(data), chart.update)
- .getter(stateGetter(data))
- .update();
-
- // DEPRECATED set state.disableddisabled
- state.disabled = data.map(function(d) { return !!d.disabled });
-
- if (!defaultState) {
- var key;
- defaultState = {};
- for (key in state) {
- if (state[key] instanceof Array)
- defaultState[key] = state[key].slice(0);
- else
- defaultState[key] = state[key];
- }
- }
-
- var indexDrag = d3.behavior.drag()
- .on('dragstart', dragStart)
- .on('drag', dragMove)
- .on('dragend', dragEnd);
-
-
- function dragStart(d,i) {
- d3.select(chart.container)
- .style('cursor', 'ew-resize');
- }
-
- function dragMove(d,i) {
- index.x = d3.event.x;
- index.i = Math.round(dx.invert(index.x));
- updateZero();
- }
-
- function dragEnd(d,i) {
- d3.select(chart.container)
- .style('cursor', 'auto');
-
- // update state and send stateChange with new index
- state.index = index.i;
- dispatch.stateChange(state);
- }
-
- // Display No Data message if there's nothing to show.
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
- nv.utils.noData(chart, container)
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- // Setup Scales
- x = lines.xScale();
- y = lines.yScale();
-
- if (!rescaleY) {
- var seriesDomains = data
- .filter(function(series) { return !series.disabled })
- .map(function(series,i) {
- var initialDomain = d3.extent(series.values, lines.y());
-
- //account for series being disabled when losing 95% or more
- if (initialDomain[0] < -.95) initialDomain[0] = -.95;
-
- return [
- (initialDomain[0] - initialDomain[1]) / (1 + initialDomain[1]),
- (initialDomain[1] - initialDomain[0]) / (1 + initialDomain[0])
- ];
- });
-
- var completeDomain = [
- d3.min(seriesDomains, function(d) { return d[0] }),
- d3.max(seriesDomains, function(d) { return d[1] })
- ];
-
- lines.yDomain(completeDomain);
- } else {
- lines.yDomain(null);
- }
-
- dx.domain([0, data[0].values.length - 1]) //Assumes all series have same length
- .range([0, availableWidth])
- .clamp(true);
-
- var data = indexify(index.i, data);
-
- // Setup containers and skeleton of chart
- var interactivePointerEvents = (useInteractiveGuideline) ? "none" : "all";
- var wrap = container.selectAll('g.nv-wrap.nv-cumulativeLine').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-cumulativeLine').append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-interactive');
- gEnter.append('g').attr('class', 'nv-x nv-axis').style("pointer-events","none");
- gEnter.append('g').attr('class', 'nv-y nv-axis');
- gEnter.append('g').attr('class', 'nv-background');
- gEnter.append('g').attr('class', 'nv-linesWrap').style("pointer-events",interactivePointerEvents);
- gEnter.append('g').attr('class', 'nv-avgLinesWrap').style("pointer-events","none");
- gEnter.append('g').attr('class', 'nv-legendWrap');
- gEnter.append('g').attr('class', 'nv-controlsWrap');
-
- // Legend
- if (showLegend) {
- legend.width(availableWidth);
-
- g.select('.nv-legendWrap')
- .datum(data)
- .call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- availableHeight = nv.utils.availableHeight(height, container, margin);
- }
-
- g.select('.nv-legendWrap')
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- }
-
- // Controls
- if (showControls) {
- var controlsData = [
- { key: 'Re-scale y-axis', disabled: !rescaleY }
- ];
-
- controls
- .width(140)
- .color(['#444', '#444', '#444'])
- .rightAlign(false)
- .margin({top: 5, right: 0, bottom: 5, left: 20})
- ;
-
- g.select('.nv-controlsWrap')
- .datum(controlsData)
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- .call(controls);
- }
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- // Show error if series goes below 100%
- var tempDisabled = data.filter(function(d) { return d.tempDisabled });
-
- wrap.select('.tempDisabled').remove(); //clean-up and prevent duplicates
- if (tempDisabled.length) {
- wrap.append('text').attr('class', 'tempDisabled')
- .attr('x', availableWidth / 2)
- .attr('y', '-.71em')
- .style('text-anchor', 'end')
- .text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.');
- }
-
- //Set up interactive layer
- if (useInteractiveGuideline) {
- interactiveLayer
- .width(availableWidth)
- .height(availableHeight)
- .margin({left:margin.left,top:margin.top})
- .svgContainer(container)
- .xScale(x);
- wrap.select(".nv-interactive").call(interactiveLayer);
- }
-
- gEnter.select('.nv-background')
- .append('rect');
-
- g.select('.nv-background rect')
- .attr('width', availableWidth)
- .attr('height', availableHeight);
-
- lines
- //.x(function(d) { return d.x })
- .y(function(d) { return d.display.y })
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled; }));
-
- var linesWrap = g.select('.nv-linesWrap')
- .datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled }));
-
- linesWrap.call(lines);
-
- //Store a series index number in the data array.
- data.forEach(function(d,i) {
- d.seriesIndex = i;
- });
-
- var avgLineData = data.filter(function(d) {
- return !d.disabled && !!average(d);
- });
-
- var avgLines = g.select(".nv-avgLinesWrap").selectAll("line")
- .data(avgLineData, function(d) { return d.key; });
-
- var getAvgLineY = function(d) {
- //If average lines go off the svg element, clamp them to the svg bounds.
- var yVal = y(average(d));
- if (yVal < 0) return 0;
- if (yVal > availableHeight) return availableHeight;
- return yVal;
- };
-
- avgLines.enter()
- .append('line')
- .style('stroke-width',2)
- .style('stroke-dasharray','10,10')
- .style('stroke',function (d,i) {
- return lines.color()(d,d.seriesIndex);
- })
- .attr('x1',0)
- .attr('x2',availableWidth)
- .attr('y1', getAvgLineY)
- .attr('y2', getAvgLineY);
-
- avgLines
- .style('stroke-opacity',function(d){
- //If average lines go offscreen, make them transparent
- var yVal = y(average(d));
- if (yVal < 0 || yVal > availableHeight) return 0;
- return 1;
- })
- .attr('x1',0)
- .attr('x2',availableWidth)
- .attr('y1', getAvgLineY)
- .attr('y2', getAvgLineY);
-
- avgLines.exit().remove();
-
- //Create index line
- var indexLine = linesWrap.selectAll('.nv-indexLine')
- .data([index]);
- indexLine.enter().append('rect').attr('class', 'nv-indexLine')
- .attr('width', 3)
- .attr('x', -2)
- .attr('fill', 'red')
- .attr('fill-opacity', .5)
- .style("pointer-events","all")
- .call(indexDrag);
-
- indexLine
- .attr('transform', function(d) { return 'translate(' + dx(d.i) + ',0)' })
- .attr('height', availableHeight);
-
- // Setup Axes
- if (showXAxis) {
- xAxis
- .scale(x)
- ._ticks( nv.utils.calcTicksX(availableWidth/70, data) )
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y.range()[0] + ')');
- g.select('.nv-x.nv-axis')
- .call(xAxis);
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis')
- .call(yAxis);
- }
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- function updateZero() {
- indexLine
- .data([index]);
-
- //When dragging the index line, turn off line transitions.
- // Then turn them back on when done dragging.
- var oldDuration = chart.duration();
- chart.duration(0);
- chart.update();
- chart.duration(oldDuration);
- }
-
- g.select('.nv-background rect')
- .on('click', function() {
- index.x = d3.mouse(this)[0];
- index.i = Math.round(dx.invert(index.x));
-
- // update state and send stateChange with new index
- state.index = index.i;
- dispatch.stateChange(state);
-
- updateZero();
- });
-
- lines.dispatch.on('elementClick', function(e) {
- index.i = e.pointIndex;
- index.x = dx(index.i);
-
- // update state and send stateChange with new index
- state.index = index.i;
- dispatch.stateChange(state);
-
- updateZero();
- });
-
- controls.dispatch.on('legendClick', function(d,i) {
- d.disabled = !d.disabled;
- rescaleY = !d.disabled;
-
- state.rescaleY = rescaleY;
- dispatch.stateChange(state);
- chart.update();
- });
-
- legend.dispatch.on('stateChange', function(newState) {
- for (var key in newState)
- state[key] = newState[key];
- dispatch.stateChange(state);
- chart.update();
- });
-
- interactiveLayer.dispatch.on('elementMousemove', function(e) {
- lines.clearHighlights();
- var singlePoint, pointIndex, pointXLocation, allData = [];
-
- data
- .filter(function(series, i) {
- series.seriesIndex = i;
- return !series.disabled;
- })
- .forEach(function(series,i) {
- pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
- lines.highlightPoint(i, pointIndex, true);
- var point = series.values[pointIndex];
- if (typeof point === 'undefined') return;
- if (typeof singlePoint === 'undefined') singlePoint = point;
- if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
- allData.push({
- key: series.key,
- value: chart.y()(point, pointIndex),
- color: color(series,series.seriesIndex)
- });
- });
-
- //Highlight the tooltip entry based on which point the mouse is closest to.
- if (allData.length > 2) {
- var yValue = chart.yScale().invert(e.mouseY);
- var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]);
- var threshold = 0.03 * domainExtent;
- var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold);
- if (indexToHighlight !== null)
- allData[indexToHighlight].highlight = true;
- }
-
- var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex), pointIndex);
- interactiveLayer.tooltip
- .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top})
- .chartContainer(that.parentNode)
- .valueFormatter(function(d,i) {
- return yAxis.tickFormat()(d);
- })
- .data(
- {
- value: xValue,
- series: allData
- }
- )();
-
- interactiveLayer.renderGuideLine(pointXLocation);
- });
-
- interactiveLayer.dispatch.on("elementMouseout",function(e) {
- lines.clearHighlights();
- });
-
- // Update chart from a state object passed to event handler
- dispatch.on('changeState', function(e) {
- if (typeof e.disabled !== 'undefined') {
- data.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
-
- state.disabled = e.disabled;
- }
-
- if (typeof e.index !== 'undefined') {
- index.i = e.index;
- index.x = dx(index.i);
-
- state.index = e.index;
-
- indexLine
- .data([index]);
- }
-
- if (typeof e.rescaleY !== 'undefined') {
- rescaleY = e.rescaleY;
- }
-
- chart.update();
- });
-
- });
-
- renderWatch.renderEnd('cumulativeLineChart immediate');
-
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- lines.dispatch.on('elementMouseover.tooltip', function(evt) {
- var point = {
- x: chart.x()(evt.point),
- y: chart.y()(evt.point),
- color: evt.point.color
- };
- evt.point = point;
- tooltip.data(evt).position(evt.pos).hidden(false);
- });
-
- lines.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true)
- });
-
- //============================================================
- // Functions
- //------------------------------------------------------------
-
- var indexifyYGetter = null;
- /* Normalize the data according to an index point. */
- function indexify(idx, data) {
- if (!indexifyYGetter) indexifyYGetter = lines.y();
- return data.map(function(line, i) {
- if (!line.values) {
- return line;
- }
- var indexValue = line.values[idx];
- if (indexValue == null) {
- return line;
- }
- var v = indexifyYGetter(indexValue, idx);
-
- //TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue
- if (v < -.95 && !noErrorCheck) {
- //if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically correct till it hits 100)
-
- line.tempDisabled = true;
- return line;
- }
-
- line.tempDisabled = false;
-
- line.values = line.values.map(function(point, pointIndex) {
- point.display = {'y': (indexifyYGetter(point, pointIndex) - v) / (1 + v) };
- return point;
- });
-
- return line;
- })
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.dispatch = dispatch;
- chart.lines = lines;
- chart.legend = legend;
- chart.controls = controls;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.interactiveLayer = interactiveLayer;
- chart.state = state;
- chart.tooltip = tooltip;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- rescaleY: {get: function(){return rescaleY;}, set: function(_){rescaleY=_;}},
- showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
- average: {get: function(){return average;}, set: function(_){average=_;}},
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
- showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
- showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
- noErrorCheck: {get: function(){return noErrorCheck;}, set: function(_){noErrorCheck=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- legend.color(color);
- }},
- useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){
- useInteractiveGuideline = _;
- if (_ === true) {
- chart.interactive(false);
- chart.useVoronoi(false);
- }
- }},
- rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- lines.duration(duration);
- xAxis.duration(duration);
- yAxis.duration(duration);
- renderWatch.reset(duration);
- }}
- });
-
- nv.utils.inheritOptions(chart, lines);
- nv.utils.initOptions(chart);
-
- return chart;
-};
-//TODO: consider deprecating by adding necessary features to multiBar model
-nv.models.discreteBar = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 960
- , height = 500
- , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
- , container
- , x = d3.scale.ordinal()
- , y = d3.scale.linear()
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove
- , color = nv.utils.defaultColor()
- , showValues = false
- , valueFormat = d3.format(',.2f')
- , xDomain
- , yDomain
- , xRange
- , yRange
- , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
- , rectClass = 'discreteBar'
- , duration = 250
- ;
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0;
- var renderWatch = nv.utils.renderWatch(dispatch, duration);
-
- function chart(selection) {
- renderWatch.reset();
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom;
-
- container = d3.select(this);
- nv.utils.initSVG(container);
-
- //add series index to each data point for reference
- data.forEach(function(series, i) {
- series.values.forEach(function(point) {
- point.series = i;
- });
- });
-
- // Setup Scales
- // remap and flatten the data for use in calculating the scales' domains
- var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate
- data.map(function(d) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i), y0: d.y0 }
- })
- });
-
- x .domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))
- .rangeBands(xRange || [0, availableWidth], .1);
- y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y }).concat(forceY)));
-
- // If showValues, pad the Y axis range to account for label height
- if (showValues) y.range(yRange || [availableHeight - (y.domain()[0] < 0 ? 12 : 0), y.domain()[1] > 0 ? 12 : 0]);
- else y.range(yRange || [availableHeight, 0]);
-
- //store old scales if they exist
- x0 = x0 || x;
- y0 = y0 || y.copy().range([y(0),y(0)]);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-discretebar').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discretebar');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-groups');
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- //TODO: by definition, the discrete bar should not have multiple groups, will modify/remove later
- var groups = wrap.select('.nv-groups').selectAll('.nv-group')
- .data(function(d) { return d }, function(d) { return d.key });
- groups.enter().append('g')
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6);
- groups.exit()
- .watchTransition(renderWatch, 'discreteBar: exit groups')
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6)
- .remove();
- groups
- .attr('class', function(d,i) { return 'nv-group nv-series-' + i })
- .classed('hover', function(d) { return d.hover });
- groups
- .watchTransition(renderWatch, 'discreteBar: groups')
- .style('stroke-opacity', 1)
- .style('fill-opacity', .75);
-
- var bars = groups.selectAll('g.nv-bar')
- .data(function(d) { return d.values });
- bars.exit().remove();
-
- var barsEnter = bars.enter().append('g')
- .attr('transform', function(d,i,j) {
- return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05 ) + ', ' + y(0) + ')'
- })
- .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here
- d3.select(this).classed('hover', true);
- dispatch.elementMouseover({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- })
- .on('mouseout', function(d,i) {
- d3.select(this).classed('hover', false);
- dispatch.elementMouseout({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- })
- .on('mousemove', function(d,i) {
- dispatch.elementMousemove({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- })
- .on('click', function(d,i) {
- dispatch.elementClick({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- d3.event.stopPropagation();
- })
- .on('dblclick', function(d,i) {
- dispatch.elementDblClick({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- d3.event.stopPropagation();
- });
-
- barsEnter.append('rect')
- .attr('height', 0)
- .attr('width', x.rangeBand() * .9 / data.length )
-
- if (showValues) {
- barsEnter.append('text')
- .attr('text-anchor', 'middle')
- ;
-
- bars.select('text')
- .text(function(d,i) { return valueFormat(getY(d,i)) })
- .watchTransition(renderWatch, 'discreteBar: bars text')
- .attr('x', x.rangeBand() * .9 / 2)
- .attr('y', function(d,i) { return getY(d,i) < 0 ? y(getY(d,i)) - y(0) + 12 : -4 })
-
- ;
- } else {
- bars.selectAll('text').remove();
- }
-
- bars
- .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive' })
- .style('fill', function(d,i) { return d.color || color(d,i) })
- .style('stroke', function(d,i) { return d.color || color(d,i) })
- .select('rect')
- .attr('class', rectClass)
- .watchTransition(renderWatch, 'discreteBar: bars rect')
- .attr('width', x.rangeBand() * .9 / data.length);
- bars.watchTransition(renderWatch, 'discreteBar: bars')
- //.delay(function(d,i) { return i * 1200 / data[0].values.length })
- .attr('transform', function(d,i) {
- var left = x(getX(d,i)) + x.rangeBand() * .05,
- top = getY(d,i) < 0 ?
- y(0) :
- y(0) - y(getY(d,i)) < 1 ?
- y(0) - 1 : //make 1 px positive bars show up above y=0
- y(getY(d,i));
-
- return 'translate(' + left + ', ' + top + ')'
- })
- .select('rect')
- .attr('height', function(d,i) {
- return Math.max(Math.abs(y(getY(d,i)) - y((yDomain && yDomain[0]) || 0)) || 1)
- });
-
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
-
- });
-
- renderWatch.renderEnd('discreteBar immediate');
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},
- showValues: {get: function(){return showValues;}, set: function(_){showValues=_;}},
- x: {get: function(){return getX;}, set: function(_){getX=_;}},
- y: {get: function(){return getY;}, set: function(_){getY=_;}},
- xScale: {get: function(){return x;}, set: function(_){x=_;}},
- yScale: {get: function(){return y;}, set: function(_){y=_;}},
- xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
- yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
- xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},
- yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},
- valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},
- id: {get: function(){return id;}, set: function(_){id=_;}},
- rectClass: {get: function(){return rectClass;}, set: function(_){rectClass=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- }}
- });
-
- nv.utils.initOptions(chart);
-
- return chart;
-};
-
-nv.models.discreteBarChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var discretebar = nv.models.discreteBar()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , tooltip = nv.models.tooltip()
- ;
-
- var margin = {top: 15, right: 10, bottom: 50, left: 60}
- , width = null
- , height = null
- , color = nv.utils.getColor()
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = false
- , staggerLabels = false
- , x
- , y
- , noData = null
- , dispatch = d3.dispatch('beforeUpdate','renderEnd')
- , duration = 250
- ;
-
- xAxis
- .orient('bottom')
- .showMaxMin(false)
- .tickFormat(function(d) { return d })
- ;
- yAxis
- .orient((rightAlignYAxis) ? 'right' : 'left')
- .tickFormat(d3.format(',.1f'))
- ;
-
- tooltip
- .duration(0)
- .headerEnabled(false)
- .valueFormatter(function(d, i) {
- return yAxis.tickFormat()(d, i);
- })
- .keyFormatter(function(d, i) {
- return xAxis.tickFormat()(d, i);
- });
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var renderWatch = nv.utils.renderWatch(dispatch, duration);
-
- function chart(selection) {
- renderWatch.reset();
- renderWatch.models(discretebar);
- if (showXAxis) renderWatch.models(xAxis);
- if (showYAxis) renderWatch.models(yAxis);
-
- selection.each(function(data) {
- var container = d3.select(this),
- that = this;
- nv.utils.initSVG(container);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- chart.update = function() {
- dispatch.beforeUpdate();
- container.transition().duration(duration).call(chart);
- };
- chart.container = this;
-
- // Display No Data message if there's nothing to show.
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
- nv.utils.noData(chart, container);
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- // Setup Scales
- x = discretebar.xScale();
- y = discretebar.yScale().clamp(true);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-discreteBarWithAxes').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discreteBarWithAxes').append('g');
- var defsEnter = gEnter.append('defs');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis')
- .append('g').attr('class', 'nv-zeroLine')
- .append('line');
-
- gEnter.append('g').attr('class', 'nv-barsWrap');
-
- g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- // Main Chart Component(s)
- discretebar
- .width(availableWidth)
- .height(availableHeight);
-
- var barsWrap = g.select('.nv-barsWrap')
- .datum(data.filter(function(d) { return !d.disabled }));
-
- barsWrap.transition().call(discretebar);
-
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-x-label-clip-' + discretebar.id())
- .append('rect');
-
- g.select('#nv-x-label-clip-' + discretebar.id() + ' rect')
- .attr('width', x.rangeBand() * (staggerLabels ? 2 : 1))
- .attr('height', 16)
- .attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 ));
-
- // Setup Axes
- if (showXAxis) {
- xAxis
- .scale(x)
- ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + (y.range()[0] + ((discretebar.showValues() && y.domain()[0] < 0) ? 16 : 0)) + ')');
- g.select('.nv-x.nv-axis').call(xAxis);
-
- var xTicks = g.select('.nv-x.nv-axis').selectAll('g');
- if (staggerLabels) {
- xTicks
- .selectAll('text')
- .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' })
- }
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis').call(yAxis);
- }
-
- // Zero line
- g.select(".nv-zeroLine line")
- .attr("x1",0)
- .attr("x2",availableWidth)
- .attr("y1", y(0))
- .attr("y2", y(0))
- ;
- });
-
- renderWatch.renderEnd('discreteBar chart immediate');
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- discretebar.dispatch.on('elementMouseover.tooltip', function(evt) {
- evt['series'] = {
- key: chart.x()(evt.data),
- value: chart.y()(evt.data),
- color: evt.color
- };
- tooltip.data(evt).hidden(false);
- });
-
- discretebar.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true);
- });
-
- discretebar.dispatch.on('elementMousemove.tooltip', function(evt) {
- tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
- });
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.discretebar = discretebar;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.tooltip = tooltip;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}},
- showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
- showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- discretebar.duration(duration);
- xAxis.duration(duration);
- yAxis.duration(duration);
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- discretebar.color(color);
- }},
- rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- }}
- });
-
- nv.utils.inheritOptions(chart, discretebar);
- nv.utils.initOptions(chart);
-
- return chart;
-}
-
-nv.models.distribution = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 400 //technically width or height depending on x or y....
- , size = 8
- , axis = 'x' // 'x' or 'y'... horizontal or vertical
- , getData = function(d) { return d[axis] } // defaults d.x or d.y
- , color = nv.utils.defaultColor()
- , scale = d3.scale.linear()
- , domain
- , duration = 250
- , dispatch = d3.dispatch('renderEnd')
- ;
-
- //============================================================
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var scale0;
- var renderWatch = nv.utils.renderWatch(dispatch, duration);
-
- //============================================================
-
-
- function chart(selection) {
- renderWatch.reset();
- selection.each(function(data) {
- var availableLength = width - (axis === 'x' ? margin.left + margin.right : margin.top + margin.bottom),
- naxis = axis == 'x' ? 'y' : 'x',
- container = d3.select(this);
- nv.utils.initSVG(container);
-
- //------------------------------------------------------------
- // Setup Scales
-
- scale0 = scale0 || scale;
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-distribution').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-distribution');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
-
- //------------------------------------------------------------
-
-
- var distWrap = g.selectAll('g.nv-dist')
- .data(function(d) { return d }, function(d) { return d.key });
-
- distWrap.enter().append('g');
- distWrap
- .attr('class', function(d,i) { return 'nv-dist nv-series-' + i })
- .style('stroke', function(d,i) { return color(d, i) });
-
- var dist = distWrap.selectAll('line.nv-dist' + axis)
- .data(function(d) { return d.values })
- dist.enter().append('line')
- .attr(axis + '1', function(d,i) { return scale0(getData(d,i)) })
- .attr(axis + '2', function(d,i) { return scale0(getData(d,i)) })
- renderWatch.transition(distWrap.exit().selectAll('line.nv-dist' + axis), 'dist exit')
- // .transition()
- .attr(axis + '1', function(d,i) { return scale(getData(d,i)) })
- .attr(axis + '2', function(d,i) { return scale(getData(d,i)) })
- .style('stroke-opacity', 0)
- .remove();
- dist
- .attr('class', function(d,i) { return 'nv-dist' + axis + ' nv-dist' + axis + '-' + i })
- .attr(naxis + '1', 0)
- .attr(naxis + '2', size);
- renderWatch.transition(dist, 'dist')
- // .transition()
- .attr(axis + '1', function(d,i) { return scale(getData(d,i)) })
- .attr(axis + '2', function(d,i) { return scale(getData(d,i)) })
-
-
- scale0 = scale.copy();
-
- });
- renderWatch.renderEnd('distribution immediate');
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
- chart.options = nv.utils.optionsFunc.bind(chart);
- chart.dispatch = dispatch;
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
- margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
- margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
- margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.axis = function(_) {
- if (!arguments.length) return axis;
- axis = _;
- return chart;
- };
-
- chart.size = function(_) {
- if (!arguments.length) return size;
- size = _;
- return chart;
- };
-
- chart.getData = function(_) {
- if (!arguments.length) return getData;
- getData = d3.functor(_);
- return chart;
- };
-
- chart.scale = function(_) {
- if (!arguments.length) return scale;
- scale = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return chart;
- };
-
- chart.duration = function(_) {
- if (!arguments.length) return duration;
- duration = _;
- renderWatch.reset(duration);
- return chart;
- };
- //============================================================
-
-
- return chart;
-}
-nv.models.furiousLegend = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 5, right: 0, bottom: 5, left: 0}
- , width = 400
- , height = 20
- , getKey = function(d) { return d.key }
- , color = nv.utils.getColor()
- , align = true
- , padding = 28 //define how much space between legend items. - recommend 32 for furious version
- , rightAlign = true
- , updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch.
- , radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time)
- , expanded = false
- , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange')
- , vers = 'classic' //Options are "classic" and "furious"
- ;
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- container = d3.select(this);
- nv.utils.initSVG(container);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-legend').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g');
- var g = wrap.select('g');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- var series = g.selectAll('.nv-series')
- .data(function(d) {
- if(vers != 'furious') return d;
-
- return d.filter(function(n) {
- return expanded ? true : !n.disengaged;
- });
- });
- var seriesEnter = series.enter().append('g').attr('class', 'nv-series')
-
- var seriesShape;
-
- if(vers == 'classic') {
- seriesEnter.append('circle')
- .style('stroke-width', 2)
- .attr('class','nv-legend-symbol')
- .attr('r', 5);
-
- seriesShape = series.select('circle');
- } else if (vers == 'furious') {
- seriesEnter.append('rect')
- .style('stroke-width', 2)
- .attr('class','nv-legend-symbol')
- .attr('rx', 3)
- .attr('ry', 3);
-
- seriesShape = series.select('rect');
-
- seriesEnter.append('g')
- .attr('class', 'nv-check-box')
- .property('innerHTML','<path d="M0.5,5 L22.5,5 L22.5,26.5 L0.5,26.5 L0.5,5 Z" class="nv-box"></path><path d="M5.5,12.8618467 L11.9185089,19.2803556 L31,0.198864511" class="nv-check"></path>')
- .attr('transform', 'translate(-10,-8)scale(0.5)');
-
- var seriesCheckbox = series.select('.nv-check-box');
-
- seriesCheckbox.each(function(d,i) {
- d3.select(this).selectAll('path')
- .attr('stroke', setTextColor(d,i));
- });
- }
-
- seriesEnter.append('text')
- .attr('text-anchor', 'start')
- .attr('class','nv-legend-text')
- .attr('dy', '.32em')
- .attr('dx', '8');
-
- var seriesText = series.select('text.nv-legend-text');
-
- series
- .on('mouseover', function(d,i) {
- dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects
- })
- .on('mouseout', function(d,i) {
- dispatch.legendMouseout(d,i);
- })
- .on('click', function(d,i) {
- dispatch.legendClick(d,i);
- // make sure we re-get data in case it was modified
- var data = series.data();
- if (updateState) {
- if(vers =='classic') {
- if (radioButtonMode) {
- //Radio button mode: set every series to disabled,
- // and enable the clicked series.
- data.forEach(function(series) { series.disabled = true});
- d.disabled = false;
- }
- else {
- d.disabled = !d.disabled;
- if (data.every(function(series) { return series.disabled})) {
- //the default behavior of NVD3 legends is, if every single series
- // is disabled, turn all series' back on.
- data.forEach(function(series) { series.disabled = false});
- }
- }
- } else if(vers == 'furious') {
- if(expanded) {
- d.disengaged = !d.disengaged;
- d.userDisabled = d.userDisabled == undefined ? !!d.disabled : d.userDisabled;
- d.disabled = d.disengaged || d.userDisabled;
- } else if (!expanded) {
- d.disabled = !d.disabled;
- d.userDisabled = d.disabled;
- var engaged = data.filter(function(d) { return !d.disengaged; });
- if (engaged.every(function(series) { return series.userDisabled })) {
- //the default behavior of NVD3 legends is, if every single series
- // is disabled, turn all series' back on.
- data.forEach(function(series) {
- series.disabled = series.userDisabled = false;
- });
- }
- }
- }
- dispatch.stateChange({
- disabled: data.map(function(d) { return !!d.disabled }),
- disengaged: data.map(function(d) { return !!d.disengaged })
- });
-
- }
- })
- .on('dblclick', function(d,i) {
- if(vers == 'furious' && expanded) return;
- dispatch.legendDblclick(d,i);
- if (updateState) {
- // make sure we re-get data in case it was modified
- var data = series.data();
- //the default behavior of NVD3 legends, when double clicking one,
- // is to set all other series' to false, and make the double clicked series enabled.
- data.forEach(function(series) {
- series.disabled = true;
- if(vers == 'furious') series.userDisabled = series.disabled;
- });
- d.disabled = false;
- if(vers == 'furious') d.userDisabled = d.disabled;
- dispatch.stateChange({
- disabled: data.map(function(d) { return !!d.disabled })
- });
- }
- });
-
- series.classed('nv-disabled', function(d) { return d.userDisabled });
- series.exit().remove();
-
- seriesText
- .attr('fill', setTextColor)
- .text(getKey);
-
- //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)
- // NEW ALIGNING CODE, TODO: clean up
-
- var versPadding;
- switch(vers) {
- case 'furious' :
- versPadding = 23;
- break;
- case 'classic' :
- versPadding = 20;
- }
-
- if (align) {
-
- var seriesWidths = [];
- series.each(function(d,i) {
- var legendText = d3.select(this).select('text');
- var nodeTextLength;
- try {
- nodeTextLength = legendText.node().getComputedTextLength();
- // If the legendText is display:none'd (nodeTextLength == 0), simulate an error so we approximate, instead
- if(nodeTextLength <= 0) throw Error();
- }
- catch(e) {
- nodeTextLength = nv.utils.calcApproxTextWidth(legendText);
- }
-
- seriesWidths.push(nodeTextLength + padding);
- });
-
- var seriesPerRow = 0;
- var legendWidth = 0;
- var columnWidths = [];
-
- while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) {
- columnWidths[seriesPerRow] = seriesWidths[seriesPerRow];
- legendWidth += seriesWidths[seriesPerRow++];
- }
- if (seriesPerRow === 0) seriesPerRow = 1; //minimum of one series per row
-
- while ( legendWidth > availableWidth && seriesPerRow > 1 ) {
- columnWidths = [];
- seriesPerRow--;
-
- for (var k = 0; k < seriesWidths.length; k++) {
- if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) )
- columnWidths[k % seriesPerRow] = seriesWidths[k];
- }
-
- legendWidth = columnWidths.reduce(function(prev, cur, index, array) {
- return prev + cur;
- });
- }
-
- var xPositions = [];
- for (var i = 0, curX = 0; i < seriesPerRow; i++) {
- xPositions[i] = curX;
- curX += columnWidths[i];
- }
-
- series
- .attr('transform', function(d, i) {
- return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * versPadding) + ')';
- });
-
- //position legend as far right as possible within the total width
- if (rightAlign) {
- g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')');
- }
- else {
- g.attr('transform', 'translate(0' + ',' + margin.top + ')');
- }
-
- height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * versPadding);
-
- } else {
-
- var ypos = 5,
- newxpos = 5,
- maxwidth = 0,
- xpos;
- series
- .attr('transform', function(d, i) {
- var length = d3.select(this).select('text').node().getComputedTextLength() + padding;
- xpos = newxpos;
-
- if (width < margin.left + margin.right + xpos + length) {
- newxpos = xpos = 5;
- ypos += versPadding;
- }
-
- newxpos += length;
- if (newxpos > maxwidth) maxwidth = newxpos;
-
- return 'translate(' + xpos + ',' + ypos + ')';
- });
-
- //position legend as far right as possible within the total width
- g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')');
-
- height = margin.top + margin.bottom + ypos + 15;
- }
-
- if(vers == 'furious') {
- // Size rectangles after text is placed
- seriesShape
- .attr('width', function(d,i) {
- return seriesText[0][i].getComputedTextLength() + 27;
- })
- .attr('height', 18)
- .attr('y', -9)
- .attr('x', -15)
- }
-
- seriesShape
- .style('fill', setBGColor)
- .style('stroke', function(d,i) { return d.color || color(d, i) });
- });
-
- function setTextColor(d,i) {
- if(vers != 'furious') return '#000';
- if(expanded) {
- return d.disengaged ? color(d,i) : '#fff';
- } else if (!expanded) {
- return !!d.disabled ? color(d,i) : '#fff';
- }
- }
-
- function setBGColor(d,i) {
- if(expanded && vers == 'furious') {
- return d.disengaged ? '#fff' : color(d,i);
- } else {
- return !!d.disabled ? '#fff' : color(d,i);
- }
- }
-
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- key: {get: function(){return getKey;}, set: function(_){getKey=_;}},
- align: {get: function(){return align;}, set: function(_){align=_;}},
- rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
- padding: {get: function(){return padding;}, set: function(_){padding=_;}},
- updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},
- radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
- expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},
- vers: {get: function(){return vers;}, set: function(_){vers=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }}
- });
-
- nv.utils.initOptions(chart);
-
- return chart;
-};
-//TODO: consider deprecating and using multibar with single series for this
-nv.models.historicalBar = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = null
- , height = null
- , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
- , container = null
- , x = d3.scale.linear()
- , y = d3.scale.linear()
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , forceX = []
- , forceY = [0]
- , padData = false
- , clipEdge = true
- , color = nv.utils.defaultColor()
- , xDomain
- , yDomain
- , xRange
- , yRange
- , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
- , interactive = true
- ;
-
- var renderWatch = nv.utils.renderWatch(dispatch, 0);
-
- function chart(selection) {
- selection.each(function(data) {
- renderWatch.reset();
-
- container = d3.select(this);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- nv.utils.initSVG(container);
-
- // Setup Scales
- x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ));
-
- if (padData)
- x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);
- else
- x.range(xRange || [0, availableWidth]);
-
- y.domain(yDomain || d3.extent(data[0].values.map(getY).concat(forceY) ))
- .range(yRange || [availableHeight, 0]);
-
- // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
- if (x.domain()[0] === x.domain()[1])
- x.domain()[0] ?
- x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])
- : x.domain([-1,1]);
-
- if (y.domain()[0] === y.domain()[1])
- y.domain()[0] ?
- y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])
- : y.domain([-1,1]);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-historicalBar-' + id).data([data[0].values]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBar-' + id);
- var defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-bars');
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- container
- .on('click', function(d,i) {
- dispatch.chartClick({
- data: d,
- index: i,
- pos: d3.event,
- id: id
- });
- });
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-chart-clip-path-' + id)
- .append('rect');
-
- wrap.select('#nv-chart-clip-path-' + id + ' rect')
- .attr('width', availableWidth)
- .attr('height', availableHeight);
-
- g.attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : '');
-
- var bars = wrap.select('.nv-bars').selectAll('.nv-bar')
- .data(function(d) { return d }, function(d,i) {return getX(d,i)});
- bars.exit().remove();
-
- bars.enter().append('rect')
- .attr('x', 0 )
- .attr('y', function(d,i) { return nv.utils.NaNtoZero(y(Math.max(0, getY(d,i)))) })
- .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.abs(y(getY(d,i)) - y(0))) })
- .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; })
- .on('mouseover', function(d,i) {
- if (!interactive) return;
- d3.select(this).classed('hover', true);
- dispatch.elementMouseover({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
-
- })
- .on('mouseout', function(d,i) {
- if (!interactive) return;
- d3.select(this).classed('hover', false);
- dispatch.elementMouseout({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- })
- .on('mousemove', function(d,i) {
- if (!interactive) return;
- dispatch.elementMousemove({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- })
- .on('click', function(d,i) {
- if (!interactive) return;
- dispatch.elementClick({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- d3.event.stopPropagation();
- })
- .on('dblclick', function(d,i) {
- if (!interactive) return;
- dispatch.elementDblClick({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- d3.event.stopPropagation();
- });
-
- bars
- .attr('fill', function(d,i) { return color(d, i); })
- .attr('class', function(d,i,j) { return (getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive') + ' nv-bar-' + j + '-' + i })
- .watchTransition(renderWatch, 'bars')
- .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; })
- //TODO: better width calculations that don't assume always uniform data spacing;w
- .attr('width', (availableWidth / data[0].values.length) * .9 );
-
- bars.watchTransition(renderWatch, 'bars')
- .attr('y', function(d,i) {
- var rval = getY(d,i) < 0 ?
- y(0) :
- y(0) - y(getY(d,i)) < 1 ?
- y(0) - 1 :
- y(getY(d,i));
- return nv.utils.NaNtoZero(rval);
- })
- .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.max(Math.abs(y(getY(d,i)) - y(0)),1)) });
-
- });
-
- renderWatch.renderEnd('historicalBar immediate');
- return chart;
- }
-
- //Create methods to allow outside functions to highlight a specific bar.
- chart.highlightPoint = function(pointIndex, isHoverOver) {
- container
- .select(".nv-bars .nv-bar-0-" + pointIndex)
- .classed("hover", isHoverOver)
- ;
- };
-
- chart.clearHighlights = function() {
- container
- .select(".nv-bars .nv-bar.hover")
- .classed("hover", false)
- ;
- };
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}},
- forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},
- padData: {get: function(){return padData;}, set: function(_){padData=_;}},
- x: {get: function(){return getX;}, set: function(_){getX=_;}},
- y: {get: function(){return getY;}, set: function(_){getY=_;}},
- xScale: {get: function(){return x;}, set: function(_){x=_;}},
- yScale: {get: function(){return y;}, set: function(_){y=_;}},
- xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
- yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
- xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},
- yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},
- clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
- id: {get: function(){return id;}, set: function(_){id=_;}},
- interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }}
- });
-
- nv.utils.initOptions(chart);
-
- return chart;
-};
-
-nv.models.historicalBarChart = function(bar_model) {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var bars = bar_model || nv.models.historicalBar()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- , interactiveLayer = nv.interactiveGuideline()
- , tooltip = nv.models.tooltip()
- ;
-
-
- var margin = {top: 30, right: 90, bottom: 50, left: 90}
- , color = nv.utils.defaultColor()
- , width = null
- , height = null
- , showLegend = false
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = false
- , useInteractiveGuideline = false
- , x
- , y
- , state = {}
- , defaultState = null
- , noData = null
- , dispatch = d3.dispatch('tooltipHide', 'stateChange', 'changeState', 'renderEnd')
- , transitionDuration = 250
- ;
-
- xAxis.orient('bottom').tickPadding(7);
- yAxis.orient( (rightAlignYAxis) ? 'right' : 'left');
- tooltip
- .duration(0)
- .headerEnabled(false)
- .valueFormatter(function(d, i) {
- return yAxis.tickFormat()(d, i);
- })
- .headerFormatter(function(d, i) {
- return xAxis.tickFormat()(d, i);
- });
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var renderWatch = nv.utils.renderWatch(dispatch, 0);
-
- function chart(selection) {
- selection.each(function(data) {
- renderWatch.reset();
- renderWatch.models(bars);
- if (showXAxis) renderWatch.models(xAxis);
- if (showYAxis) renderWatch.models(yAxis);
-
- var container = d3.select(this),
- that = this;
- nv.utils.initSVG(container);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- chart.update = function() { container.transition().duration(transitionDuration).call(chart) };
- chart.container = this;
-
- //set state.disabled
- state.disabled = data.map(function(d) { return !!d.disabled });
-
- if (!defaultState) {
- var key;
- defaultState = {};
- for (key in state) {
- if (state[key] instanceof Array)
- defaultState[key] = state[key].slice(0);
- else
- defaultState[key] = state[key];
- }
- }
-
- // Display noData message if there's nothing to show.
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
- nv.utils.noData(chart, container)
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- // Setup Scales
- x = bars.xScale();
- y = bars.yScale();
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-historicalBarChart').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBarChart').append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis');
- gEnter.append('g').attr('class', 'nv-barsWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
- gEnter.append('g').attr('class', 'nv-interactive');
-
- // Legend
- if (showLegend) {
- legend.width(availableWidth);
-
- g.select('.nv-legendWrap')
- .datum(data)
- .call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- availableHeight = nv.utils.availableHeight(height, container, margin);
- }
-
- wrap.select('.nv-legendWrap')
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- }
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- //Set up interactive layer
- if (useInteractiveGuideline) {
- interactiveLayer
- .width(availableWidth)
- .height(availableHeight)
- .margin({left:margin.left, top:margin.top})
- .svgContainer(container)
- .xScale(x);
- wrap.select(".nv-interactive").call(interactiveLayer);
- }
- bars
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
-
- var barsWrap = g.select('.nv-barsWrap')
- .datum(data.filter(function(d) { return !d.disabled }));
- barsWrap.transition().call(bars);
-
- // Setup Axes
- if (showXAxis) {
- xAxis
- .scale(x)
- ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y.range()[0] + ')');
- g.select('.nv-x.nv-axis')
- .transition()
- .call(xAxis);
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis')
- .transition()
- .call(yAxis);
- }
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- interactiveLayer.dispatch.on('elementMousemove', function(e) {
- bars.clearHighlights();
-
- var singlePoint, pointIndex, pointXLocation, allData = [];
- data
- .filter(function(series, i) {
- series.seriesIndex = i;
- return !series.disabled;
- })
- .forEach(function(series,i) {
- pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
- bars.highlightPoint(pointIndex,true);
- var point = series.values[pointIndex];
- if (point === undefined) return;
- if (singlePoint === undefined) singlePoint = point;
- if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
- allData.push({
- key: series.key,
- value: chart.y()(point, pointIndex),
- color: color(series,series.seriesIndex),
- data: series.values[pointIndex]
- });
- });
-
- var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));
- interactiveLayer.tooltip
- .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top})
- .chartContainer(that.parentNode)
- .valueFormatter(function(d,i) {
- return yAxis.tickFormat()(d);
- })
- .data({
- value: xValue,
- index: pointIndex,
- series: allData
- })();
-
- interactiveLayer.renderGuideLine(pointXLocation);
-
- });
-
- interactiveLayer.dispatch.on("elementMouseout",function(e) {
- dispatch.tooltipHide();
- bars.clearHighlights();
- });
-
- legend.dispatch.on('legendClick', function(d,i) {
- d.disabled = !d.disabled;
-
- if (!data.filter(function(d) { return !d.disabled }).length) {
- data.map(function(d) {
- d.disabled = false;
- wrap.selectAll('.nv-series').classed('disabled', false);
- return d;
- });
- }
-
- state.disabled = data.map(function(d) { return !!d.disabled });
- dispatch.stateChange(state);
-
- selection.transition().call(chart);
- });
-
- legend.dispatch.on('legendDblclick', function(d) {
- //Double clicking should always enable current series, and disabled all others.
- data.forEach(function(d) {
- d.disabled = true;
- });
- d.disabled = false;
-
- state.disabled = data.map(function(d) { return !!d.disabled });
- dispatch.stateChange(state);
- chart.update();
- });
-
- dispatch.on('changeState', function(e) {
- if (typeof e.disabled !== 'undefined') {
- data.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
-
- state.disabled = e.disabled;
- }
-
- chart.update();
- });
- });
-
- renderWatch.renderEnd('historicalBarChart immediate');
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- bars.dispatch.on('elementMouseover.tooltip', function(evt) {
- evt['series'] = {
- key: chart.x()(evt.data),
- value: chart.y()(evt.data),
- color: evt.color
- };
- tooltip.data(evt).hidden(false);
- });
-
- bars.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true);
- });
-
- bars.dispatch.on('elementMousemove.tooltip', function(evt) {
- tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
- });
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.dispatch = dispatch;
- chart.bars = bars;
- chart.legend = legend;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.interactiveLayer = interactiveLayer;
- chart.tooltip = tooltip;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
- showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
- showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- legend.color(color);
- bars.color(color);
- }},
- duration: {get: function(){return transitionDuration;}, set: function(_){
- transitionDuration=_;
- renderWatch.reset(transitionDuration);
- yAxis.duration(transitionDuration);
- xAxis.duration(transitionDuration);
- }},
- rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- }},
- useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){
- useInteractiveGuideline = _;
- if (_ === true) {
- chart.interactive(false);
- }
- }}
- });
-
- nv.utils.inheritOptions(chart, bars);
- nv.utils.initOptions(chart);
-
- return chart;
-};
-
-
-// ohlcChart is just a historical chart with ohlc bars and some tweaks
-nv.models.ohlcBarChart = function() {
- var chart = nv.models.historicalBarChart(nv.models.ohlcBar());
-
- // special default tooltip since we show multiple values per x
- chart.useInteractiveGuideline(true);
- chart.interactiveLayer.tooltip.contentGenerator(function(data) {
- // we assume only one series exists for this chart
- var d = data.series[0].data;
- // match line colors as defined in nv.d3.css
- var color = d.open < d.close ? "2ca02c" : "d62728";
- return '' +
- '<h3 style="color: #' + color + '">' + data.value + '</h3>' +
- '<table>' +
- '<tr><td>open:</td><td>' + chart.yAxis.tickFormat()(d.open) + '</td></tr>' +
- '<tr><td>close:</td><td>' + chart.yAxis.tickFormat()(d.close) + '</td></tr>' +
- '<tr><td>high</td><td>' + chart.yAxis.tickFormat()(d.high) + '</td></tr>' +
- '<tr><td>low:</td><td>' + chart.yAxis.tickFormat()(d.low) + '</td></tr>' +
- '</table>';
- });
- return chart;
-};
-
-// candlestickChart is just a historical chart with candlestick bars and some tweaks
-nv.models.candlestickBarChart = function() {
- var chart = nv.models.historicalBarChart(nv.models.candlestickBar());
-
- // special default tooltip since we show multiple values per x
- chart.useInteractiveGuideline(true);
- chart.interactiveLayer.tooltip.contentGenerator(function(data) {
- // we assume only one series exists for this chart
- var d = data.series[0].data;
- // match line colors as defined in nv.d3.css
- var color = d.open < d.close ? "2ca02c" : "d62728";
- return '' +
- '<h3 style="color: #' + color + '">' + data.value + '</h3>' +
- '<table>' +
- '<tr><td>open:</td><td>' + chart.yAxis.tickFormat()(d.open) + '</td></tr>' +
- '<tr><td>close:</td><td>' + chart.yAxis.tickFormat()(d.close) + '</td></tr>' +
- '<tr><td>high</td><td>' + chart.yAxis.tickFormat()(d.high) + '</td></tr>' +
- '<tr><td>low:</td><td>' + chart.yAxis.tickFormat()(d.low) + '</td></tr>' +
- '</table>';
- });
- return chart;
-};
-nv.models.legend = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 5, right: 0, bottom: 5, left: 0}
- , width = 400
- , height = 20
- , getKey = function(d) { return d.key }
- , color = nv.utils.getColor()
- , align = true
- , padding = 32 //define how much space between legend items. - recommend 32 for furious version
- , rightAlign = true
- , updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch.
- , radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time)
- , expanded = false
- , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange')
- , vers = 'classic' //Options are "classic" and "furious"
- ;
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- container = d3.select(this);
- nv.utils.initSVG(container);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-legend').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g');
- var g = wrap.select('g');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- var series = g.selectAll('.nv-series')
- .data(function(d) {
- if(vers != 'furious') return d;
-
- return d.filter(function(n) {
- return expanded ? true : !n.disengaged;
- });
- });
-
- var seriesEnter = series.enter().append('g').attr('class', 'nv-series');
- var seriesShape;
-
- var versPadding;
- switch(vers) {
- case 'furious' :
- versPadding = 23;
- break;
- case 'classic' :
- versPadding = 20;
- }
-
- if(vers == 'classic') {
- seriesEnter.append('circle')
- .style('stroke-width', 2)
- .attr('class','nv-legend-symbol')
- .attr('r', 5);
-
- seriesShape = series.select('circle');
- } else if (vers == 'furious') {
- seriesEnter.append('rect')
- .style('stroke-width', 2)
- .attr('class','nv-legend-symbol')
- .attr('rx', 3)
- .attr('ry', 3);
-
- seriesShape = series.select('.nv-legend-symbol');
-
- seriesEnter.append('g')
- .attr('class', 'nv-check-box')
- .property('innerHTML','<path d="M0.5,5 L22.5,5 L22.5,26.5 L0.5,26.5 L0.5,5 Z" class="nv-box"></path><path d="M5.5,12.8618467 L11.9185089,19.2803556 L31,0.198864511" class="nv-check"></path>')
- .attr('transform', 'translate(-10,-8)scale(0.5)');
-
- var seriesCheckbox = series.select('.nv-check-box');
-
- seriesCheckbox.each(function(d,i) {
- d3.select(this).selectAll('path')
- .attr('stroke', setTextColor(d,i));
- });
- }
-
- seriesEnter.append('text')
- .attr('text-anchor', 'start')
- .attr('class','nv-legend-text')
- .attr('dy', '.32em')
- .attr('dx', '8');
-
- var seriesText = series.select('text.nv-legend-text');
-
- series
- .on('mouseover', function(d,i) {
- dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects
- })
- .on('mouseout', function(d,i) {
- dispatch.legendMouseout(d,i);
- })
- .on('click', function(d,i) {
- dispatch.legendClick(d,i);
- // make sure we re-get data in case it was modified
- var data = series.data();
- if (updateState) {
- if(vers =='classic') {
- if (radioButtonMode) {
- //Radio button mode: set every series to disabled,
- // and enable the clicked series.
- data.forEach(function(series) { series.disabled = true});
- d.disabled = false;
- }
- else {
- d.disabled = !d.disabled;
- if (data.every(function(series) { return series.disabled})) {
- //the default behavior of NVD3 legends is, if every single series
- // is disabled, turn all series' back on.
- data.forEach(function(series) { series.disabled = false});
- }
- }
- } else if(vers == 'furious') {
- if(expanded) {
- d.disengaged = !d.disengaged;
- d.userDisabled = d.userDisabled == undefined ? !!d.disabled : d.userDisabled;
- d.disabled = d.disengaged || d.userDisabled;
- } else if (!expanded) {
- d.disabled = !d.disabled;
- d.userDisabled = d.disabled;
- var engaged = data.filter(function(d) { return !d.disengaged; });
- if (engaged.every(function(series) { return series.userDisabled })) {
- //the default behavior of NVD3 legends is, if every single series
- // is disabled, turn all series' back on.
- data.forEach(function(series) {
- series.disabled = series.userDisabled = false;
- });
- }
- }
- }
- dispatch.stateChange({
- disabled: data.map(function(d) { return !!d.disabled }),
- disengaged: data.map(function(d) { return !!d.disengaged })
- });
-
- }
- })
- .on('dblclick', function(d,i) {
- if(vers == 'furious' && expanded) return;
- dispatch.legendDblclick(d,i);
- if (updateState) {
- // make sure we re-get data in case it was modified
- var data = series.data();
- //the default behavior of NVD3 legends, when double clicking one,
- // is to set all other series' to false, and make the double clicked series enabled.
- data.forEach(function(series) {
- series.disabled = true;
- if(vers == 'furious') series.userDisabled = series.disabled;
- });
- d.disabled = false;
- if(vers == 'furious') d.userDisabled = d.disabled;
- dispatch.stateChange({
- disabled: data.map(function(d) { return !!d.disabled })
- });
- }
- });
-
- series.classed('nv-disabled', function(d) { return d.userDisabled });
- series.exit().remove();
-
- seriesText
- .attr('fill', setTextColor)
- .text(getKey);
-
- //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)
- // NEW ALIGNING CODE, TODO: clean up
- var legendWidth = 0;
- if (align) {
-
- var seriesWidths = [];
- series.each(function(d,i) {
- var legendText = d3.select(this).select('text');
- var nodeTextLength;
- try {
- nodeTextLength = legendText.node().getComputedTextLength();
- // If the legendText is display:none'd (nodeTextLength == 0), simulate an error so we approximate, instead
- if(nodeTextLength <= 0) throw Error();
- }
- catch(e) {
- nodeTextLength = nv.utils.calcApproxTextWidth(legendText);
- }
-
- seriesWidths.push(nodeTextLength + padding);
- });
-
- var seriesPerRow = 0;
- var columnWidths = [];
- legendWidth = 0;
-
- while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) {
- columnWidths[seriesPerRow] = seriesWidths[seriesPerRow];
- legendWidth += seriesWidths[seriesPerRow++];
- }
- if (seriesPerRow === 0) seriesPerRow = 1; //minimum of one series per row
-
- while ( legendWidth > availableWidth && seriesPerRow > 1 ) {
- columnWidths = [];
- seriesPerRow--;
-
- for (var k = 0; k < seriesWidths.length; k++) {
- if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) )
- columnWidths[k % seriesPerRow] = seriesWidths[k];
- }
-
- legendWidth = columnWidths.reduce(function(prev, cur, index, array) {
- return prev + cur;
- });
- }
-
- var xPositions = [];
- for (var i = 0, curX = 0; i < seriesPerRow; i++) {
- xPositions[i] = curX;
- curX += columnWidths[i];
- }
-
- series
- .attr('transform', function(d, i) {
- return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * versPadding) + ')';
- });
-
- //position legend as far right as possible within the total width
- if (rightAlign) {
- g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')');
- }
- else {
- g.attr('transform', 'translate(0' + ',' + margin.top + ')');
- }
-
- height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * versPadding);
-
- } else {
-
- var ypos = 5,
- newxpos = 5,
- maxwidth = 0,
- xpos;
- series
- .attr('transform', function(d, i) {
- var length = d3.select(this).select('text').node().getComputedTextLength() + padding;
- xpos = newxpos;
-
- if (width < margin.left + margin.right + xpos + length) {
- newxpos = xpos = 5;
- ypos += versPadding;
- }
-
- newxpos += length;
- if (newxpos > maxwidth) maxwidth = newxpos;
-
- if(legendWidth < xpos + maxwidth) {
- legendWidth = xpos + maxwidth;
- }
- return 'translate(' + xpos + ',' + ypos + ')';
- });
-
- //position legend as far right as possible within the total width
- g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')');
-
- height = margin.top + margin.bottom + ypos + 15;
- }
-
- if(vers == 'furious') {
- // Size rectangles after text is placed
- seriesShape
- .attr('width', function(d,i) {
- return seriesText[0][i].getComputedTextLength() + 27;
- })
- .attr('height', 18)
- .attr('y', -9)
- .attr('x', -15);
-
- // The background for the expanded legend (UI)
- gEnter.insert('rect',':first-child')
- .attr('class', 'nv-legend-bg')
- .attr('fill', '#eee')
- // .attr('stroke', '#444')
- .attr('opacity',0);
-
- var seriesBG = g.select('.nv-legend-bg');
-
- seriesBG
- .transition().duration(300)
- .attr('x', -versPadding )
- .attr('width', legendWidth + versPadding - 12)
- .attr('height', height + 10)
- .attr('y', -margin.top - 10)
- .attr('opacity', expanded ? 1 : 0);
-
-
- }
-
- seriesShape
- .style('fill', setBGColor)
- .style('fill-opacity', setBGOpacity)
- .style('stroke', setBGColor);
- });
-
- function setTextColor(d,i) {
- if(vers != 'furious') return '#000';
- if(expanded) {
- return d.disengaged ? '#000' : '#fff';
- } else if (!expanded) {
- if(!d.color) d.color = color(d,i);
- return !!d.disabled ? d.color : '#fff';
- }
- }
-
- function setBGColor(d,i) {
- if(expanded && vers == 'furious') {
- return d.disengaged ? '#eee' : d.color || color(d,i);
- } else {
- return d.color || color(d,i);
- }
- }
-
-
- function setBGOpacity(d,i) {
- if(expanded && vers == 'furious') {
- return 1;
- } else {
- return !!d.disabled ? 0 : 1;
- }
- }
-
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- key: {get: function(){return getKey;}, set: function(_){getKey=_;}},
- align: {get: function(){return align;}, set: function(_){align=_;}},
- rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
- padding: {get: function(){return padding;}, set: function(_){padding=_;}},
- updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},
- radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
- expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},
- vers: {get: function(){return vers;}, set: function(_){vers=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }}
- });
-
- nv.utils.initOptions(chart);
-
- return chart;
-};
-
-nv.models.line = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var scatter = nv.models.scatter()
- ;
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 960
- , height = 500
- , container = null
- , strokeWidth = 1.5
- , color = nv.utils.defaultColor() // a function that returns a color
- , getX = function(d) { return d.x } // accessor to get the x value from a data point
- , getY = function(d) { return d.y } // accessor to get the y value from a data point
- , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continuous when it is not defined
- , isArea = function(d) { return d.area } // decides if a line is an area or just a line
- , clipEdge = false // if true, masks lines within x and y scale
- , x //can be accessed via chart.xScale()
- , y //can be accessed via chart.yScale()
- , interpolate = "linear" // controls the line interpolation
- , duration = 250
- , dispatch = d3.dispatch('elementClick', 'elementMouseover', 'elementMouseout', 'renderEnd')
- ;
-
- scatter
- .pointSize(16) // default size
- .pointDomain([16,256]) //set to speed up calculation, needs to be unset if there is a custom size accessor
- ;
-
- //============================================================
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0 //used to store previous scales
- , renderWatch = nv.utils.renderWatch(dispatch, duration)
- ;
-
- //============================================================
-
-
- function chart(selection) {
- renderWatch.reset();
- renderWatch.models(scatter);
- selection.each(function(data) {
- container = d3.select(this);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
- nv.utils.initSVG(container);
-
- // Setup Scales
- x = scatter.xScale();
- y = scatter.yScale();
-
- x0 = x0 || x;
- y0 = y0 || y;
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-line').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-line');
- var defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-groups');
- gEnter.append('g').attr('class', 'nv-scatterWrap');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- scatter
- .width(availableWidth)
- .height(availableHeight);
-
- var scatterWrap = wrap.select('.nv-scatterWrap');
- scatterWrap.call(scatter);
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-edge-clip-' + scatter.id())
- .append('rect');
-
- wrap.select('#nv-edge-clip-' + scatter.id() + ' rect')
- .attr('width', availableWidth)
- .attr('height', (availableHeight > 0) ? availableHeight : 0);
-
- g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');
- scatterWrap
- .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');
-
- var groups = wrap.select('.nv-groups').selectAll('.nv-group')
- .data(function(d) { return d }, function(d) { return d.key });
- groups.enter().append('g')
- .style('stroke-opacity', 1e-6)
- .style('stroke-width', function(d) { return d.strokeWidth || strokeWidth })
- .style('fill-opacity', 1e-6);
-
- groups.exit().remove();
-
- groups
- .attr('class', function(d,i) {
- return (d.classed || '') + ' nv-group nv-series-' + i;
- })
- .classed('hover', function(d) { return d.hover })
- .style('fill', function(d,i){ return color(d, i) })
- .style('stroke', function(d,i){ return color(d, i)});
- groups.watchTransition(renderWatch, 'line: groups')
- .style('stroke-opacity', 1)
- .style('fill-opacity', function(d) { return d.fillOpacity || .5});
-
- var areaPaths = groups.selectAll('path.nv-area')
- .data(function(d) { return isArea(d) ? [d] : [] }); // this is done differently than lines because I need to check if series is an area
- areaPaths.enter().append('path')
- .attr('class', 'nv-area')
- .attr('d', function(d) {
- return d3.svg.area()
- .interpolate(interpolate)
- .defined(defined)
- .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })
- .y0(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })
- .y1(function(d,i) { return y0( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) })
- //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this
- .apply(this, [d.values])
- });
- groups.exit().selectAll('path.nv-area')
- .remove();
-
- areaPaths.watchTransition(renderWatch, 'line: areaPaths')
- .attr('d', function(d) {
- return d3.svg.area()
- .interpolate(interpolate)
- .defined(defined)
- .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
- .y0(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
- .y1(function(d,i) { return y( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) })
- //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this
- .apply(this, [d.values])
- });
-
- var linePaths = groups.selectAll('path.nv-line')
- .data(function(d) { return [d.values] });
-
- linePaths.enter().append('path')
- .attr('class', 'nv-line')
- .attr('d',
- d3.svg.line()
- .interpolate(interpolate)
- .defined(defined)
- .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })
- .y(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })
- );
-
- linePaths.watchTransition(renderWatch, 'line: linePaths')
- .attr('d',
- d3.svg.line()
- .interpolate(interpolate)
- .defined(defined)
- .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
- .y(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
- );
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
- });
- renderWatch.renderEnd('line immediate');
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.scatter = scatter;
- // Pass through events
- scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); });
- scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); });
- scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); });
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- defined: {get: function(){return defined;}, set: function(_){defined=_;}},
- interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}},
- clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- scatter.duration(duration);
- }},
- isArea: {get: function(){return isArea;}, set: function(_){
- isArea = d3.functor(_);
- }},
- x: {get: function(){return getX;}, set: function(_){
- getX = _;
- scatter.x(_);
- }},
- y: {get: function(){return getY;}, set: function(_){
- getY = _;
- scatter.y(_);
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- scatter.color(color);
- }}
- });
-
- nv.utils.inheritOptions(chart, scatter);
- nv.utils.initOptions(chart);
-
- return chart;
-};
-nv.models.lineChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var lines = nv.models.line()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- , interactiveLayer = nv.interactiveGuideline()
- , tooltip = nv.models.tooltip()
- ;
-
- var margin = {top: 30, right: 20, bottom: 50, left: 60}
- , color = nv.utils.defaultColor()
- , width = null
- , height = null
- , showLegend = true
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = false
- , useInteractiveGuideline = false
- , x
- , y
- , state = nv.utils.state()
- , defaultState = null
- , noData = null
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd')
- , duration = 250
- ;
-
- // set options on sub-objects for this chart
- xAxis.orient('bottom').tickPadding(7);
- yAxis.orient(rightAlignYAxis ? 'right' : 'left');
- tooltip.valueFormatter(function(d, i) {
- return yAxis.tickFormat()(d, i);
- }).headerFormatter(function(d, i) {
- return xAxis.tickFormat()(d, i);
- });
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var renderWatch = nv.utils.renderWatch(dispatch, duration);
-
- var stateGetter = function(data) {
- return function(){
- return {
- active: data.map(function(d) { return !d.disabled })
- };
- }
- };
-
- var stateSetter = function(data) {
- return function(state) {
- if (state.active !== undefined)
- data.forEach(function(series,i) {
- series.disabled = !state.active[i];
- });
- }
- };
-
- function chart(selection) {
- renderWatch.reset();
- renderWatch.models(lines);
- if (showXAxis) renderWatch.models(xAxis);
- if (showYAxis) renderWatch.models(yAxis);
-
- selection.each(function(data) {
- var container = d3.select(this),
- that = this;
- nv.utils.initSVG(container);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- chart.update = function() {
- if (duration === 0)
- container.call(chart);
- else
- container.transition().duration(duration).call(chart)
- };
- chart.container = this;
-
- state
- .setter(stateSetter(data), chart.update)
- .getter(stateGetter(data))
- .update();
-
- // DEPRECATED set state.disableddisabled
- state.disabled = data.map(function(d) { return !!d.disabled });
-
- if (!defaultState) {
- var key;
- defaultState = {};
- for (key in state) {
- if (state[key] instanceof Array)
- defaultState[key] = state[key].slice(0);
- else
- defaultState[key] = state[key];
- }
- }
-
- // Display noData message if there's nothing to show.
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
- nv.utils.noData(chart, container)
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
-
- // Setup Scales
- x = lines.xScale();
- y = lines.yScale();
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-lineChart').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineChart').append('g');
- var g = wrap.select('g');
-
- gEnter.append("rect").style("opacity",0);
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis');
- gEnter.append('g').attr('class', 'nv-linesWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
- gEnter.append('g').attr('class', 'nv-interactive');
-
- g.select("rect")
- .attr("width",availableWidth)
- .attr("height",(availableHeight > 0) ? availableHeight : 0);
-
- // Legend
- if (showLegend) {
- legend.width(availableWidth);
-
- g.select('.nv-legendWrap')
- .datum(data)
- .call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- availableHeight = nv.utils.availableHeight(height, container, margin);
- }
-
- wrap.select('.nv-legendWrap')
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- }
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- //Set up interactive layer
- if (useInteractiveGuideline) {
- interactiveLayer
- .width(availableWidth)
- .height(availableHeight)
- .margin({left:margin.left, top:margin.top})
- .svgContainer(container)
- .xScale(x);
- wrap.select(".nv-interactive").call(interactiveLayer);
- }
-
- lines
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
-
-
- var linesWrap = g.select('.nv-linesWrap')
- .datum(data.filter(function(d) { return !d.disabled }));
-
- linesWrap.call(lines);
-
- // Setup Axes
- if (showXAxis) {
- xAxis
- .scale(x)
- ._ticks(nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y.range()[0] + ')');
- g.select('.nv-x.nv-axis')
- .call(xAxis);
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- ._ticks(nv.utils.calcTicksY(availableHeight/36, data) )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis')
- .call(yAxis);
- }
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('stateChange', function(newState) {
- for (var key in newState)
- state[key] = newState[key];
- dispatch.stateChange(state);
- chart.update();
- });
-
- interactiveLayer.dispatch.on('elementMousemove', function(e) {
- lines.clearHighlights();
- var singlePoint, pointIndex, pointXLocation, allData = [];
- data
- .filter(function(series, i) {
- series.seriesIndex = i;
- return !series.disabled;
- })
- .forEach(function(series,i) {
- pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
- var point = series.values[pointIndex];
- var pointYValue = chart.y()(point, pointIndex);
- if (pointYValue != null) {
- lines.highlightPoint(i, pointIndex, true);
- }
- if (point === undefined) return;
- if (singlePoint === undefined) singlePoint = point;
- if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
- allData.push({
- key: series.key,
- value: pointYValue,
- color: color(series,series.seriesIndex)
- });
- });
- //Highlight the tooltip entry based on which point the mouse is closest to.
- if (allData.length > 2) {
- var yValue = chart.yScale().invert(e.mouseY);
- var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]);
- var threshold = 0.03 * domainExtent;
- var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold);
- if (indexToHighlight !== null)
- allData[indexToHighlight].highlight = true;
- }
-
- var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));
- interactiveLayer.tooltip
- .position({left: e.mouseX + margin.left, top: e.mouseY + margin.top})
- .chartContainer(that.parentNode)
- .valueFormatter(function(d,i) {
- return d == null ? "N/A" : yAxis.tickFormat()(d);
- })
- .data({
- value: xValue,
- index: pointIndex,
- series: allData
- })();
-
- interactiveLayer.renderGuideLine(pointXLocation);
-
- });
-
- interactiveLayer.dispatch.on('elementClick', function(e) {
- var pointXLocation, allData = [];
-
- data.filter(function(series, i) {
- series.seriesIndex = i;
- return !series.disabled;
- }).forEach(function(series) {
- var pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
- var point = series.values[pointIndex];
- if (typeof point === 'undefined') return;
- if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
- var yPos = chart.yScale()(chart.y()(point,pointIndex));
- allData.push({
- point: point,
- pointIndex: pointIndex,
- pos: [pointXLocation, yPos],
- seriesIndex: series.seriesIndex,
- series: series
- });
- });
-
- lines.dispatch.elementClick(allData);
- });
-
- interactiveLayer.dispatch.on("elementMouseout",function(e) {
- lines.clearHighlights();
- });
-
- dispatch.on('changeState', function(e) {
- if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) {
- data.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
-
- state.disabled = e.disabled;
- }
-
- chart.update();
- });
-
- });
-
- renderWatch.renderEnd('lineChart immediate');
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- lines.dispatch.on('elementMouseover.tooltip', function(evt) {
- tooltip.data(evt).position(evt.pos).hidden(false);
- });
-
- lines.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true)
- });
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.dispatch = dispatch;
- chart.lines = lines;
- chart.legend = legend;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.interactiveLayer = interactiveLayer;
- chart.tooltip = tooltip;
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
- showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
- showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- lines.duration(duration);
- xAxis.duration(duration);
- yAxis.duration(duration);
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- legend.color(color);
- lines.color(color);
- }},
- rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
- rightAlignYAxis = _;
- yAxis.orient( rightAlignYAxis ? 'right' : 'left');
- }},
- useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){
- useInteractiveGuideline = _;
- if (useInteractiveGuideline) {
- lines.interactive(false);
- lines.useVoronoi(false);
- }
- }}
- });
-
- nv.utils.inheritOptions(chart, lines);
- nv.utils.initOptions(chart);
-
- return chart;
-};
-nv.models.linePlusBarChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var lines = nv.models.line()
- , lines2 = nv.models.line()
- , bars = nv.models.historicalBar()
- , bars2 = nv.models.historicalBar()
- , xAxis = nv.models.axis()
- , x2Axis = nv.models.axis()
- , y1Axis = nv.models.axis()
- , y2Axis = nv.models.axis()
- , y3Axis = nv.models.axis()
- , y4Axis = nv.models.axis()
- , legend = nv.models.legend()
- , brush = d3.svg.brush()
- , tooltip = nv.models.tooltip()
- ;
-
- var margin = {top: 30, right: 30, bottom: 30, left: 60}
- , margin2 = {top: 0, right: 30, bottom: 20, left: 60}
- , width = null
- , height = null
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , color = nv.utils.defaultColor()
- , showLegend = true
- , focusEnable = true
- , focusShowAxisY = false
- , focusShowAxisX = true
- , focusHeight = 50
- , extent
- , brushExtent = null
- , x
- , x2
- , y1
- , y2
- , y3
- , y4
- , noData = null
- , dispatch = d3.dispatch('brush', 'stateChange', 'changeState')
- , transitionDuration = 0
- , state = nv.utils.state()
- , defaultState = null
- , legendLeftAxisHint = ' (left axis)'
- , legendRightAxisHint = ' (right axis)'
- ;
-
- lines.clipEdge(true);
- lines2.interactive(false);
- xAxis.orient('bottom').tickPadding(5);
- y1Axis.orient('left');
- y2Axis.orient('right');
- x2Axis.orient('bottom').tickPadding(5);
- y3Axis.orient('left');
- y4Axis.orient('right');
-
- tooltip.headerEnabled(true).headerFormatter(function(d, i) {
- return xAxis.tickFormat()(d, i);
- });
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var stateGetter = function(data) {
- return function(){
- return {
- active: data.map(function(d) { return !d.disabled })
- };
- }
- };
-
- var stateSetter = function(data) {
- return function(state) {
- if (state.active !== undefined)
- data.forEach(function(series,i) {
- series.disabled = !state.active[i];
- });
- }
- };
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- that = this;
- nv.utils.initSVG(container);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight1 = nv.utils.availableHeight(height, container, margin)
- - (focusEnable ? focusHeight : 0),
- availableHeight2 = focusHeight - margin2.top - margin2.bottom;
-
- chart.update = function() { container.transition().duration(transitionDuration).call(chart); };
- chart.container = this;
-
- state
- .setter(stateSetter(data), chart.update)
- .getter(stateGetter(data))
- .update();
-
- // DEPRECATED set state.disableddisabled
- state.disabled = data.map(function(d) { return !!d.disabled });
-
- if (!defaultState) {
- var key;
- defaultState = {};
- for (key in state) {
- if (state[key] instanceof Array)
- defaultState[key] = state[key].slice(0);
- else
- defaultState[key] = state[key];
- }
- }
-
- // Display No Data message if there's nothing to show.
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
- nv.utils.noData(chart, container)
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- // Setup Scales
- var dataBars = data.filter(function(d) { return !d.disabled && d.bar });
- var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #240
-
- x = bars.xScale();
- x2 = x2Axis.scale();
- y1 = bars.yScale();
- y2 = lines.yScale();
- y3 = bars2.yScale();
- y4 = lines2.yScale();
-
- var series1 = data
- .filter(function(d) { return !d.disabled && d.bar })
- .map(function(d) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i) }
- })
- });
-
- var series2 = data
- .filter(function(d) { return !d.disabled && !d.bar })
- .map(function(d) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i) }
- })
- });
-
- x.range([0, availableWidth]);
-
- x2 .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))
- .range([0, availableWidth]);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-linePlusBar').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-legendWrap');
-
- // this is the main chart
- var focusEnter = gEnter.append('g').attr('class', 'nv-focus');
- focusEnter.append('g').attr('class', 'nv-x nv-axis');
- focusEnter.append('g').attr('class', 'nv-y1 nv-axis');
- focusEnter.append('g').attr('class', 'nv-y2 nv-axis');
- focusEnter.append('g').attr('class', 'nv-barsWrap');
- focusEnter.append('g').attr('class', 'nv-linesWrap');
-
- // context chart is where you can focus in
- var contextEnter = gEnter.append('g').attr('class', 'nv-context');
- contextEnter.append('g').attr('class', 'nv-x nv-axis');
- contextEnter.append('g').attr('class', 'nv-y1 nv-axis');
- contextEnter.append('g').attr('class', 'nv-y2 nv-axis');
- contextEnter.append('g').attr('class', 'nv-barsWrap');
- contextEnter.append('g').attr('class', 'nv-linesWrap');
- contextEnter.append('g').attr('class', 'nv-brushBackground');
- contextEnter.append('g').attr('class', 'nv-x nv-brush');
-
- //============================================================
- // Legend
- //------------------------------------------------------------
-
- if (showLegend) {
- var legendWidth = legend.align() ? availableWidth / 2 : availableWidth;
- var legendXPosition = legend.align() ? legendWidth : 0;
-
- legend.width(legendWidth);
-
- g.select('.nv-legendWrap')
- .datum(data.map(function(series) {
- series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;
- series.key = series.originalKey + (series.bar ? legendLeftAxisHint : legendRightAxisHint);
- return series;
- }))
- .call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- // FIXME: shouldn't this be "- (focusEnabled ? focusHeight : 0)"?
- availableHeight1 = nv.utils.availableHeight(height, container, margin) - focusHeight;
- }
-
- g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + legendXPosition + ',' + (-margin.top) +')');
- }
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- //============================================================
- // Context chart (focus chart) components
- //------------------------------------------------------------
-
- // hide or show the focus context chart
- g.select('.nv-context').style('display', focusEnable ? 'initial' : 'none');
-
- bars2
- .width(availableWidth)
- .height(availableHeight2)
- .color(data.map(function (d, i) {
- return d.color || color(d, i);
- }).filter(function (d, i) {
- return !data[i].disabled && data[i].bar
- }));
- lines2
- .width(availableWidth)
- .height(availableHeight2)
- .color(data.map(function (d, i) {
- return d.color || color(d, i);
- }).filter(function (d, i) {
- return !data[i].disabled && !data[i].bar
- }));
-
- var bars2Wrap = g.select('.nv-context .nv-barsWrap')
- .datum(dataBars.length ? dataBars : [
- {values: []}
- ]);
- var lines2Wrap = g.select('.nv-context .nv-linesWrap')
- .datum(!dataLines[0].disabled ? dataLines : [
- {values: []}
- ]);
-
- g.select('.nv-context')
- .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')');
-
- bars2Wrap.transition().call(bars2);
- lines2Wrap.transition().call(lines2);
-
- // context (focus chart) axis controls
- if (focusShowAxisX) {
- x2Axis
- ._ticks( nv.utils.calcTicksX(availableWidth / 100, data))
- .tickSize(-availableHeight2, 0);
- g.select('.nv-context .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y3.range()[0] + ')');
- g.select('.nv-context .nv-x.nv-axis').transition()
- .call(x2Axis);
- }
-
- if (focusShowAxisY) {
- y3Axis
- .scale(y3)
- ._ticks( availableHeight2 / 36 )
- .tickSize( -availableWidth, 0);
- y4Axis
- .scale(y4)
- ._ticks( availableHeight2 / 36 )
- .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none
-
- g.select('.nv-context .nv-y3.nv-axis')
- .style('opacity', dataBars.length ? 1 : 0)
- .attr('transform', 'translate(0,' + x2.range()[0] + ')');
- g.select('.nv-context .nv-y2.nv-axis')
- .style('opacity', dataLines.length ? 1 : 0)
- .attr('transform', 'translate(' + x2.range()[1] + ',0)');
-
- g.select('.nv-context .nv-y1.nv-axis').transition()
- .call(y3Axis);
- g.select('.nv-context .nv-y2.nv-axis').transition()
- .call(y4Axis);
- }
-
- // Setup Brush
- brush.x(x2).on('brush', onBrush);
-
- if (brushExtent) brush.extent(brushExtent);
-
- var brushBG = g.select('.nv-brushBackground').selectAll('g')
- .data([brushExtent || brush.extent()]);
-
- var brushBGenter = brushBG.enter()
- .append('g');
-
- brushBGenter.append('rect')
- .attr('class', 'left')
- .attr('x', 0)
- .attr('y', 0)
- .attr('height', availableHeight2);
-
- brushBGenter.append('rect')
- .attr('class', 'right')
- .attr('x', 0)
- .attr('y', 0)
- .attr('height', availableHeight2);
-
- var gBrush = g.select('.nv-x.nv-brush')
- .call(brush);
- gBrush.selectAll('rect')
- //.attr('y', -5)
- .attr('height', availableHeight2);
- gBrush.selectAll('.resize').append('path').attr('d', resizePath);
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('stateChange', function(newState) {
- for (var key in newState)
- state[key] = newState[key];
- dispatch.stateChange(state);
- chart.update();
- });
-
- // Update chart from a state object passed to event handler
- dispatch.on('changeState', function(e) {
- if (typeof e.disabled !== 'undefined') {
- data.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
- state.disabled = e.disabled;
- }
- chart.update();
- });
-
- //============================================================
- // Functions
- //------------------------------------------------------------
-
- // Taken from crossfilter (http://square.github.com/crossfilter/)
- function resizePath(d) {
- var e = +(d == 'e'),
- x = e ? 1 : -1,
- y = availableHeight2 / 3;
- return 'M' + (.5 * x) + ',' + y
- + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)
- + 'V' + (2 * y - 6)
- + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y)
- + 'Z'
- + 'M' + (2.5 * x) + ',' + (y + 8)
- + 'V' + (2 * y - 8)
- + 'M' + (4.5 * x) + ',' + (y + 8)
- + 'V' + (2 * y - 8);
- }
-
-
- function updateBrushBG() {
- if (!brush.empty()) brush.extent(brushExtent);
- brushBG
- .data([brush.empty() ? x2.domain() : brushExtent])
- .each(function(d,i) {
- var leftWidth = x2(d[0]) - x2.range()[0],
- rightWidth = x2.range()[1] - x2(d[1]);
- d3.select(this).select('.left')
- .attr('width', leftWidth < 0 ? 0 : leftWidth);
-
- d3.select(this).select('.right')
- .attr('x', x2(d[1]))
- .attr('width', rightWidth < 0 ? 0 : rightWidth);
- });
- }
-
- function onBrush() {
- brushExtent = brush.empty() ? null : brush.extent();
- extent = brush.empty() ? x2.domain() : brush.extent();
- dispatch.brush({extent: extent, brush: brush});
- updateBrushBG();
-
- // Prepare Main (Focus) Bars and Lines
- bars
- .width(availableWidth)
- .height(availableHeight1)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled && data[i].bar }));
-
- lines
- .width(availableWidth)
- .height(availableHeight1)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled && !data[i].bar }));
-
- var focusBarsWrap = g.select('.nv-focus .nv-barsWrap')
- .datum(!dataBars.length ? [{values:[]}] :
- dataBars
- .map(function(d,i) {
- return {
- key: d.key,
- values: d.values.filter(function(d,i) {
- return bars.x()(d,i) >= extent[0] && bars.x()(d,i) <= extent[1];
- })
- }
- })
- );
-
- var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
- .datum(dataLines[0].disabled ? [{values:[]}] :
- dataLines
- .map(function(d,i) {
- return {
- area: d.area,
- fillOpacity: d.fillOpacity,
- key: d.key,
- values: d.values.filter(function(d,i) {
- return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
- })
- }
- })
- );
-
- // Update Main (Focus) X Axis
- if (dataBars.length) {
- x = bars.xScale();
- } else {
- x = lines.xScale();
- }
-
- xAxis
- .scale(x)
- ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize(-availableHeight1, 0);
-
- xAxis.domain([Math.ceil(extent[0]), Math.floor(extent[1])]);
-
- g.select('.nv-x.nv-axis').transition().duration(transitionDuration)
- .call(xAxis);
-
- // Update Main (Focus) Bars and Lines
- focusBarsWrap.transition().duration(transitionDuration).call(bars);
- focusLinesWrap.transition().duration(transitionDuration).call(lines);
-
- // Setup and Update Main (Focus) Y Axes
- g.select('.nv-focus .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y1.range()[0] + ')');
-
- y1Axis
- .scale(y1)
- ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) )
- .tickSize(-availableWidth, 0);
- y2Axis
- .scale(y2)
- ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) )
- .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none
-
- g.select('.nv-focus .nv-y1.nv-axis')
- .style('opacity', dataBars.length ? 1 : 0);
- g.select('.nv-focus .nv-y2.nv-axis')
- .style('opacity', dataLines.length && !dataLines[0].disabled ? 1 : 0)
- .attr('transform', 'translate(' + x.range()[1] + ',0)');
-
- g.select('.nv-focus .nv-y1.nv-axis').transition().duration(transitionDuration)
- .call(y1Axis);
- g.select('.nv-focus .nv-y2.nv-axis').transition().duration(transitionDuration)
- .call(y2Axis);
- }
-
- onBrush();
-
- });
-
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- lines.dispatch.on('elementMouseover.tooltip', function(evt) {
- tooltip
- .duration(100)
- .valueFormatter(function(d, i) {
- return y2Axis.tickFormat()(d, i);
- })
- .data(evt)
- .position(evt.pos)
- .hidden(false);
- });
-
- lines.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true)
- });
-
- bars.dispatch.on('elementMouseover.tooltip', function(evt) {
- evt.value = chart.x()(evt.data);
- evt['series'] = {
- value: chart.y()(evt.data),
- color: evt.color
- };
- tooltip
- .duration(0)
- .valueFormatter(function(d, i) {
- return y1Axis.tickFormat()(d, i);
- })
- .data(evt)
- .hidden(false);
- });
-
- bars.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true);
- });
-
- bars.dispatch.on('elementMousemove.tooltip', function(evt) {
- tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
- });
-
- //============================================================
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.dispatch = dispatch;
- chart.legend = legend;
- chart.lines = lines;
- chart.lines2 = lines2;
- chart.bars = bars;
- chart.bars2 = bars2;
- chart.xAxis = xAxis;
- chart.x2Axis = x2Axis;
- chart.y1Axis = y1Axis;
- chart.y2Axis = y2Axis;
- chart.y3Axis = y3Axis;
- chart.y4Axis = y4Axis;
- chart.tooltip = tooltip;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
- brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
- focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}},
- focusHeight: {get: function(){return focusHeight;}, set: function(_){focusHeight=_;}},
- focusShowAxisX: {get: function(){return focusShowAxisX;}, set: function(_){focusShowAxisX=_;}},
- focusShowAxisY: {get: function(){return focusShowAxisY;}, set: function(_){focusShowAxisY=_;}},
- legendLeftAxisHint: {get: function(){return legendLeftAxisHint;}, set: function(_){legendLeftAxisHint=_;}},
- legendRightAxisHint: {get: function(){return legendRightAxisHint;}, set: function(_){legendRightAxisHint=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- duration: {get: function(){return transitionDuration;}, set: function(_){
- transitionDuration = _;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- legend.color(color);
- }},
- x: {get: function(){return getX;}, set: function(_){
- getX = _;
- lines.x(_);
- lines2.x(_);
- bars.x(_);
- bars2.x(_);
- }},
- y: {get: function(){return getY;}, set: function(_){
- getY = _;
- lines.y(_);
- lines2.y(_);
- bars.y(_);
- bars2.y(_);
- }}
- });
-
- nv.utils.inheritOptions(chart, lines);
- nv.utils.initOptions(chart);
-
- return chart;
-};
-nv.models.lineWithFocusChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var lines = nv.models.line()
- , lines2 = nv.models.line()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , x2Axis = nv.models.axis()
- , y2Axis = nv.models.axis()
- , legend = nv.models.legend()
- , brush = d3.svg.brush()
- , tooltip = nv.models.tooltip()
- , interactiveLayer = nv.interactiveGuideline()
- ;
-
- var margin = {top: 30, right: 30, bottom: 30, left: 60}
- , margin2 = {top: 0, right: 30, bottom: 20, left: 60}
- , color = nv.utils.defaultColor()
- , width = null
- , height = null
- , height2 = 50
- , useInteractiveGuideline = false
- , x
- , y
- , x2
- , y2
- , showLegend = true
- , brushExtent = null
- , noData = null
- , dispatch = d3.dispatch('brush', 'stateChange', 'changeState')
- , transitionDuration = 250
- , state = nv.utils.state()
- , defaultState = null
- ;
-
- lines.clipEdge(true).duration(0);
- lines2.interactive(false);
- xAxis.orient('bottom').tickPadding(5);
- yAxis.orient('left');
- x2Axis.orient('bottom').tickPadding(5);
- y2Axis.orient('left');
-
- tooltip.valueFormatter(function(d, i) {
- return yAxis.tickFormat()(d, i);
- }).headerFormatter(function(d, i) {
- return xAxis.tickFormat()(d, i);
- });
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var stateGetter = function(data) {
- return function(){
- return {
- active: data.map(function(d) { return !d.disabled })
- };
- }
- };
-
- var stateSetter = function(data) {
- return function(state) {
- if (state.active !== undefined)
- data.forEach(function(series,i) {
- series.disabled = !state.active[i];
- });
- }
- };
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- that = this;
- nv.utils.initSVG(container);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight1 = nv.utils.availableHeight(height, container, margin) - height2,
- availableHeight2 = height2 - margin2.top - margin2.bottom;
-
- chart.update = function() { container.transition().duration(transitionDuration).call(chart) };
- chart.container = this;
-
- state
- .setter(stateSetter(data), chart.update)
- .getter(stateGetter(data))
- .update();
-
- // DEPRECATED set state.disableddisabled
- state.disabled = data.map(function(d) { return !!d.disabled });
-
- if (!defaultState) {
- var key;
- defaultState = {};
- for (key in state) {
- if (state[key] instanceof Array)
- defaultState[key] = state[key].slice(0);
- else
- defaultState[key] = state[key];
- }
- }
-
- // Display No Data message if there's nothing to show.
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
- nv.utils.noData(chart, container)
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- // Setup Scales
- x = lines.xScale();
- y = lines.yScale();
- x2 = lines2.xScale();
- y2 = lines2.yScale();
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-lineWithFocusChart').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineWithFocusChart').append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-legendWrap');
-
- var focusEnter = gEnter.append('g').attr('class', 'nv-focus');
- focusEnter.append('g').attr('class', 'nv-x nv-axis');
- focusEnter.append('g').attr('class', 'nv-y nv-axis');
- focusEnter.append('g').attr('class', 'nv-linesWrap');
- focusEnter.append('g').attr('class', 'nv-interactive');
-
- var contextEnter = gEnter.append('g').attr('class', 'nv-context');
- contextEnter.append('g').attr('class', 'nv-x nv-axis');
- contextEnter.append('g').attr('class', 'nv-y nv-axis');
- contextEnter.append('g').attr('class', 'nv-linesWrap');
- contextEnter.append('g').attr('class', 'nv-brushBackground');
- contextEnter.append('g').attr('class', 'nv-x nv-brush');
-
- // Legend
- if (showLegend) {
- legend.width(availableWidth);
-
- g.select('.nv-legendWrap')
- .datum(data)
- .call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- availableHeight1 = nv.utils.availableHeight(height, container, margin) - height2;
- }
-
- g.select('.nv-legendWrap')
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- }
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
-
- //Set up interactive layer
- if (useInteractiveGuideline) {
- interactiveLayer
- .width(availableWidth)
- .height(availableHeight1)
- .margin({left:margin.left, top:margin.top})
- .svgContainer(container)
- .xScale(x);
- wrap.select(".nv-interactive").call(interactiveLayer);
- }
-
- // Main Chart Component(s)
- lines
- .width(availableWidth)
- .height(availableHeight1)
- .color(
- data
- .map(function(d,i) {
- return d.color || color(d, i);
- })
- .filter(function(d,i) {
- return !data[i].disabled;
- })
- );
-
- lines2
- .defined(lines.defined())
- .width(availableWidth)
- .height(availableHeight2)
- .color(
- data
- .map(function(d,i) {
- return d.color || color(d, i);
- })
- .filter(function(d,i) {
- return !data[i].disabled;
- })
- );
-
- g.select('.nv-context')
- .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')')
-
- var contextLinesWrap = g.select('.nv-context .nv-linesWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
-
- d3.transition(contextLinesWrap).call(lines2);
-
- // Setup Main (Focus) Axes
- xAxis
- .scale(x)
- ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize(-availableHeight1, 0);
-
- yAxis
- .scale(y)
- ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-focus .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + availableHeight1 + ')');
-
- // Setup Brush
- brush
- .x(x2)
- .on('brush', function() {
- onBrush();
- });
-
- if (brushExtent) brush.extent(brushExtent);
-
- var brushBG = g.select('.nv-brushBackground').selectAll('g')
- .data([brushExtent || brush.extent()])
-
- var brushBGenter = brushBG.enter()
- .append('g');
-
- brushBGenter.append('rect')
- .attr('class', 'left')
- .attr('x', 0)
- .attr('y', 0)
- .attr('height', availableHeight2);
-
- brushBGenter.append('rect')
- .attr('class', 'right')
- .attr('x', 0)
- .attr('y', 0)
- .attr('height', availableHeight2);
-
- var gBrush = g.select('.nv-x.nv-brush')
- .call(brush);
- gBrush.selectAll('rect')
- .attr('height', availableHeight2);
- gBrush.selectAll('.resize').append('path').attr('d', resizePath);
-
- onBrush();
-
- // Setup Secondary (Context) Axes
- x2Axis
- .scale(x2)
- ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize(-availableHeight2, 0);
-
- g.select('.nv-context .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y2.range()[0] + ')');
- d3.transition(g.select('.nv-context .nv-x.nv-axis'))
- .call(x2Axis);
-
- y2Axis
- .scale(y2)
- ._ticks( nv.utils.calcTicksY(availableHeight2/36, data) )
- .tickSize( -availableWidth, 0);
-
- d3.transition(g.select('.nv-context .nv-y.nv-axis'))
- .call(y2Axis);
-
- g.select('.nv-context .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y2.range()[0] + ')');
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('stateChange', function(newState) {
- for (var key in newState)
- state[key] = newState[key];
- dispatch.stateChange(state);
- chart.update();
- });
-
- interactiveLayer.dispatch.on('elementMousemove', function(e) {
- lines.clearHighlights();
- var singlePoint, pointIndex, pointXLocation, allData = [];
- data
- .filter(function(series, i) {
- series.seriesIndex = i;
- return !series.disabled;
- })
- .forEach(function(series,i) {
- var extent = brush.empty() ? x2.domain() : brush.extent();
- var currentValues = series.values.filter(function(d,i) {
- return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
- });
-
- pointIndex = nv.interactiveBisect(currentValues, e.pointXValue, lines.x());
- var point = currentValues[pointIndex];
- var pointYValue = chart.y()(point, pointIndex);
- if (pointYValue != null) {
- lines.highlightPoint(i, pointIndex, true);
- }
- if (point === undefined) return;
- if (singlePoint === undefined) singlePoint = point;
- if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
- allData.push({
- key: series.key,
- value: chart.y()(point, pointIndex),
- color: color(series,series.seriesIndex)
- });
- });
- //Highlight the tooltip entry based on which point the mouse is closest to.
- if (allData.length > 2) {
- var yValue = chart.yScale().invert(e.mouseY);
- var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]);
- var threshold = 0.03 * domainExtent;
- var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold);
- if (indexToHighlight !== null)
- allData[indexToHighlight].highlight = true;
- }
-
- var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));
- interactiveLayer.tooltip
- .position({left: e.mouseX + margin.left, top: e.mouseY + margin.top})
- .chartContainer(that.parentNode)
- .valueFormatter(function(d,i) {
- return d == null ? "N/A" : yAxis.tickFormat()(d);
- })
- .data({
- value: xValue,
- index: pointIndex,
- series: allData
- })();
-
- interactiveLayer.renderGuideLine(pointXLocation);
-
- });
-
- interactiveLayer.dispatch.on("elementMouseout",function(e) {
- lines.clearHighlights();
- });
-
- dispatch.on('changeState', function(e) {
- if (typeof e.disabled !== 'undefined') {
- data.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
- }
- chart.update();
- });
-
- //============================================================
- // Functions
- //------------------------------------------------------------
-
- // Taken from crossfilter (http://square.github.com/crossfilter/)
- function resizePath(d) {
- var e = +(d == 'e'),
- x = e ? 1 : -1,
- y = availableHeight2 / 3;
- return 'M' + (.5 * x) + ',' + y
- + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)
- + 'V' + (2 * y - 6)
- + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y)
- + 'Z'
- + 'M' + (2.5 * x) + ',' + (y + 8)
- + 'V' + (2 * y - 8)
- + 'M' + (4.5 * x) + ',' + (y + 8)
- + 'V' + (2 * y - 8);
- }
-
-
- function updateBrushBG() {
- if (!brush.empty()) brush.extent(brushExtent);
- brushBG
- .data([brush.empty() ? x2.domain() : brushExtent])
- .each(function(d,i) {
- var leftWidth = x2(d[0]) - x.range()[0],
- rightWidth = availableWidth - x2(d[1]);
- d3.select(this).select('.left')
- .attr('width', leftWidth < 0 ? 0 : leftWidth);
-
- d3.select(this).select('.right')
- .attr('x', x2(d[1]))
- .attr('width', rightWidth < 0 ? 0 : rightWidth);
- });
- }
-
-
- function onBrush() {
- brushExtent = brush.empty() ? null : brush.extent();
- var extent = brush.empty() ? x2.domain() : brush.extent();
-
- //The brush extent cannot be less than one. If it is, don't update the line chart.
- if (Math.abs(extent[0] - extent[1]) <= 1) {
- return;
- }
-
- dispatch.brush({extent: extent, brush: brush});
-
-
- updateBrushBG();
-
- // Update Main (Focus)
- var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
- .datum(
- data
- .filter(function(d) { return !d.disabled })
- .map(function(d,i) {
- return {
- key: d.key,
- area: d.area,
- values: d.values.filter(function(d,i) {
- return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
- })
- }
- })
- );
- focusLinesWrap.transition().duration(transitionDuration).call(lines);
-
-
- // Update Main (Focus) Axes
- g.select('.nv-focus .nv-x.nv-axis').transition().duration(transitionDuration)
- .call(xAxis);
- g.select('.nv-focus .nv-y.nv-axis').transition().duration(transitionDuration)
- .call(yAxis);
- }
- });
-
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- lines.dispatch.on('elementMouseover.tooltip', function(evt) {
- tooltip.data(evt).position(evt.pos).hidden(false);
- });
-
- lines.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true)
- });
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.dispatch = dispatch;
- chart.legend = legend;
- chart.lines = lines;
- chart.lines2 = lines2;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.x2Axis = x2Axis;
- chart.y2Axis = y2Axis;
- chart.interactiveLayer = interactiveLayer;
- chart.tooltip = tooltip;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- focusHeight: {get: function(){return height2;}, set: function(_){height2=_;}},
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
- brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}},
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- legend.color(color);
- // line color is handled above?
- }},
- interpolate: {get: function(){return lines.interpolate();}, set: function(_){
- lines.interpolate(_);
- lines2.interpolate(_);
- }},
- xTickFormat: {get: function(){return xAxis.tickFormat();}, set: function(_){
- xAxis.tickFormat(_);
- x2Axis.tickFormat(_);
- }},
- yTickFormat: {get: function(){return yAxis.tickFormat();}, set: function(_){
- yAxis.tickFormat(_);
- y2Axis.tickFormat(_);
- }},
- duration: {get: function(){return transitionDuration;}, set: function(_){
- transitionDuration=_;
- yAxis.duration(transitionDuration);
- y2Axis.duration(transitionDuration);
- xAxis.duration(transitionDuration);
- x2Axis.duration(transitionDuration);
- }},
- x: {get: function(){return lines.x();}, set: function(_){
- lines.x(_);
- lines2.x(_);
- }},
- y: {get: function(){return lines.y();}, set: function(_){
- lines.y(_);
- lines2.y(_);
- }},
- useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){
- useInteractiveGuideline = _;
- if (useInteractiveGuideline) {
- lines.interactive(false);
- lines.useVoronoi(false);
- }
- }}
- });
-
- nv.utils.inheritOptions(chart, lines);
- nv.utils.initOptions(chart);
-
- return chart;
-};
-nv.models.multiBar = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 960
- , height = 500
- , x = d3.scale.ordinal()
- , y = d3.scale.linear()
- , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
- , container = null
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , getYerr = function(d) { return d.yErr }
- , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove
- , clipEdge = true
- , stacked = false
- , stackOffset = 'zero' // options include 'silhouette', 'wiggle', 'expand', 'zero', or a custom function
- , color = nv.utils.defaultColor()
- , errorBarColor = nv.utils.defaultColor()
- , hideable = false
- , barColor = null // adding the ability to set the color for each rather than the whole group
- , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled
- , duration = 500
- , xDomain
- , yDomain
- , xRange
- , yRange
- , groupSpacing = 0.1
- , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
- ;
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0 //used to store previous scales
- , renderWatch = nv.utils.renderWatch(dispatch, duration)
- ;
-
- var last_datalength = 0;
-
- function chart(selection) {
- renderWatch.reset();
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom;
-
- container = d3.select(this);
- nv.utils.initSVG(container);
- var nonStackableCount = 0;
- // This function defines the requirements for render complete
- var endFn = function(d, i) {
- if (d.series === data.length - 1 && i === data[0].values.length - 1)
- return true;
- return false;
- };
-
- if(hideable && data.length) hideable = [{
- values: data[0].values.map(function(d) {
- return {
- x: d.x,
- y: 0,
- series: d.series,
- size: 0.01
- };}
- )}];
-
- if (stacked) {
- var parsed = d3.layout.stack()
- .offset(stackOffset)
- .values(function(d){ return d.values })
- .y(getY)
- (!data.length && hideable ? hideable : data);
-
- parsed.forEach(function(series, i){
- // if series is non-stackable, use un-parsed data
- if (series.nonStackable) {
- data[i].nonStackableSeries = nonStackableCount++;
- parsed[i] = data[i];
- } else {
- // don't stack this seires on top of the nonStackable seriees
- if (i > 0 && parsed[i - 1].nonStackable){
- parsed[i].values.map(function(d,j){
- d.y0 -= parsed[i - 1].values[j].y;
- d.y1 = d.y0 + d.y;
- });
- }
- }
- });
- data = parsed;
- }
- //add series index and key to each data point for reference
- data.forEach(function(series, i) {
- series.values.forEach(function(point) {
- point.series = i;
- point.key = series.key;
- });
- });
-
- // HACK for negative value stacking
- if (stacked) {
- data[0].values.map(function(d,i) {
- var posBase = 0, negBase = 0;
- data.map(function(d, idx) {
- if (!data[idx].nonStackable) {
- var f = d.values[i]
- f.size = Math.abs(f.y);
- if (f.y<0) {
- f.y1 = negBase;
- negBase = negBase - f.size;
- } else
- {
- f.y1 = f.size + posBase;
- posBase = posBase + f.size;
- }
- }
-
- });
- });
- }
- // Setup Scales
- // remap and flatten the data for use in calculating the scales' domains
- var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate
- data.map(function(d, idx) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1, idx:idx, yErr: getYerr(d,i)}
- })
- });
-
- x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))
- .rangeBands(xRange || [0, availableWidth], groupSpacing);
-
- y.domain(yDomain || d3.extent(d3.merge(
- d3.merge(seriesData).map(function(d) {
- var domain = d.y;
- // increase the domain range if this series is stackable
- if (stacked && !data[d.idx].nonStackable) {
- if (d.y > 0){
- domain = d.y1
- } else {
- domain = d.y1 + d.y
- }
- }
- var yerr = d.yErr;
- if (yerr) {
- if (yerr.length) {
- return [domain + yerr[0], domain + yerr[1]];
- } else {
- yerr = Math.abs(yerr)
- return [domain - yerr, domain + yerr];
- }
- } else {
- return [domain];
- }
- })).concat(forceY)))
- .range(yRange || [availableHeight, 0]);
-
- // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
- if (x.domain()[0] === x.domain()[1])
- x.domain()[0] ?
- x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])
- : x.domain([-1,1]);
-
- if (y.domain()[0] === y.domain()[1])
- y.domain()[0] ?
- y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])
- : y.domain([-1,1]);
-
- x0 = x0 || x;
- y0 = y0 || y;
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-multibar').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibar');
- var defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-groups');
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-edge-clip-' + id)
- .append('rect');
- wrap.select('#nv-edge-clip-' + id + ' rect')
- .attr('width', availableWidth)
- .attr('height', availableHeight);
-
- g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
-
- var groups = wrap.select('.nv-groups').selectAll('.nv-group')
- .data(function(d) { return d }, function(d,i) { return i });
- groups.enter().append('g')
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6);
-
- var exitTransition = renderWatch
- .transition(groups.exit().selectAll('g.nv-bar'), 'multibarExit', Math.min(100, duration))
- .attr('y', function(d, i, j) {
- var yVal = y0(0) || 0;
- if (stacked) {
- if (data[d.series] && !data[d.series].nonStackable) {
- yVal = y0(d.y0);
- }
- }
- return yVal;
- })
- .attr('height', 0)
- .remove();
- if (exitTransition.delay)
- exitTransition.delay(function(d,i) {
- var delay = i * (duration / (last_datalength + 1)) - i;
- return delay;
- });
- groups
- .attr('class', function(d,i) { return 'nv-group nv-series-' + i })
- .classed('hover', function(d) { return d.hover })
- .style('fill', function(d,i){ return color(d, i) })
- .style('stroke', function(d,i){ return color(d, i) });
- groups
- .style('stroke-opacity', 1)
- .style('fill-opacity', 0.75);
-
- var bars = groups.selectAll('g.nv-bar')
- .data(function(d) { return (hideable && !data.length) ? hideable.values : d.values });
- bars.exit().remove();
-
- var barsEnter = bars.enter().append('g')
- .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})
- .attr('transform', function(d,i,j) {
- var _x = stacked && !data[j].nonStackable ? 0 : (j * x.rangeBand() / data.length );
- var _y = y0(stacked && !data[j].nonStackable ? d.y0 : 0) || 0;
- return 'translate(' + _x + ',' + _y + ')';
- })
- ;
-
- barsEnter.append('rect')
- .attr('height', 0)
- .attr('width', function(d,i,j) { return x.rangeBand() / (stacked && !data[j].nonStackable ? 1 : data.length) })
- .style('fill', function(d,i,j){ return color(d, j, i); })
- .style('stroke', function(d,i,j){ return color(d, j, i); })
- ;
- bars
- .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here
- d3.select(this).classed('hover', true);
- dispatch.elementMouseover({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- })
- .on('mouseout', function(d,i) {
- d3.select(this).classed('hover', false);
- dispatch.elementMouseout({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- })
- .on('mousemove', function(d,i) {
- dispatch.elementMousemove({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- })
- .on('click', function(d,i) {
- dispatch.elementClick({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- d3.event.stopPropagation();
- })
- .on('dblclick', function(d,i) {
- dispatch.elementDblClick({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- d3.event.stopPropagation();
- });
-
- if (getYerr(data[0].values[0], 0)) {
- barsEnter.append('polyline');
-
- bars.select('polyline')
- .attr('fill', 'none')
- .attr('stroke', 'black')
- //.attr('stroke', function(d, i, j) { return errorBarColor(d, j, i); })
- .attr('points', function(d,i) {
- var yerr = getYerr(d,i)
- , mid = 0.8 * x.rangeBand() / ((stacked ? 1 : data.length) * 2);
- yerr = yerr.length ? yerr : [-Math.abs(yerr), Math.abs(yerr)];
- yerr = yerr.map(function(e) { return y(e) - y(0); });
- var a = [[-mid, yerr[0]], [mid, yerr[0]], [0, yerr[0]], [0, yerr[1]], [-mid, yerr[1]], [mid, yerr[1]]];
- return a.map(function (path) { return path.join(',') }).join(' ');
- })
- .attr('transform', function(d, i) {
- var xOffset = x.rangeBand() / ((stacked ? 1 : data.length) * 2);
- var yOffset = getY(d,i) < 0 ? y(getY(d, i)) - y(0) : 0;
- return 'translate(' + xOffset + ', ' + yOffset + ')';
- })
- }
-
- bars
- .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})
-
- if (barColor) {
- if (!disabled) disabled = data.map(function() { return true });
- bars.select('rect')
- .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); })
- .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); });
- }
-
- var barSelection =
- bars.watchTransition(renderWatch, 'multibar', Math.min(250, duration))
- .delay(function(d,i) {
- return i * duration / data[0].values.length;
- });
- if (stacked){
- barSelection
- .attr('transform', function(d,i,j) {
- var yVal = 0;
- // if stackable, stack it on top of the previous series
- if (!data[j].nonStackable) {
- yVal = y(d.y1);
- } else {
- if (getY(d,i) < 0){
- yVal = y(0);
- } else {
- if (y(0) - y(getY(d,i)) < -1){
- yVal = y(0) - 1;
- } else {
- yVal = y(getY(d, i)) || 0;
- }
- }
- }
- var width = 0;
- if (data[j].nonStackable) {
- width = d.series * x.rangeBand() / data.length;
- if (data.length !== nonStackableCount){
- width = data[j].nonStackableSeries * x.rangeBand()/(nonStackableCount*2);
- }
- }
- var xVal = width + x(getX(d, i));
- return 'translate(' + xVal + ',' + yVal + ')';
- })
- .select('rect')
- .attr('height', function(d,i,j) {
- if (!data[j].nonStackable) {
- return Math.max(Math.abs(y(d.y+d.y0) - y(d.y0)), 1);
- } else {
- return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0;
- }
- })
- .attr('width', function(d,i,j){
- if (!data[j].nonStackable) {
- return x.rangeBand();
- } else {
- // if all series are nonStacable, take the full width
- var width = (x.rangeBand() / nonStackableCount);
- // otherwise, nonStackable graph will be only taking the half-width
- // of the x rangeBand
- if (data.length !== nonStackableCount) {
- width = x.rangeBand()/(nonStackableCount*2);
- }
- return width;
- }
- });
- }
- else {
- barSelection.attr('transform', function(d,i) {
- var xVal = d.series * x.rangeBand() / data.length + x(getX(d, i));
- var yVal = getY(d,i) < 0 ?
- y(0) :
- y(0) - y(getY(d,i)) < 1 ?
- y(0) - 1 :
- y(getY(d,i)) || 0;
- return 'translate(' + xVal + ',' + yVal + ')';
- })
- .select('rect')
- .attr('width', x.rangeBand() / data.length)
- .attr('height', function(d,i) {
- return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0;
- });
- }
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
-
- // keep track of the last data value length for transition calculations
- if (data[0] && data[0].values) {
- last_datalength = data[0].values.length;
- }
-
- });
-
- renderWatch.renderEnd('multibar immediate');
-
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- x: {get: function(){return getX;}, set: function(_){getX=_;}},
- y: {get: function(){return getY;}, set: function(_){getY=_;}},
- yErr: {get: function(){return getYerr;}, set: function(_){getYerr=_;}},
- xScale: {get: function(){return x;}, set: function(_){x=_;}},
- yScale: {get: function(){return y;}, set: function(_){y=_;}},
- xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
- yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
- xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},
- yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},
- forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},
- stacked: {get: function(){return stacked;}, set: function(_){stacked=_;}},
- stackOffset: {get: function(){return stackOffset;}, set: function(_){stackOffset=_;}},
- clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
- disabled: {get: function(){return disabled;}, set: function(_){disabled=_;}},
- id: {get: function(){return id;}, set: function(_){id=_;}},
- hideable: {get: function(){return hideable;}, set: function(_){hideable=_;}},
- groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }},
- barColor: {get: function(){return barColor;}, set: function(_){
- barColor = _ ? nv.utils.getColor(_) : null;
- }},
- errorBarColor: {get: function(){return errorBarColor;}, set: function(_){
- errorBarColor = _ ? nv.utils.getColor(_) : null;
- }}
- });
-
- nv.utils.initOptions(chart);
-
- return chart;
-};
-
-nv.models.multiBarChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var multibar = nv.models.multiBar()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- , controls = nv.models.legend()
- , tooltip = nv.models.tooltip()
- ;
-
- var margin = {top: 30, right: 20, bottom: 50, left: 60}
- , width = null
- , height = null
- , color = nv.utils.defaultColor()
- , showControls = true
- , controlLabels = {}
- , showLegend = true
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = false
- , reduceXTicks = true // if false a tick will show for every data point
- , staggerLabels = false
- , rotateLabels = 0
- , x //can be accessed via chart.xScale()
- , y //can be accessed via chart.yScale()
- , state = nv.utils.state()
- , defaultState = null
- , noData = null
- , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd')
- , controlWidth = function() { return showControls ? 180 : 0 }
- , duration = 250
- ;
-
- state.stacked = false // DEPRECATED Maintained for backward compatibility
-
- multibar.stacked(false);
- xAxis
- .orient('bottom')
- .tickPadding(7)
- .showMaxMin(false)
- .tickFormat(function(d) { return d })
- ;
- yAxis
- .orient((rightAlignYAxis) ? 'right' : 'left')
- .tickFormat(d3.format(',.1f'))
- ;
-
- tooltip
- .duration(0)
- .valueFormatter(function(d, i) {
- return yAxis.tickFormat()(d, i);
- })
- .headerFormatter(function(d, i) {
- return xAxis.tickFormat()(d, i);
- });
-
- controls.updateState(false);
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var renderWatch = nv.utils.renderWatch(dispatch);
- var stacked = false;
-
- var stateGetter = function(data) {
- return function(){
- return {
- active: data.map(function(d) { return !d.disabled }),
- stacked: stacked
- };
- }
- };
-
- var stateSetter = function(data) {
- return function(state) {
- if (state.stacked !== undefined)
- stacked = state.stacked;
- if (state.active !== undefined)
- data.forEach(function(series,i) {
- series.disabled = !state.active[i];
- });
- }
- };
-
- function chart(selection) {
- renderWatch.reset();
- renderWatch.models(multibar);
- if (showXAxis) renderWatch.models(xAxis);
- if (showYAxis) renderWatch.models(yAxis);
-
- selection.each(function(data) {
- var container = d3.select(this),
- that = this;
- nv.utils.initSVG(container);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- chart.update = function() {
- if (duration === 0)
- container.call(chart);
- else
- container.transition()
- .duration(duration)
- .call(chart);
- };
- chart.container = this;
-
- state
- .setter(stateSetter(data), chart.update)
- .getter(stateGetter(data))
- .update();
-
- // DEPRECATED set state.disableddisabled
- state.disabled = data.map(function(d) { return !!d.disabled });
-
- if (!defaultState) {
- var key;
- defaultState = {};
- for (key in state) {
- if (state[key] instanceof Array)
- defaultState[key] = state[key].slice(0);
- else
- defaultState[key] = state[key];
- }
- }
-
- // Display noData message if there's nothing to show.
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
- nv.utils.noData(chart, container)
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- // Setup Scales
- x = multibar.xScale();
- y = multibar.yScale();
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-multiBarWithLegend').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarWithLegend').append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis');
- gEnter.append('g').attr('class', 'nv-barsWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
- gEnter.append('g').attr('class', 'nv-controlsWrap');
-
- // Legend
- if (showLegend) {
- legend.width(availableWidth - controlWidth());
-
- g.select('.nv-legendWrap')
- .datum(data)
- .call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- availableHeight = nv.utils.availableHeight(height, container, margin);
- }
-
- g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
- }
-
- // Controls
- if (showControls) {
- var controlsData = [
- { key: controlLabels.grouped || 'Grouped', disabled: multibar.stacked() },
- { key: controlLabels.stacked || 'Stacked', disabled: !multibar.stacked() }
- ];
-
- controls.width(controlWidth()).color(['#444', '#444', '#444']);
- g.select('.nv-controlsWrap')
- .datum(controlsData)
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- .call(controls);
- }
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- // Main Chart Component(s)
- multibar
- .disabled(data.map(function(series) { return series.disabled }))
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
-
-
- var barsWrap = g.select('.nv-barsWrap')
- .datum(data.filter(function(d) { return !d.disabled }));
-
- barsWrap.call(multibar);
-
- // Setup Axes
- if (showXAxis) {
- xAxis
- .scale(x)
- ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y.range()[0] + ')');
- g.select('.nv-x.nv-axis')
- .call(xAxis);
-
- var xTicks = g.select('.nv-x.nv-axis > g').selectAll('g');
-
- xTicks
- .selectAll('line, text')
- .style('opacity', 1)
-
- if (staggerLabels) {
- var getTranslate = function(x,y) {
- return "translate(" + x + "," + y + ")";
- };
-
- var staggerUp = 5, staggerDown = 17; //pixels to stagger by
- // Issue #140
- xTicks
- .selectAll("text")
- .attr('transform', function(d,i,j) {
- return getTranslate(0, (j % 2 == 0 ? staggerUp : staggerDown));
- });
-
- var totalInBetweenTicks = d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;
- g.selectAll(".nv-x.nv-axis .nv-axisMaxMin text")
- .attr("transform", function(d,i) {
- return getTranslate(0, (i === 0 || totalInBetweenTicks % 2 !== 0) ? staggerDown : staggerUp);
- });
- }
-
- if (reduceXTicks)
- xTicks
- .filter(function(d,i) {
- return i % Math.ceil(data[0].values.length / (availableWidth / 100)) !== 0;
- })
- .selectAll('text, line')
- .style('opacity', 0);
-
- if(rotateLabels)
- xTicks
- .selectAll('.tick text')
- .attr('transform', 'rotate(' + rotateLabels + ' 0,0)')
- .style('text-anchor', rotateLabels > 0 ? 'start' : 'end');
-
- g.select('.nv-x.nv-axis').selectAll('g.nv-axisMaxMin text')
- .style('opacity', 1);
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis')
- .call(yAxis);
- }
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('stateChange', function(newState) {
- for (var key in newState)
- state[key] = newState[key];
- dispatch.stateChange(state);
- chart.update();
- });
-
- controls.dispatch.on('legendClick', function(d,i) {
- if (!d.disabled) return;
- controlsData = controlsData.map(function(s) {
- s.disabled = true;
- return s;
- });
- d.disabled = false;
-
- switch (d.key) {
- case 'Grouped':
- case controlLabels.grouped:
- multibar.stacked(false);
- break;
- case 'Stacked':
- case controlLabels.stacked:
- multibar.stacked(true);
- break;
- }
-
- state.stacked = multibar.stacked();
- dispatch.stateChange(state);
- chart.update();
- });
-
- // Update chart from a state object passed to event handler
- dispatch.on('changeState', function(e) {
- if (typeof e.disabled !== 'undefined') {
- data.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
- state.disabled = e.disabled;
- }
- if (typeof e.stacked !== 'undefined') {
- multibar.stacked(e.stacked);
- state.stacked = e.stacked;
- stacked = e.stacked;
- }
- chart.update();
- });
- });
-
- renderWatch.renderEnd('multibarchart immediate');
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- multibar.dispatch.on('elementMouseover.tooltip', function(evt) {
- evt.value = chart.x()(evt.data);
- evt['series'] = {
- key: evt.data.key,
- value: chart.y()(evt.data),
- color: evt.color
- };
- tooltip.data(evt).hidden(false);
- });
-
- multibar.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true);
- });
-
- multibar.dispatch.on('elementMousemove.tooltip', function(evt) {
- tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
- });
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.dispatch = dispatch;
- chart.multibar = multibar;
- chart.legend = legend;
- chart.controls = controls;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.state = state;
- chart.tooltip = tooltip;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
- showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},
- controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}},
- showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
- showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
- reduceXTicks: {get: function(){return reduceXTicks;}, set: function(_){reduceXTicks=_;}},
- rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}},
- staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- multibar.duration(duration);
- xAxis.duration(duration);
- yAxis.duration(duration);
- renderWatch.reset(duration);
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- legend.color(color);
- }},
- rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
- rightAlignYAxis = _;
- yAxis.orient( rightAlignYAxis ? 'right' : 'left');
- }},
- barColor: {get: function(){return multibar.barColor;}, set: function(_){
- multibar.barColor(_);
- legend.color(function(d,i) {return d3.rgb('#ccc').darker(i * 1.5).toString();})
- }}
- });
-
- nv.utils.inheritOptions(chart, multibar);
- nv.utils.initOptions(chart);
-
- return chart;
-};
-
-nv.models.multiBarHorizontal = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 960
- , height = 500
- , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
- , container = null
- , x = d3.scale.ordinal()
- , y = d3.scale.linear()
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , getYerr = function(d) { return d.yErr }
- , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove
- , color = nv.utils.defaultColor()
- , barColor = null // adding the ability to set the color for each rather than the whole group
- , errorBarColor = nv.utils.defaultColor()
- , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled
- , stacked = false
- , showValues = false
- , showBarLabels = false
- , valuePadding = 60
- , groupSpacing = 0.1
- , valueFormat = d3.format(',.2f')
- , delay = 1200
- , xDomain
- , yDomain
- , xRange
- , yRange
- , duration = 250
- , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
- ;
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0; //used to store previous scales
- var renderWatch = nv.utils.renderWatch(dispatch, duration);
-
- function chart(selection) {
- renderWatch.reset();
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom;
-
- container = d3.select(this);
- nv.utils.initSVG(container);
-
- if (stacked)
- data = d3.layout.stack()
- .offset('zero')
- .values(function(d){ return d.values })
- .y(getY)
- (data);
-
- //add series index and key to each data point for reference
- data.forEach(function(series, i) {
- series.values.forEach(function(point) {
- point.series = i;
- point.key = series.key;
- });
- });
-
- // HACK for negative value stacking
- if (stacked)
- data[0].values.map(function(d,i) {
- var posBase = 0, negBase = 0;
- data.map(function(d) {
- var f = d.values[i]
- f.size = Math.abs(f.y);
- if (f.y<0) {
- f.y1 = negBase - f.size;
- negBase = negBase - f.size;
- } else
- {
- f.y1 = posBase;
- posBase = posBase + f.size;
- }
- });
- });
-
- // Setup Scales
- // remap and flatten the data for use in calculating the scales' domains
- var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate
- data.map(function(d) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1, yErr: getYerr(d,i) }
- })
- });
-
- x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))
- .rangeBands(xRange || [0, availableHeight], groupSpacing);
-
- y.domain(yDomain || d3.extent(d3.merge(
- d3.merge(seriesData).map(function(d) {
- var domain = d.y;
- if (stacked) {
- if (d.y > 0){
- domain = d.y1 + d.y
- } else {
- domain = d.y1
- }
- }
- var yerr = d.yErr;
- if (yerr) {
- if (yerr.length) {
- return [domain + yerr[0], domain + yerr[1]];
- } else {
- yerr = Math.abs(yerr)
- return [domain - yerr, domain + yerr];
- }
- } else {
- return [domain];
- }
- })).concat(forceY)))
-
- if (showValues && !stacked)
- y.range(yRange || [(y.domain()[0] < 0 ? valuePadding : 0), availableWidth - (y.domain()[1] > 0 ? valuePadding : 0) ]);
- else
- y.range(yRange || [0, availableWidth]);
-
- x0 = x0 || x;
- y0 = y0 || d3.scale.linear().domain(y.domain()).range([y(0),y(0)]);
-
- // Setup containers and skeleton of chart
- var wrap = d3.select(this).selectAll('g.nv-wrap.nv-multibarHorizontal').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibarHorizontal');
- var defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-groups');
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- var groups = wrap.select('.nv-groups').selectAll('.nv-group')
- .data(function(d) { return d }, function(d,i) { return i });
- groups.enter().append('g')
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6);
- groups.exit().watchTransition(renderWatch, 'multibarhorizontal: exit groups')
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6)
- .remove();
- groups
- .attr('class', function(d,i) { return 'nv-group nv-series-' + i })
- .classed('hover', function(d) { return d.hover })
- .style('fill', function(d,i){ return color(d, i) })
- .style('stroke', function(d,i){ return color(d, i) });
- groups.watchTransition(renderWatch, 'multibarhorizontal: groups')
- .style('stroke-opacity', 1)
- .style('fill-opacity', .75);
-
- var bars = groups.selectAll('g.nv-bar')
- .data(function(d) { return d.values });
- bars.exit().remove();
-
- var barsEnter = bars.enter().append('g')
- .attr('transform', function(d,i,j) {
- return 'translate(' + y0(stacked ? d.y0 : 0) + ',' + (stacked ? 0 : (j * x.rangeBand() / data.length ) + x(getX(d,i))) + ')'
- });
-
- barsEnter.append('rect')
- .attr('width', 0)
- .attr('height', x.rangeBand() / (stacked ? 1 : data.length) )
-
- bars
- .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here
- d3.select(this).classed('hover', true);
- dispatch.elementMouseover({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- })
- .on('mouseout', function(d,i) {
- d3.select(this).classed('hover', false);
- dispatch.elementMouseout({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- })
- .on('mouseout', function(d,i) {
- dispatch.elementMouseout({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- })
- .on('mousemove', function(d,i) {
- dispatch.elementMousemove({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- })
- .on('click', function(d,i) {
- dispatch.elementClick({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- d3.event.stopPropagation();
- })
- .on('dblclick', function(d,i) {
- dispatch.elementDblClick({
- data: d,
- index: i,
- color: d3.select(this).style("fill")
- });
- d3.event.stopPropagation();
- });
-
- if (getYerr(data[0].values[0], 0)) {
- barsEnter.append('polyline');
-
- bars.select('polyline')
- .attr('fill', 'none')
- .attr('stroke', function(d,i,j) { return errorBarColor(d, j, i); })
- .attr('points', function(d,i) {
- var xerr = getYerr(d,i)
- , mid = 0.8 * x.rangeBand() / ((stacked ? 1 : data.length) * 2);
- xerr = xerr.length ? xerr : [-Math.abs(xerr), Math.abs(xerr)];
- xerr = xerr.map(function(e) { return y(e) - y(0); });
- var a = [[xerr[0],-mid], [xerr[0],mid], [xerr[0],0], [xerr[1],0], [xerr[1],-mid], [xerr[1],mid]];
- return a.map(function (path) { return path.join(',') }).join(' ');
- })
- .attr('transform', function(d,i) {
- var mid = x.rangeBand() / ((stacked ? 1 : data.length) * 2);
- return 'translate(' + (getY(d,i) < 0 ? 0 : y(getY(d,i)) - y(0)) + ', ' + mid + ')'
- });
- }
-
- barsEnter.append('text');
-
- if (showValues && !stacked) {
- bars.select('text')
- .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' })
- .attr('y', x.rangeBand() / (data.length * 2))
- .attr('dy', '.32em')
- .text(function(d,i) {
- var t = valueFormat(getY(d,i))
- , yerr = getYerr(d,i);
- if (yerr === undefined)
- return t;
- if (!yerr.length)
- return t + '±' + valueFormat(Math.abs(yerr));
- return t + '+' + valueFormat(Math.abs(yerr[1])) + '-' + valueFormat(Math.abs(yerr[0]));
- });
- bars.watchTransition(renderWatch, 'multibarhorizontal: bars')
- .select('text')
- .attr('x', function(d,i) { return getY(d,i) < 0 ? -4 : y(getY(d,i)) - y(0) + 4 })
- } else {
- bars.selectAll('text').text('');
- }
-
- if (showBarLabels && !stacked) {
- barsEnter.append('text').classed('nv-bar-label',true);
- bars.select('text.nv-bar-label')
- .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'start' : 'end' })
- .attr('y', x.rangeBand() / (data.length * 2))
- .attr('dy', '.32em')
- .text(function(d,i) { return getX(d,i) });
- bars.watchTransition(renderWatch, 'multibarhorizontal: bars')
- .select('text.nv-bar-label')
- .attr('x', function(d,i) { return getY(d,i) < 0 ? y(0) - y(getY(d,i)) + 4 : -4 });
- }
- else {
- bars.selectAll('text.nv-bar-label').text('');
- }
-
- bars
- .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})
-
- if (barColor) {
- if (!disabled) disabled = data.map(function() { return true });
- bars
- .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); })
- .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); });
- }
-
- if (stacked)
- bars.watchTransition(renderWatch, 'multibarhorizontal: bars')
- .attr('transform', function(d,i) {
- return 'translate(' + y(d.y1) + ',' + x(getX(d,i)) + ')'
- })
- .select('rect')
- .attr('width', function(d,i) {
- return Math.abs(y(getY(d,i) + d.y0) - y(d.y0))
- })
- .attr('height', x.rangeBand() );
- else
- bars.watchTransition(renderWatch, 'multibarhorizontal: bars')
- .attr('transform', function(d,i) {
- //TODO: stacked must be all positive or all negative, not both?
- return 'translate(' +
- (getY(d,i) < 0 ? y(getY(d,i)) : y(0))
- + ',' +
- (d.series * x.rangeBand() / data.length
- +
- x(getX(d,i)) )
- + ')'
- })
- .select('rect')
- .attr('height', x.rangeBand() / data.length )
- .attr('width', function(d,i) {
- return Math.max(Math.abs(y(getY(d,i)) - y(0)),1)
- });
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
-
- });
-
- renderWatch.renderEnd('multibarHorizontal immediate');
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- x: {get: function(){return getX;}, set: function(_){getX=_;}},
- y: {get: function(){return getY;}, set: function(_){getY=_;}},
- yErr: {get: function(){return getYerr;}, set: function(_){getYerr=_;}},
- xScale: {get: function(){return x;}, set: function(_){x=_;}},
- yScale: {get: function(){return y;}, set: function(_){y=_;}},
- xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
- yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
- xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},
- yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},
- forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},
- stacked: {get: function(){return stacked;}, set: function(_){stacked=_;}},
- showValues: {get: function(){return showValues;}, set: function(_){showValues=_;}},
- // this shows the group name, seems pointless?
- //showBarLabels: {get: function(){return showBarLabels;}, set: function(_){showBarLabels=_;}},
- disabled: {get: function(){return disabled;}, set: function(_){disabled=_;}},
- id: {get: function(){return id;}, set: function(_){id=_;}},
- valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},
- valuePadding: {get: function(){return valuePadding;}, set: function(_){valuePadding=_;}},
- groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }},
- barColor: {get: function(){return barColor;}, set: function(_){
- barColor = _ ? nv.utils.getColor(_) : null;
- }},
- errorBarColor: {get: function(){return errorBarColor;}, set: function(_){
- errorBarColor = _ ? nv.utils.getColor(_) : null;
- }}
- });
-
- nv.utils.initOptions(chart);
-
- return chart;
-};
-
-nv.models.multiBarHorizontalChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var multibar = nv.models.multiBarHorizontal()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend().height(30)
- , controls = nv.models.legend().height(30)
- , tooltip = nv.models.tooltip()
- ;
-
- var margin = {top: 30, right: 20, bottom: 50, left: 60}
- , width = null
- , height = null
- , color = nv.utils.defaultColor()
- , showControls = true
- , controlLabels = {}
- , showLegend = true
- , showXAxis = true
- , showYAxis = true
- , stacked = false
- , x //can be accessed via chart.xScale()
- , y //can be accessed via chart.yScale()
- , state = nv.utils.state()
- , defaultState = null
- , noData = null
- , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd')
- , controlWidth = function() { return showControls ? 180 : 0 }
- , duration = 250
- ;
-
- state.stacked = false; // DEPRECATED Maintained for backward compatibility
-
- multibar.stacked(stacked);
-
- xAxis
- .orient('left')
- .tickPadding(5)
- .showMaxMin(false)
- .tickFormat(function(d) { return d })
- ;
- yAxis
- .orient('bottom')
- .tickFormat(d3.format(',.1f'))
- ;
-
- tooltip
- .duration(0)
- .valueFormatter(function(d, i) {
- return yAxis.tickFormat()(d, i);
- })
- .headerFormatter(function(d, i) {
- return xAxis.tickFormat()(d, i);
- });
-
- controls.updateState(false);
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var stateGetter = function(data) {
- return function(){
- return {
- active: data.map(function(d) { return !d.disabled }),
- stacked: stacked
- };
- }
- };
-
- var stateSetter = function(data) {
- return function(state) {
- if (state.stacked !== undefined)
- stacked = state.stacked;
- if (state.active !== undefined)
- data.forEach(function(series,i) {
- series.disabled = !state.active[i];
- });
- }
- };
-
- var renderWatch = nv.utils.renderWatch(dispatch, duration);
-
- function chart(selection) {
- renderWatch.reset();
- renderWatch.models(multibar);
- if (showXAxis) renderWatch.models(xAxis);
- if (showYAxis) renderWatch.models(yAxis);
-
- selection.each(function(data) {
- var container = d3.select(this),
- that = this;
- nv.utils.initSVG(container);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- chart.update = function() { container.transition().duration(duration).call(chart) };
- chart.container = this;
-
- stacked = multibar.stacked();
-
- state
- .setter(stateSetter(data), chart.update)
- .getter(stateGetter(data))
- .update();
-
- // DEPRECATED set state.disableddisabled
- state.disabled = data.map(function(d) { return !!d.disabled });
-
- if (!defaultState) {
- var key;
- defaultState = {};
- for (key in state) {
- if (state[key] instanceof Array)
- defaultState[key] = state[key].slice(0);
- else
- defaultState[key] = state[key];
- }
- }
-
- // Display No Data message if there's nothing to show.
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
- nv.utils.noData(chart, container)
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- // Setup Scales
- x = multibar.xScale();
- y = multibar.yScale();
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-multiBarHorizontalChart').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarHorizontalChart').append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis')
- .append('g').attr('class', 'nv-zeroLine')
- .append('line');
- gEnter.append('g').attr('class', 'nv-barsWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
- gEnter.append('g').attr('class', 'nv-controlsWrap');
-
- // Legend
- if (showLegend) {
- legend.width(availableWidth - controlWidth());
-
- g.select('.nv-legendWrap')
- .datum(data)
- .call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- availableHeight = nv.utils.availableHeight(height, container, margin);
- }
-
- g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
- }
-
- // Controls
- if (showControls) {
- var controlsData = [
- { key: controlLabels.grouped || 'Grouped', disabled: multibar.stacked() },
- { key: controlLabels.stacked || 'Stacked', disabled: !multibar.stacked() }
- ];
-
- controls.width(controlWidth()).color(['#444', '#444', '#444']);
- g.select('.nv-controlsWrap')
- .datum(controlsData)
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- .call(controls);
- }
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- // Main Chart Component(s)
- multibar
- .disabled(data.map(function(series) { return series.disabled }))
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
-
- var barsWrap = g.select('.nv-barsWrap')
- .datum(data.filter(function(d) { return !d.disabled }));
-
- barsWrap.transition().call(multibar);
-
- // Setup Axes
- if (showXAxis) {
- xAxis
- .scale(x)
- ._ticks( nv.utils.calcTicksY(availableHeight/24, data) )
- .tickSize(-availableWidth, 0);
-
- g.select('.nv-x.nv-axis').call(xAxis);
-
- var xTicks = g.select('.nv-x.nv-axis').selectAll('g');
-
- xTicks
- .selectAll('line, text');
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize( -availableHeight, 0);
-
- g.select('.nv-y.nv-axis')
- .attr('transform', 'translate(0,' + availableHeight + ')');
- g.select('.nv-y.nv-axis').call(yAxis);
- }
-
- // Zero line
- g.select(".nv-zeroLine line")
- .attr("x1", y(0))
- .attr("x2", y(0))
- .attr("y1", 0)
- .attr("y2", -availableHeight)
- ;
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('stateChange', function(newState) {
- for (var key in newState)
- state[key] = newState[key];
- dispatch.stateChange(state);
- chart.update();
- });
-
- controls.dispatch.on('legendClick', function(d,i) {
- if (!d.disabled) return;
- controlsData = controlsData.map(function(s) {
- s.disabled = true;
- return s;
- });
- d.disabled = false;
-
- switch (d.key) {
- case 'Grouped':
- multibar.stacked(false);
- break;
- case 'Stacked':
- multibar.stacked(true);
- break;
- }
-
- state.stacked = multibar.stacked();
- dispatch.stateChange(state);
- stacked = multibar.stacked();
-
- chart.update();
- });
-
- // Update chart from a state object passed to event handler
- dispatch.on('changeState', function(e) {
-
- if (typeof e.disabled !== 'undefined') {
- data.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
-
- state.disabled = e.disabled;
- }
-
- if (typeof e.stacked !== 'undefined') {
- multibar.stacked(e.stacked);
- state.stacked = e.stacked;
- stacked = e.stacked;
- }
-
- chart.update();
- });
- });
- renderWatch.renderEnd('multibar horizontal chart immediate');
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- multibar.dispatch.on('elementMouseover.tooltip', function(evt) {
- evt.value = chart.x()(evt.data);
- evt['series'] = {
- key: evt.data.key,
- value: chart.y()(evt.data),
- color: evt.color
- };
- tooltip.data(evt).hidden(false);
- });
-
- multibar.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true);
- });
-
- multibar.dispatch.on('elementMousemove.tooltip', function(evt) {
- tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
- });
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.dispatch = dispatch;
- chart.multibar = multibar;
- chart.legend = legend;
- chart.controls = controls;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.state = state;
- chart.tooltip = tooltip;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
- showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},
- controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}},
- showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
- showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- multibar.duration(duration);
- xAxis.duration(duration);
- yAxis.duration(duration);
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- legend.color(color);
- }},
- barColor: {get: function(){return multibar.barColor;}, set: function(_){
- multibar.barColor(_);
- legend.color(function(d,i) {return d3.rgb('#ccc').darker(i * 1.5).toString();})
- }}
- });
-
- nv.utils.inheritOptions(chart, multibar);
- nv.utils.initOptions(chart);
-
- return chart;
-};
-nv.models.multiChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 30, right: 20, bottom: 50, left: 60},
- color = nv.utils.defaultColor(),
- width = null,
- height = null,
- showLegend = true,
- noData = null,
- yDomain1,
- yDomain2,
- getX = function(d) { return d.x },
- getY = function(d) { return d.y},
- interpolate = 'monotone',
- useVoronoi = true
- ;
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x = d3.scale.linear(),
- yScale1 = d3.scale.linear(),
- yScale2 = d3.scale.linear(),
-
- lines1 = nv.models.line().yScale(yScale1),
- lines2 = nv.models.line().yScale(yScale2),
-
- bars1 = nv.models.multiBar().stacked(false).yScale(yScale1),
- bars2 = nv.models.multiBar().stacked(false).yScale(yScale2),
-
- stack1 = nv.models.stackedArea().yScale(yScale1),
- stack2 = nv.models.stackedArea().yScale(yScale2),
-
- xAxis = nv.models.axis().scale(x).orient('bottom').tickPadding(5),
- yAxis1 = nv.models.axis().scale(yScale1).orient('left'),
- yAxis2 = nv.models.axis().scale(yScale2).orient('right'),
-
- legend = nv.models.legend().height(30),
- tooltip = nv.models.tooltip(),
- dispatch = d3.dispatch();
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- that = this;
- nv.utils.initSVG(container);
-
- chart.update = function() { container.transition().call(chart); };
- chart.container = this;
-
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- var dataLines1 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 1});
- var dataLines2 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 2});
- var dataBars1 = data.filter(function(d) {return d.type == 'bar' && d.yAxis == 1});
- var dataBars2 = data.filter(function(d) {return d.type == 'bar' && d.yAxis == 2});
- var dataStack1 = data.filter(function(d) {return d.type == 'area' && d.yAxis == 1});
- var dataStack2 = data.filter(function(d) {return d.type == 'area' && d.yAxis == 2});
-
- // Display noData message if there's nothing to show.
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
- nv.utils.noData(chart, container);
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- var series1 = data.filter(function(d) {return !d.disabled && d.yAxis == 1})
- .map(function(d) {
- return d.values.map(function(d,i) {
- return { x: d.x, y: d.y }
- })
- });
-
- var series2 = data.filter(function(d) {return !d.disabled && d.yAxis == 2})
- .map(function(d) {
- return d.values.map(function(d,i) {
- return { x: d.x, y: d.y }
- })
- });
-
- x .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))
- .range([0, availableWidth]);
-
- var wrap = container.selectAll('g.wrap.multiChart').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'wrap nvd3 multiChart').append('g');
-
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y1 nv-axis');
- gEnter.append('g').attr('class', 'nv-y2 nv-axis');
- gEnter.append('g').attr('class', 'lines1Wrap');
- gEnter.append('g').attr('class', 'lines2Wrap');
- gEnter.append('g').attr('class', 'bars1Wrap');
- gEnter.append('g').attr('class', 'bars2Wrap');
- gEnter.append('g').attr('class', 'stack1Wrap');
- gEnter.append('g').attr('class', 'stack2Wrap');
- gEnter.append('g').attr('class', 'legendWrap');
-
- var g = wrap.select('g');
-
- var color_array = data.map(function(d,i) {
- return data[i].color || color(d, i);
- });
-
- if (showLegend) {
- var legendWidth = legend.align() ? availableWidth / 2 : availableWidth;
- var legendXPosition = legend.align() ? legendWidth : 0;
-
- legend.width(legendWidth);
- legend.color(color_array);
-
- g.select('.legendWrap')
- .datum(data.map(function(series) {
- series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;
- series.key = series.originalKey + (series.yAxis == 1 ? '' : ' (right axis)');
- return series;
- }))
- .call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- availableHeight = nv.utils.availableHeight(height, container, margin);
- }
-
- g.select('.legendWrap')
- .attr('transform', 'translate(' + legendXPosition + ',' + (-margin.top) +')');
- }
-
- lines1
- .width(availableWidth)
- .height(availableHeight)
- .interpolate(interpolate)
- .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'line'}));
- lines2
- .width(availableWidth)
- .height(availableHeight)
- .interpolate(interpolate)
- .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'line'}));
- bars1
- .width(availableWidth)
- .height(availableHeight)
- .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'bar'}));
- bars2
- .width(availableWidth)
- .height(availableHeight)
- .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'bar'}));
- stack1
- .width(availableWidth)
- .height(availableHeight)
- .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'area'}));
- stack2
- .width(availableWidth)
- .height(availableHeight)
- .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'area'}));
-
- g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- var lines1Wrap = g.select('.lines1Wrap')
- .datum(dataLines1.filter(function(d){return !d.disabled}));
- var bars1Wrap = g.select('.bars1Wrap')
- .datum(dataBars1.filter(function(d){return !d.disabled}));
- var stack1Wrap = g.select('.stack1Wrap')
- .datum(dataStack1.filter(function(d){return !d.disabled}));
- var lines2Wrap = g.select('.lines2Wrap')
- .datum(dataLines2.filter(function(d){return !d.disabled}));
- var bars2Wrap = g.select('.bars2Wrap')
- .datum(dataBars2.filter(function(d){return !d.disabled}));
- var stack2Wrap = g.select('.stack2Wrap')
- .datum(dataStack2.filter(function(d){return !d.disabled}));
-
- var extraValue1 = dataStack1.length ? dataStack1.map(function(a){return a.values}).reduce(function(a,b){
- return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}})
- }).concat([{x:0, y:0}]) : [];
- var extraValue2 = dataStack2.length ? dataStack2.map(function(a){return a.values}).reduce(function(a,b){
- return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}})
- }).concat([{x:0, y:0}]) : [];
-
- yScale1 .domain(yDomain1 || d3.extent(d3.merge(series1).concat(extraValue1), function(d) { return d.y } ))
- .range([0, availableHeight]);
-
- yScale2 .domain(yDomain2 || d3.extent(d3.merge(series2).concat(extraValue2), function(d) { return d.y } ))
- .range([0, availableHeight]);
-
- lines1.yDomain(yScale1.domain());
- bars1.yDomain(yScale1.domain());
- stack1.yDomain(yScale1.domain());
-
- lines2.yDomain(yScale2.domain());
- bars2.yDomain(yScale2.domain());
- stack2.yDomain(yScale2.domain());
-
- if(dataStack1.length){d3.transition(stack1Wrap).call(stack1);}
- if(dataStack2.length){d3.transition(stack2Wrap).call(stack2);}
-
- if(dataBars1.length){d3.transition(bars1Wrap).call(bars1);}
- if(dataBars2.length){d3.transition(bars2Wrap).call(bars2);}
-
- if(dataLines1.length){d3.transition(lines1Wrap).call(lines1);}
- if(dataLines2.length){d3.transition(lines2Wrap).call(lines2);}
-
- xAxis
- ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + availableHeight + ')');
- d3.transition(g.select('.nv-x.nv-axis'))
- .call(xAxis);
-
- yAxis1
- ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
- .tickSize( -availableWidth, 0);
-
-
- d3.transition(g.select('.nv-y1.nv-axis'))
- .call(yAxis1);
-
- yAxis2
- ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
- .tickSize( -availableWidth, 0);
-
- d3.transition(g.select('.nv-y2.nv-axis'))
- .call(yAxis2);
-
- g.select('.nv-y1.nv-axis')
- .classed('nv-disabled', series1.length ? false : true)
- .attr('transform', 'translate(' + x.range()[0] + ',0)');
-
- g.select('.nv-y2.nv-axis')
- .classed('nv-disabled', series2.length ? false : true)
- .attr('transform', 'translate(' + x.range()[1] + ',0)');
-
- legend.dispatch.on('stateChange', function(newState) {
- chart.update();
- });
-
- //============================================================
- // Event Handling/Dispatching
- //------------------------------------------------------------
-
- function mouseover_line(evt) {
- var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1;
- evt.value = evt.point.x;
- evt.series = {
- value: evt.point.y,
- color: evt.point.color
- };
- tooltip
- .duration(100)
- .valueFormatter(function(d, i) {
- return yaxis.tickFormat()(d, i);
- })
- .data(evt)
- .position(evt.pos)
- .hidden(false);
- }
-
- function mouseover_stack(evt) {
- var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1;
- evt.point['x'] = stack1.x()(evt.point);
- evt.point['y'] = stack1.y()(evt.point);
- tooltip
- .duration(100)
- .valueFormatter(function(d, i) {
- return yaxis.tickFormat()(d, i);
- })
- .data(evt)
- .position(evt.pos)
- .hidden(false);
- }
-
- function mouseover_bar(evt) {
- var yaxis = data[evt.data.series].yAxis === 2 ? yAxis2 : yAxis1;
-
- evt.value = bars1.x()(evt.data);
- evt['series'] = {
- value: bars1.y()(evt.data),
- color: evt.color
- };
- tooltip
- .duration(0)
- .valueFormatter(function(d, i) {
- return yaxis.tickFormat()(d, i);
- })
- .data(evt)
- .hidden(false);
- }
-
- lines1.dispatch.on('elementMouseover.tooltip', mouseover_line);
- lines2.dispatch.on('elementMouseover.tooltip', mouseover_line);
- lines1.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true)
- });
- lines2.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true)
- });
-
- stack1.dispatch.on('elementMouseover.tooltip', mouseover_stack);
- stack2.dispatch.on('elementMouseover.tooltip', mouseover_stack);
- stack1.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true)
- });
- stack2.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true)
- });
-
- bars1.dispatch.on('elementMouseover.tooltip', mouseover_bar);
- bars2.dispatch.on('elementMouseover.tooltip', mouseover_bar);
-
- bars1.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true);
- });
- bars2.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true);
- });
- bars1.dispatch.on('elementMousemove.tooltip', function(evt) {
- tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
- });
- bars2.dispatch.on('elementMousemove.tooltip', function(evt) {
- tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
- });
-
- });
-
- return chart;
- }
-
- //============================================================
- // Global getters and setters
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.lines1 = lines1;
- chart.lines2 = lines2;
- chart.bars1 = bars1;
- chart.bars2 = bars2;
- chart.stack1 = stack1;
- chart.stack2 = stack2;
- chart.xAxis = xAxis;
- chart.yAxis1 = yAxis1;
- chart.yAxis2 = yAxis2;
- chart.tooltip = tooltip;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
- yDomain1: {get: function(){return yDomain1;}, set: function(_){yDomain1=_;}},
- yDomain2: {get: function(){return yDomain2;}, set: function(_){yDomain2=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
- interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }},
- x: {get: function(){return getX;}, set: function(_){
- getX = _;
- lines1.x(_);
- lines2.x(_);
- bars1.x(_);
- bars2.x(_);
- stack1.x(_);
- stack2.x(_);
- }},
- y: {get: function(){return getY;}, set: function(_){
- getY = _;
- lines1.y(_);
- lines2.y(_);
- stack1.y(_);
- stack2.y(_);
- bars1.y(_);
- bars2.y(_);
- }},
- useVoronoi: {get: function(){return useVoronoi;}, set: function(_){
- useVoronoi=_;
- lines1.useVoronoi(_);
- lines2.useVoronoi(_);
- stack1.useVoronoi(_);
- stack2.useVoronoi(_);
- }}
- });
-
- nv.utils.initOptions(chart);
-
- return chart;
-};
-
-
-nv.models.ohlcBar = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = null
- , height = null
- , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
- , container = null
- , x = d3.scale.linear()
- , y = d3.scale.linear()
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , getOpen = function(d) { return d.open }
- , getClose = function(d) { return d.close }
- , getHigh = function(d) { return d.high }
- , getLow = function(d) { return d.low }
- , forceX = []
- , forceY = []
- , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart
- , clipEdge = true
- , color = nv.utils.defaultColor()
- , interactive = false
- , xDomain
- , yDomain
- , xRange
- , yRange
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove')
- ;
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- function chart(selection) {
- selection.each(function(data) {
- container = d3.select(this);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- nv.utils.initSVG(container);
-
- // ohlc bar width.
- var w = (availableWidth / data[0].values.length) * .9;
-
- // Setup Scales
- x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ));
-
- if (padData)
- x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);
- else
- x.range(xRange || [5 + w/2, availableWidth - w/2 - 5]);
-
- y.domain(yDomain || [
- d3.min(data[0].values.map(getLow).concat(forceY)),
- d3.max(data[0].values.map(getHigh).concat(forceY))
- ]
- ).range(yRange || [availableHeight, 0]);
-
- // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
- if (x.domain()[0] === x.domain()[1])
- x.domain()[0] ?
- x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])
- : x.domain([-1,1]);
-
- if (y.domain()[0] === y.domain()[1])
- y.domain()[0] ?
- y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])
- : y.domain([-1,1]);
-
- // Setup containers and skeleton of chart
- var wrap = d3.select(this).selectAll('g.nv-wrap.nv-ohlcBar').data([data[0].values]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-ohlcBar');
- var defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-ticks');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- container
- .on('click', function(d,i) {
- dispatch.chartClick({
- data: d,
- index: i,
- pos: d3.event,
- id: id
- });
- });
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-chart-clip-path-' + id)
- .append('rect');
-
- wrap.select('#nv-chart-clip-path-' + id + ' rect')
- .attr('width', availableWidth)
- .attr('height', availableHeight);
-
- g .attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : '');
-
- var ticks = wrap.select('.nv-ticks').selectAll('.nv-tick')
- .data(function(d) { return d });
- ticks.exit().remove();
-
- ticks.enter().append('path')
- .attr('class', function(d,i,j) { return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i })
- .attr('d', function(d,i) {
- return 'm0,0l0,'
- + (y(getOpen(d,i))
- - y(getHigh(d,i)))
- + 'l'
- + (-w/2)
- + ',0l'
- + (w/2)
- + ',0l0,'
- + (y(getLow(d,i)) - y(getOpen(d,i)))
- + 'l0,'
- + (y(getClose(d,i))
- - y(getLow(d,i)))
- + 'l'
- + (w/2)
- + ',0l'
- + (-w/2)
- + ',0z';
- })
- .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; })
- .attr('fill', function(d,i) { return color[0]; })
- .attr('stroke', function(d,i) { return color[0]; })
- .attr('x', 0 )
- .attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) })
- .attr('height', function(d,i) { return Math.abs(y(getY(d,i)) - y(0)) });
-
- // the bar colors are controlled by CSS currently
- ticks.attr('class', function(d,i,j) {
- return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i;
- });
-
- d3.transition(ticks)
- .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; })
- .attr('d', function(d,i) {
- var w = (availableWidth / data[0].values.length) * .9;
- return 'm0,0l0,'
- + (y(getOpen(d,i))
- - y(getHigh(d,i)))
- + 'l'
- + (-w/2)
- + ',0l'
- + (w/2)
- + ',0l0,'
- + (y(getLow(d,i))
- - y(getOpen(d,i)))
- + 'l0,'
- + (y(getClose(d,i))
- - y(getLow(d,i)))
- + 'l'
- + (w/2)
- + ',0l'
- + (-w/2)
- + ',0z';
- });
- });
-
- return chart;
- }
-
-
- //Create methods to allow outside functions to highlight a specific bar.
- chart.highlightPoint = function(pointIndex, isHoverOver) {
- chart.clearHighlights();
- container.select(".nv-ohlcBar .nv-tick-0-" + pointIndex)
- .classed("hover", isHoverOver)
- ;
- };
-
- chart.clearHighlights = function() {
- container.select(".nv-ohlcBar .nv-tick.hover")
- .classed("hover", false)
- ;
- };
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- xScale: {get: function(){return x;}, set: function(_){x=_;}},
- yScale: {get: function(){return y;}, set: function(_){y=_;}},
- xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
- yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
- xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},
- yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},
- forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}},
- forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},
- padData: {get: function(){return padData;}, set: function(_){padData=_;}},
- clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
- id: {get: function(){return id;}, set: function(_){id=_;}},
- interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}},
-
- x: {get: function(){return getX;}, set: function(_){getX=_;}},
- y: {get: function(){return getY;}, set: function(_){getY=_;}},
- open: {get: function(){return getOpen();}, set: function(_){getOpen=_;}},
- close: {get: function(){return getClose();}, set: function(_){getClose=_;}},
- high: {get: function(){return getHigh;}, set: function(_){getHigh=_;}},
- low: {get: function(){return getLow;}, set: function(_){getLow=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top != undefined ? _.top : margin.top;
- margin.right = _.right != undefined ? _.right : margin.right;
- margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom;
- margin.left = _.left != undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }}
- });
-
- nv.utils.initOptions(chart);
- return chart;
-};
-// Code adapted from Jason Davies' "Parallel Coordinates"
-// http://bl.ocks.org/jasondavies/1341281
-nv.models.parallelCoordinates = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 30, right: 0, bottom: 10, left: 0}
- , width = null
- , height = null
- , x = d3.scale.ordinal()
- , y = {}
- , dimensionNames = []
- , dimensionFormats = []
- , color = nv.utils.defaultColor()
- , filters = []
- , active = []
- , dragging = []
- , lineTension = 1
- , dispatch = d3.dispatch('brush', 'elementMouseover', 'elementMouseout')
- ;
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- nv.utils.initSVG(container);
-
- active = data; //set all active before first brush call
-
- // Setup Scales
- x.rangePoints([0, availableWidth], 1).domain(dimensionNames);
-
- //Set as true if all values on an axis are missing.
- var onlyNanValues = {};
- // Extract the list of dimensions and create a scale for each.
- dimensionNames.forEach(function(d) {
- var extent = d3.extent(data, function(p) { return +p[d]; });
- onlyNanValues[d] = false;
- //If there is no values to display on an axis, set the extent to 0
- if (extent[0] === undefined) {
- onlyNanValues[d] = true;
- extent[0] = 0;
- extent[1] = 0;
- }
- //Scale axis if there is only one value
- if (extent[0] === extent[1]) {
- extent[0] = extent[0] - 1;
- extent[1] = extent[1] + 1;
- }
- //Use 90% of (availableHeight - 12) for the axis range, 12 reprensenting the space necessary to display "undefined values" text.
- //The remaining 10% are used to display the missingValue line.
- y[d] = d3.scale.linear()
- .domain(extent)
- .range([(availableHeight - 12) * 0.9, 0]);
-
- y[d].brush = d3.svg.brush().y(y[d]).on('brush', brush);
-
- return d != 'name';
- });
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-parallelCoordinates').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-parallelCoordinates');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-parallelCoordinates background');
- gEnter.append('g').attr('class', 'nv-parallelCoordinates foreground');
- gEnter.append('g').attr('class', 'nv-parallelCoordinates missingValuesline');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- var line = d3.svg.line().interpolate('cardinal').tension(lineTension),
- axis = d3.svg.axis().orient('left'),
- axisDrag = d3.behavior.drag()
- .on('dragstart', dragStart)
- .on('drag', dragMove)
- .on('dragend', dragEnd);
-
- //Add missing value line at the bottom of the chart
- var missingValuesline, missingValueslineText;
- var step = x.range()[1] - x.range()[0];
- var axisWithMissingValues = [];
- var lineData = [0 + step / 2, availableHeight - 12, availableWidth - step / 2, availableHeight - 12];
- missingValuesline = wrap.select('.missingValuesline').selectAll('line').data([lineData]);
- missingValuesline.enter().append('line');
- missingValuesline.exit().remove();
- missingValuesline.attr("x1", function(d) { return d[0]; })
- .attr("y1", function(d) { return d[1]; })
- .attr("x2", function(d) { return d[2]; })
- .attr("y2", function(d) { return d[3]; });
-
- //Add the text "undefined values" under the missing value line
- missingValueslineText = wrap.select('.missingValuesline').selectAll('text').data(["undefined values"]);
- missingValueslineText.append('text').data(["undefined values"]);
- missingValueslineText.enter().append('text');
- missingValueslineText.exit().remove();
- missingValueslineText.attr("y", availableHeight)
- //To have the text right align with the missingValues line, substract 92 representing the text size.
- .attr("x", availableWidth - 92 - step / 2)
- .text(function(d) { return d; });
-
- // Add grey background lines for context.
- var background = wrap.select('.background').selectAll('path').data(data);
- background.enter().append('path');
- background.exit().remove();
- background.attr('d', path);
-
- // Add blue foreground lines for focus.
- var foreground = wrap.select('.foreground').selectAll('path').data(data);
- foreground.enter().append('path')
- foreground.exit().remove();
- foreground.attr('d', path).attr('stroke', color);
- foreground.on("mouseover", function (d, i) {
- d3.select(this).classed('hover', true);
- dispatch.elementMouseover({
- label: d.name,
- data: d.data,
- index: i,
- pos: [d3.mouse(this.parentNode)[0], d3.mouse(this.parentNode)[1]]
- });
-
- });
- foreground.on("mouseout", function (d, i) {
- d3.select(this).classed('hover', false);
- dispatch.elementMouseout({
- label: d.name,
- data: d.data,
- index: i
- });
- });
-
- // Add a group element for each dimension.
- var dimensions = g.selectAll('.dimension').data(dimensionNames);
- var dimensionsEnter = dimensions.enter().append('g').attr('class', 'nv-parallelCoordinates dimension');
- dimensionsEnter.append('g').attr('class', 'nv-parallelCoordinates nv-axis');
- dimensionsEnter.append('g').attr('class', 'nv-parallelCoordinates-brush');
- dimensionsEnter.append('text').attr('class', 'nv-parallelCoordinates nv-label');
-
- dimensions.attr('transform', function(d) { return 'translate(' + x(d) + ',0)'; });
- dimensions.exit().remove();
-
- // Add an axis and title.
- dimensions.select('.nv-label')
- .style("cursor", "move")
- .attr('dy', '-1em')
- .attr('text-anchor', 'middle')
- .text(String)
- .on("mouseover", function(d, i) {
- dispatch.elementMouseover({
- dim: d,
- pos: [d3.mouse(this.parentNode.parentNode)[0], d3.mouse(this.parentNode.parentNode)[1]]
- });
- })
- .on("mouseout", function(d, i) {
- dispatch.elementMouseout({
- dim: d
- });
- })
- .call(axisDrag);
-
- dimensions.select('.nv-axis')
- .each(function (d, i) {
- d3.select(this).call(axis.scale(y[d]).tickFormat(d3.format(dimensionFormats[i])));
- });
-
- dimensions.select('.nv-parallelCoordinates-brush')
- .each(function (d) {
- d3.select(this).call(y[d].brush);
- })
- .selectAll('rect')
- .attr('x', -8)
- .attr('width', 16);
-
- // Returns the path for a given data point.
- function path(d) {
- return line(dimensionNames.map(function (p) {
- //If value if missing, put the value on the missing value line
- if(isNaN(d[p]) || isNaN(parseFloat(d[p]))) {
- var domain = y[p].domain();
- var range = y[p].range();
- var min = domain[0] - (domain[1] - domain[0]) / 9;
-
- //If it's not already the case, allow brush to select undefined values
- if(axisWithMissingValues.indexOf(p) < 0) {
-
- var newscale = d3.scale.linear().domain([min, domain[1]]).range([availableHeight - 12, range[1]]);
- y[p].brush.y(newscale);
- axisWithMissingValues.push(p);
- }
-
- return [x(p), y[p](min)];
- }
-
- //If parallelCoordinate contain missing values show the missing values line otherwise, hide it.
- if(axisWithMissingValues.length > 0) {
- missingValuesline.style("display", "inline");
- missingValueslineText.style("display", "inline");
- } else {
- missingValuesline.style("display", "none");
- missingValueslineText.style("display", "none");
- }
-
- return [x(p), y[p](d[p])];
- }));
- }
-
- // Handles a brush event, toggling the display of foreground lines.
- function brush() {
- var actives = dimensionNames.filter(function(p) { return !y[p].brush.empty(); }),
- extents = actives.map(function(p) { return y[p].brush.extent(); });
-
- filters = []; //erase current filters
- actives.forEach(function(d,i) {
- filters[i] = {
- dimension: d,
- extent: extents[i]
- }
- });
-
- active = []; //erase current active list
- foreground.style('display', function(d) {
- var isActive = actives.every(function(p, i) {
- if(isNaN(d[p]) && extents[i][0] == y[p].brush.y().domain()[0]) return true;
- return extents[i][0] <= d[p] && d[p] <= extents[i][1];
- });
- if (isActive) active.push(d);
- return isActive ? null : 'none';
- });
-
- dispatch.brush({
- filters: filters,
- active: active
- });
- }
-
- function dragStart(d, i) {
- dragging[d] = this.parentNode.__origin__ = x(d);
- background.attr("visibility", "hidden");
-
- }
-
- function dragMove(d, i) {
- dragging[d] = Math.min(availableWidth, Math.max(0, this.parentNode.__origin__ += d3.event.x));
- foreground.attr("d", path);
- dimensionNames.sort(function (a, b) { return position(a) - position(b); });
- x.domain(dimensionNames);
- dimensions.attr("transform", function(d) { return "translate(" + position(d) + ")"; });
- }
-
- function dragEnd(d, i) {
- delete this.parentNode.__origin__;
- delete dragging[d];
- d3.select(this.parentNode).attr("transform", "translate(" + x(d) + ")");
- foreground
- .attr("d", path);
- background
- .attr("d", path)
- .attr("visibility", null);
-
- }
-
- function position(d) {
- var v = dragging[d];
- return v == null ? x(d) : v;
- }
- });
-
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width= _;}},
- height: {get: function(){return height;}, set: function(_){height= _;}},
- dimensionNames: {get: function() { return dimensionNames;}, set: function(_){dimensionNames= _;}},
- dimensionFormats : {get: function(){return dimensionFormats;}, set: function (_){dimensionFormats=_;}},
- lineTension: {get: function(){return lineTension;}, set: function(_){lineTension = _;}},
-
- // deprecated options
- dimensions: {get: function (){return dimensionNames;}, set: function(_){
- // deprecated after 1.8.1
- nv.deprecated('dimensions', 'use dimensionNames instead');
- dimensionNames = _;
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }}
- });
-
- nv.utils.initOptions(chart);
- return chart;
-};
-nv.models.pie = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 500
- , height = 500
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
- , container = null
- , color = nv.utils.defaultColor()
- , valueFormat = d3.format(',.2f')
- , showLabels = true
- , labelsOutside = false
- , labelType = "key"
- , labelThreshold = .02 //if slice percentage is under this, don't show label
- , donut = false
- , title = false
- , growOnHover = true
- , titleOffset = 0
- , labelSunbeamLayout = false
- , startAngle = false
- , padAngle = false
- , endAngle = false
- , cornerRadius = 0
- , donutRatio = 0.5
- , arcsRadius = []
- , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
- ;
-
- var arcs = [];
- var arcsOver = [];
-
- //============================================================
- // chart function
- //------------------------------------------------------------
-
- var renderWatch = nv.utils.renderWatch(dispatch);
-
- function chart(selection) {
- renderWatch.reset();
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right
- , availableHeight = height - margin.top - margin.bottom
- , radius = Math.min(availableWidth, availableHeight) / 2
- , arcsRadiusOuter = []
- , arcsRadiusInner = []
- ;
-
- container = d3.select(this)
- if (arcsRadius.length === 0) {
- var outer = radius - radius / 5;
- var inner = donutRatio * radius;
- for (var i = 0; i < data[0].length; i++) {
- arcsRadiusOuter.push(outer);
- arcsRadiusInner.push(inner);
- }
- } else {
- arcsRadiusOuter = arcsRadius.map(function (d) { return (d.outer - d.outer / 5) * radius; });
- arcsRadiusInner = arcsRadius.map(function (d) { return (d.inner - d.inner / 5) * radius; });
- donutRatio = d3.min(arcsRadius.map(function (d) { return (d.inner - d.inner / 5); }));
- }
- nv.utils.initSVG(container);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('.nv-wrap.nv-pie').data(data);
- var wrapEnter = wrap.enter().append('g').attr('class','nvd3 nv-wrap nv-pie nv-chart-' + id);
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
- var g_pie = gEnter.append('g').attr('class', 'nv-pie');
- gEnter.append('g').attr('class', 'nv-pieLabels');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
- g.select('.nv-pie').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');
- g.select('.nv-pieLabels').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');
-
- //
- container.on('click', function(d,i) {
- dispatch.chartClick({
- data: d,
- index: i,
- pos: d3.event,
- id: id
- });
- });
-
- arcs = [];
- arcsOver = [];
- for (var i = 0; i < data[0].length; i++) {
-
- var arc = d3.svg.arc().outerRadius(arcsRadiusOuter[i]);
- var arcOver = d3.svg.arc().outerRadius(arcsRadiusOuter[i] + 5);
-
- if (startAngle !== false) {
- arc.startAngle(startAngle);
- arcOver.startAngle(startAngle);
- }
- if (endAngle !== false) {
- arc.endAngle(endAngle);
- arcOver.endAngle(endAngle);
- }
- if (donut) {
- arc.innerRadius(arcsRadiusInner[i]);
- arcOver.innerRadius(arcsRadiusInner[i]);
- }
-
- if (arc.cornerRadius && cornerRadius) {
- arc.cornerRadius(cornerRadius);
- arcOver.cornerRadius(cornerRadius);
- }
-
- arcs.push(arc);
- arcsOver.push(arcOver);
- }
-
- // Setup the Pie chart and choose the data element
- var pie = d3.layout.pie()
- .sort(null)
- .value(function(d) { return d.disabled ? 0 : getY(d) });
-
- // padAngle added in d3 3.5
- if (pie.padAngle && padAngle) {
- pie.padAngle(padAngle);
- }
-
- // if title is specified and donut, put it in the middle
- if (donut && title) {
- g_pie.append("text").attr('class', 'nv-pie-title');
-
- wrap.select('.nv-pie-title')
- .style("text-anchor", "middle")
- .text(function (d) {
- return title;
- })
- .style("font-size", (Math.min(availableWidth, availableHeight)) * donutRatio * 2 / (title.length + 2) + "px")
- .attr("dy", "0.35em") // trick to vertically center text
- .attr('transform', function(d, i) {
- return 'translate(0, '+ titleOffset + ')';
- });
- }
-
- var slices = wrap.select('.nv-pie').selectAll('.nv-slice').data(pie);
- var pieLabels = wrap.select('.nv-pieLabels').selectAll('.nv-label').data(pie);
-
- slices.exit().remove();
- pieLabels.exit().remove();
-
- var ae = slices.enter().append('g');
- ae.attr('class', 'nv-slice');
- ae.on('mouseover', function(d, i) {
- d3.select(this).classed('hover', true);
- if (growOnHover) {
- d3.select(this).select("path").transition()
- .duration(70)
- .attr("d", arcsOver[i]);
- }
- dispatch.elementMouseover({
- data: d.data,
- index: i,
- color: d3.select(this).style("fill")
- });
- });
- ae.on('mouseout', function(d, i) {
- d3.select(this).classed('hover', false);
- if (growOnHover) {
- d3.select(this).select("path").transition()
- .duration(50)
- .attr("d", arcs[i]);
- }
- dispatch.elementMouseout({data: d.data, index: i});
- });
- ae.on('mousemove', function(d, i) {
- dispatch.elementMousemove({data: d.data, index: i});
- });
- ae.on('click', function(d, i) {
- dispatch.elementClick({
- data: d.data,
- index: i,
- color: d3.select(this).style("fill")
- });
- });
- ae.on('dblclick', function(d, i) {
- dispatch.elementDblClick({
- data: d.data,
- index: i,
- color: d3.select(this).style("fill")
- });
- });
-
- slices.attr('fill', function(d,i) { return color(d.data, i); });
- slices.attr('stroke', function(d,i) { return color(d.data, i); });
-
- var paths = ae.append('path').each(function(d) {
- this._current = d;
- });
-
- slices.select('path')
- .transition()
- .attr('d', function (d, i) { return arcs[i](d); })
- .attrTween('d', arcTween);
-
- if (showLabels) {
- // This does the normal label
- var labelsArc = [];
- for (var i = 0; i < data[0].length; i++) {
- labelsArc.push(arcs[i]);
-
- if (labelsOutside) {
- if (donut) {
- labelsArc[i] = d3.svg.arc().outerRadius(arcs[i].outerRadius());
- if (startAngle !== false) labelsArc[i].startAngle(startAngle);
- if (endAngle !== false) labelsArc[i].endAngle(endAngle);
- }
- } else if (!donut) {
- labelsArc[i].innerRadius(0);
- }
- }
-
- pieLabels.enter().append("g").classed("nv-label",true).each(function(d,i) {
- var group = d3.select(this);
-
- group.attr('transform', function (d, i) {
- if (labelSunbeamLayout) {
- d.outerRadius = arcsRadiusOuter[i] + 10; // Set Outer Coordinate
- d.innerRadius = arcsRadiusOuter[i] + 15; // Set Inner Coordinate
- var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);
- if ((d.startAngle + d.endAngle) / 2 < Math.PI) {
- rotateAngle -= 90;
- } else {
- rotateAngle += 90;
- }
- return 'translate(' + labelsArc[i].centroid(d) + ') rotate(' + rotateAngle + ')';
- } else {
- d.outerRadius = radius + 10; // Set Outer Coordinate
- d.innerRadius = radius + 15; // Set Inner Coordinate
- return 'translate(' + labelsArc[i].centroid(d) + ')'
- }
- });
-
- group.append('rect')
- .style('stroke', '#fff')
- .style('fill', '#fff')
- .attr("rx", 3)
- .attr("ry", 3);
-
- group.append('text')
- .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned
- .style('fill', '#000')
- });
-
- var labelLocationHash = {};
- var avgHeight = 14;
- var avgWidth = 140;
- var createHashKey = function(coordinates) {
- return Math.floor(coordinates[0]/avgWidth) * avgWidth + ',' + Math.floor(coordinates[1]/avgHeight) * avgHeight;
- };
-
- pieLabels.watchTransition(renderWatch, 'pie labels').attr('transform', function (d, i) {
- if (labelSunbeamLayout) {
- d.outerRadius = arcsRadiusOuter[i] + 10; // Set Outer Coordinate
- d.innerRadius = arcsRadiusOuter[i] + 15; // Set Inner Coordinate
- var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);
- if ((d.startAngle + d.endAngle) / 2 < Math.PI) {
- rotateAngle -= 90;
- } else {
- rotateAngle += 90;
- }
- return 'translate(' + labelsArc[i].centroid(d) + ') rotate(' + rotateAngle + ')';
- } else {
- d.outerRadius = radius + 10; // Set Outer Coordinate
- d.innerRadius = radius + 15; // Set Inner Coordinate
-
- /*
- Overlapping pie labels are not good. What this attempts to do is, prevent overlapping.
- Each label location is hashed, and if a hash collision occurs, we assume an overlap.
- Adjust the label's y-position to remove the overlap.
- */
- var center = labelsArc[i].centroid(d);
- if (d.value) {
- var hashKey = createHashKey(center);
- if (labelLocationHash[hashKey]) {
- center[1] -= avgHeight;
- }
- labelLocationHash[createHashKey(center)] = true;
- }
- return 'translate(' + center + ')'
- }
- });
-
- pieLabels.select(".nv-label text")
- .style('text-anchor', function(d,i) {
- //center the text on it's origin or begin/end if orthogonal aligned
- return labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle';
- })
- .text(function(d, i) {
- var percent = (d.endAngle - d.startAngle) / (2 * Math.PI);
- var label = '';
- if (!d.value || percent < labelThreshold) return '';
-
- if(typeof labelType === 'function') {
- label = labelType(d, i, {
- 'key': getX(d.data),
- 'value': getY(d.data),
- 'percent': valueFormat(percent)
- });
- } else {
- switch (labelType) {
- case 'key':
- label = getX(d.data);
- break;
- case 'value':
- label = valueFormat(getY(d.data));
- break;
- case 'percent':
- label = d3.format('%')(percent);
- break;
- }
- }
- return label;
- })
- ;
- }
-
-
- // Computes the angle of an arc, converting from radians to degrees.
- function angle(d) {
- var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
- return a > 90 ? a - 180 : a;
- }
-
- function arcTween(a, idx) {
- a.endAngle = isNaN(a.endAngle) ? 0 : a.endAngle;
- a.startAngle = isNaN(a.startAngle) ? 0 : a.startAngle;
- if (!donut) a.innerRadius = 0;
- var i = d3.interpolate(this._current, a);
- this._current = i(0);
- return function (t) {
- return arcs[idx](i(t));
- };
- }
- });
-
- renderWatch.renderEnd('pie immediate');
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- arcsRadius: { get: function () { return arcsRadius; }, set: function (_) { arcsRadius = _; } },
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- showLabels: {get: function(){return showLabels;}, set: function(_){showLabels=_;}},
- title: {get: function(){return title;}, set: function(_){title=_;}},
- titleOffset: {get: function(){return titleOffset;}, set: function(_){titleOffset=_;}},
- labelThreshold: {get: function(){return labelThreshold;}, set: function(_){labelThreshold=_;}},
- valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},
- x: {get: function(){return getX;}, set: function(_){getX=_;}},
- id: {get: function(){return id;}, set: function(_){id=_;}},
- endAngle: {get: function(){return endAngle;}, set: function(_){endAngle=_;}},
- startAngle: {get: function(){return startAngle;}, set: function(_){startAngle=_;}},
- padAngle: {get: function(){return padAngle;}, set: function(_){padAngle=_;}},
- cornerRadius: {get: function(){return cornerRadius;}, set: function(_){cornerRadius=_;}},
- donutRatio: {get: function(){return donutRatio;}, set: function(_){donutRatio=_;}},
- labelsOutside: {get: function(){return labelsOutside;}, set: function(_){labelsOutside=_;}},
- labelSunbeamLayout: {get: function(){return labelSunbeamLayout;}, set: function(_){labelSunbeamLayout=_;}},
- donut: {get: function(){return donut;}, set: function(_){donut=_;}},
- growOnHover: {get: function(){return growOnHover;}, set: function(_){growOnHover=_;}},
-
- // depreciated after 1.7.1
- pieLabelsOutside: {get: function(){return labelsOutside;}, set: function(_){
- labelsOutside=_;
- nv.deprecated('pieLabelsOutside', 'use labelsOutside instead');
- }},
- // depreciated after 1.7.1
- donutLabelsOutside: {get: function(){return labelsOutside;}, set: function(_){
- labelsOutside=_;
- nv.deprecated('donutLabelsOutside', 'use labelsOutside instead');
- }},
- // deprecated after 1.7.1
- labelFormat: {get: function(){ return valueFormat;}, set: function(_) {
- valueFormat=_;
- nv.deprecated('labelFormat','use valueFormat instead');
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
- margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
- margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
- margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
- }},
- y: {get: function(){return getY;}, set: function(_){
- getY=d3.functor(_);
- }},
- color: {get: function(){return color;}, set: function(_){
- color=nv.utils.getColor(_);
- }},
- labelType: {get: function(){return labelType;}, set: function(_){
- labelType= _ || 'key';
- }}
- });
-
- nv.utils.initOptions(chart);
- return chart;
-};
-nv.models.pieChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var pie = nv.models.pie();
- var legend = nv.models.legend();
- var tooltip = nv.models.tooltip();
-
- var margin = {top: 30, right: 20, bottom: 20, left: 20}
- , width = null
- , height = null
- , showLegend = true
- , legendPosition = "top"
- , color = nv.utils.defaultColor()
- , state = nv.utils.state()
- , defaultState = null
- , noData = null
- , duration = 250
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd')
- ;
-
- tooltip
- .headerEnabled(false)
- .duration(0)
- .valueFormatter(function(d, i) {
- return pie.valueFormat()(d, i);
- });
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var renderWatch = nv.utils.renderWatch(dispatch);
-
- var stateGetter = function(data) {
- return function(){
- return {
- active: data.map(function(d) { return !d.disabled })
- };
- }
- };
-
- var stateSetter = function(data) {
- return function(state) {
- if (state.active !== undefined) {
- data.forEach(function (series, i) {
- series.disabled = !state.active[i];
- });
- }
- }
- };
-
- //============================================================
- // Chart function
- //------------------------------------------------------------
-
- function chart(selection) {
- renderWatch.reset();
- renderWatch.models(pie);
-
- selection.each(function(data) {
- var container = d3.select(this);
- nv.utils.initSVG(container);
-
- var that = this;
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- chart.update = function() { container.transition().call(chart); };
- chart.container = this;
-
- state.setter(stateSetter(data), chart.update)
- .getter(stateGetter(data))
- .update();
-
- //set state.disabled
- state.disabled = data.map(function(d) { return !!d.disabled });
-
- if (!defaultState) {
- var key;
- defaultState = {};
- for (key in state) {
- if (state[key] instanceof Array)
- defaultState[key] = state[key].slice(0);
- else
- defaultState[key] = state[key];
- }
- }
-
- // Display No Data message if there's nothing to show.
- if (!data || !data.length) {
- nv.utils.noData(chart, container);
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-pieChart').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-pieChart').append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-pieWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
-
- // Legend
- if (showLegend) {
- if (legendPosition === "top") {
- legend.width( availableWidth ).key(pie.x());
-
- wrap.select('.nv-legendWrap')
- .datum(data)
- .call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- availableHeight = nv.utils.availableHeight(height, container, margin);
- }
-
- wrap.select('.nv-legendWrap')
- .attr('transform', 'translate(0,' + (-margin.top) +')');
- } else if (legendPosition === "right") {
- var legendWidth = nv.models.legend().width();
- if (availableWidth / 2 < legendWidth) {
- legendWidth = (availableWidth / 2)
- }
- legend.height(availableHeight).key(pie.x());
- legend.width(legendWidth);
- availableWidth -= legend.width();
-
- wrap.select('.nv-legendWrap')
- .datum(data)
- .call(legend)
- .attr('transform', 'translate(' + (availableWidth) +',0)');
- }
- }
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- // Main Chart Component(s)
- pie.width(availableWidth).height(availableHeight);
- var pieWrap = g.select('.nv-pieWrap').datum([data]);
- d3.transition(pieWrap).call(pie);
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('stateChange', function(newState) {
- for (var key in newState) {
- state[key] = newState[key];
- }
- dispatch.stateChange(state);
- chart.update();
- });
-
- // Update chart from a state object passed to event handler
- dispatch.on('changeState', function(e) {
- if (typeof e.disabled !== 'undefined') {
- data.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
- state.disabled = e.disabled;
- }
- chart.update();
- });
- });
-
- renderWatch.renderEnd('pieChart immediate');
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- pie.dispatch.on('elementMouseover.tooltip', function(evt) {
- evt['series'] = {
- key: chart.x()(evt.data),
- value: chart.y()(evt.data),
- color: evt.color
- };
- tooltip.data(evt).hidden(false);
- });
-
- pie.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true);
- });
-
- pie.dispatch.on('elementMousemove.tooltip', function(evt) {
- tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
- });
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.legend = legend;
- chart.dispatch = dispatch;
- chart.pie = pie;
- chart.tooltip = tooltip;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- // use Object get/set functionality to map between vars and chart functions
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
- legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
-
- // options that require extra logic in the setter
- color: {get: function(){return color;}, set: function(_){
- color = _;
- legend.color(color);
- pie.color(color);
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- }},
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }}
- });
- nv.utils.inheritOptions(chart, pie);
- nv.utils.initOptions(chart);
- return chart;
-};
-
-nv.models.scatter = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = null
- , height = null
- , color = nv.utils.defaultColor() // chooses color
- , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't select one
- , container = null
- , x = d3.scale.linear()
- , y = d3.scale.linear()
- , z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area
- , getX = function(d) { return d.x } // accessor to get the x value
- , getY = function(d) { return d.y } // accessor to get the y value
- , getSize = function(d) { return d.size || 1} // accessor to get the point size
- , getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape
- , forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
- , forceY = [] // List of numbers to Force into the Y scale
- , forceSize = [] // List of numbers to Force into the Size scale
- , interactive = true // If true, plots a voronoi overlay for advanced point intersection
- , pointActive = function(d) { return !d.notActive } // any points that return false will be filtered out
- , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart
- , padDataOuter = .1 //outerPadding to imitate ordinal scale outer padding
- , clipEdge = false // if true, masks points within x and y scale
- , clipVoronoi = true // if true, masks each point with a circle... can turn off to slightly increase performance
- , showVoronoi = false // display the voronoi areas
- , clipRadius = function() { return 25 } // function to get the radius for voronoi point clips
- , xDomain = null // Override x domain (skips the calculation from data)
- , yDomain = null // Override y domain
- , xRange = null // Override x range
- , yRange = null // Override y range
- , sizeDomain = null // Override point size domain
- , sizeRange = null
- , singlePoint = false
- , dispatch = d3.dispatch('elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd')
- , useVoronoi = true
- , duration = 250
- ;
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0, z0 // used to store previous scales
- , timeoutID
- , needsUpdate = false // Flag for when the points are visually updating, but the interactive layer is behind, to disable tooltips
- , renderWatch = nv.utils.renderWatch(dispatch, duration)
- , _sizeRange_def = [16, 256]
- ;
-
- function chart(selection) {
- renderWatch.reset();
- selection.each(function(data) {
- container = d3.select(this);
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- nv.utils.initSVG(container);
-
- //add series index to each data point for reference
- data.forEach(function(series, i) {
- series.values.forEach(function(point) {
- point.series = i;
- });
- });
-
- // Setup Scales
- // remap and flatten the data for use in calculating the scales' domains
- var seriesData = (xDomain && yDomain && sizeDomain) ? [] : // if we know xDomain and yDomain and sizeDomain, no need to calculate.... if Size is constant remember to set sizeDomain to speed up performance
- d3.merge(
- data.map(function(d) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i), size: getSize(d,i) }
- })
- })
- );
-
- x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x; }).concat(forceX)))
-
- if (padData && data[0])
- x.range(xRange || [(availableWidth * padDataOuter + availableWidth) / (2 *data[0].values.length), availableWidth - availableWidth * (1 + padDataOuter) / (2 * data[0].values.length) ]);
- //x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);
- else
- x.range(xRange || [0, availableWidth]);
-
- y .domain(yDomain || d3.extent(seriesData.map(function(d) { return d.y }).concat(forceY)))
- .range(yRange || [availableHeight, 0]);
-
- z .domain(sizeDomain || d3.extent(seriesData.map(function(d) { return d.size }).concat(forceSize)))
- .range(sizeRange || _sizeRange_def);
-
- // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
- singlePoint = x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1];
-
- if (x.domain()[0] === x.domain()[1])
- x.domain()[0] ?
- x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])
- : x.domain([-1,1]);
-
- if (y.domain()[0] === y.domain()[1])
- y.domain()[0] ?
- y.domain([y.domain()[0] - y.domain()[0] * 0.01, y.domain()[1] + y.domain()[1] * 0.01])
- : y.domain([-1,1]);
-
- if ( isNaN(x.domain()[0])) {
- x.domain([-1,1]);
- }
-
- if ( isNaN(y.domain()[0])) {
- y.domain([-1,1]);
- }
-
- x0 = x0 || x;
- y0 = y0 || y;
- z0 = z0 || z;
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-scatter').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatter nv-chart-' + id);
- var defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- wrap.classed('nv-single-point', singlePoint);
- gEnter.append('g').attr('class', 'nv-groups');
- gEnter.append('g').attr('class', 'nv-point-paths');
- wrapEnter.append('g').attr('class', 'nv-point-clips');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-edge-clip-' + id)
- .append('rect');
-
- wrap.select('#nv-edge-clip-' + id + ' rect')
- .attr('width', availableWidth)
- .attr('height', (availableHeight > 0) ? availableHeight : 0);
-
- g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
-
- function updateInteractiveLayer() {
- // Always clear needs-update flag regardless of whether or not
- // we will actually do anything (avoids needless invocations).
- needsUpdate = false;
-
- if (!interactive) return false;
-
- // inject series and point index for reference into voronoi
- if (useVoronoi === true) {
- var vertices = d3.merge(data.map(function(group, groupIndex) {
- return group.values
- .map(function(point, pointIndex) {
- // *Adding noise to make duplicates very unlikely
- // *Injecting series and point index for reference
- /* *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi.
- */
- var pX = getX(point,pointIndex);
- var pY = getY(point,pointIndex);
-
- return [x(pX)+ Math.random() * 1e-4,
- y(pY)+ Math.random() * 1e-4,
- groupIndex,
- pointIndex, point]; //temp hack to add noise until I think of a better way so there are no duplicates
- })
- .filter(function(pointArray, pointIndex) {
- return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct!
- })
- })
- );
-
- if (vertices.length == 0) return false; // No active points, we're done
- if (vertices.length < 3) {
- // Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work
- vertices.push([x.range()[0] - 20, y.range()[0] - 20, null, null]);
- vertices.push([x.range()[1] + 20, y.range()[1] + 20, null, null]);
- vertices.push([x.range()[0] - 20, y.range()[0] + 20, null, null]);
- vertices.push([x.range()[1] + 20, y.range()[1] - 20, null, null]);
- }
-
- // keep voronoi sections from going more than 10 outside of graph
- // to avoid overlap with other things like legend etc
- var bounds = d3.geom.polygon([
- [-10,-10],
- [-10,height + 10],
- [width + 10,height + 10],
- [width + 10,-10]
- ]);
-
- var voronoi = d3.geom.voronoi(vertices).map(function(d, i) {
- return {
- 'data': bounds.clip(d),
- 'series': vertices[i][2],
- 'point': vertices[i][3]
- }
- });
-
- // nuke all voronoi paths on reload and recreate them
- wrap.select('.nv-point-paths').selectAll('path').remove();
- var pointPaths = wrap.select('.nv-point-paths').selectAll('path').data(voronoi);
- var vPointPaths = pointPaths
- .enter().append("svg:path")
- .attr("d", function(d) {
- if (!d || !d.data || d.data.length === 0)
- return 'M 0 0';
- else
- return "M" + d.data.join(",") + "Z";
- })
- .attr("id", function(d,i) {
- return "nv-path-"+i; })
- .attr("clip-path", function(d,i) { return "url(#nv-clip-"+i+")"; })
- ;
-
- // good for debugging point hover issues
- if (showVoronoi) {
- vPointPaths.style("fill", d3.rgb(230, 230, 230))
- .style('fill-opacity', 0.4)
- .style('stroke-opacity', 1)
- .style("stroke", d3.rgb(200,200,200));
- }
-
- if (clipVoronoi) {
- // voronoi sections are already set to clip,
- // just create the circles with the IDs they expect
- wrap.select('.nv-point-clips').selectAll('clipPath').remove();
- wrap.select('.nv-point-clips').selectAll("clipPath")
- .data(vertices)
- .enter().append("svg:clipPath")
- .attr("id", function(d, i) { return "nv-clip-"+i;})
- .append("svg:circle")
- .attr('cx', function(d) { return d[0]; })
- .attr('cy', function(d) { return d[1]; })
- .attr('r', clipRadius);
- }
-
- var mouseEventCallback = function(d, mDispatch) {
- if (needsUpdate) return 0;
- var series = data[d.series];
- if (series === undefined) return;
- var point = series.values[d.point];
- point['color'] = color(series, d.series);
-
- // standardize attributes for tooltip.
- point['x'] = getX(point);
- point['y'] = getY(point);
-
- // can't just get box of event node since it's actually a voronoi polygon
- var box = container.node().getBoundingClientRect();
- var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
- var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
-
- var pos = {
- left: x(getX(point, d.point)) + box.left + scrollLeft + margin.left + 10,
- top: y(getY(point, d.point)) + box.top + scrollTop + margin.top + 10
- };
-
- mDispatch({
- point: point,
- series: series,
- pos: pos,
- seriesIndex: d.series,
- pointIndex: d.point
- });
- };
-
- pointPaths
- .on('click', function(d) {
- mouseEventCallback(d, dispatch.elementClick);
- })
- .on('dblclick', function(d) {
- mouseEventCallback(d, dispatch.elementDblClick);
- })
- .on('mouseover', function(d) {
- mouseEventCallback(d, dispatch.elementMouseover);
- })
- .on('mouseout', function(d, i) {
- mouseEventCallback(d, dispatch.elementMouseout);
- });
-
- } else {
- // add event handlers to points instead voronoi paths
- wrap.select('.nv-groups').selectAll('.nv-group')
- .selectAll('.nv-point')
- //.data(dataWithPoints)
- //.style('pointer-events', 'auto') // recativate events, disabled by css
- .on('click', function(d,i) {
- //nv.log('test', d, i);
- if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
- var series = data[d.series],
- point = series.values[i];
-
- dispatch.elementClick({
- point: point,
- series: series,
- pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
- seriesIndex: d.series,
- pointIndex: i
- });
- })
- .on('dblclick', function(d,i) {
- if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
- var series = data[d.series],
- point = series.values[i];
-
- dispatch.elementDblClick({
- point: point,
- series: series,
- pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
- seriesIndex: d.series,
- pointIndex: i
- });
- })
- .on('mouseover', function(d,i) {
- if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
- var series = data[d.series],
- point = series.values[i];
-
- dispatch.elementMouseover({
- point: point,
- series: series,
- pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
- seriesIndex: d.series,
- pointIndex: i,
- color: color(d, i)
- });
- })
- .on('mouseout', function(d,i) {
- if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
- var series = data[d.series],
- point = series.values[i];
-
- dispatch.elementMouseout({
- point: point,
- series: series,
- seriesIndex: d.series,
- pointIndex: i,
- color: color(d, i)
- });
- });
- }
- }
-
- needsUpdate = true;
- var groups = wrap.select('.nv-groups').selectAll('.nv-group')
- .data(function(d) { return d }, function(d) { return d.key });
- groups.enter().append('g')
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6);
- groups.exit()
- .remove();
- groups
- .attr('class', function(d,i) { return 'nv-group nv-series-' + i })
- .classed('hover', function(d) { return d.hover });
- groups.watchTransition(renderWatch, 'scatter: groups')
- .style('fill', function(d,i) { return color(d, i) })
- .style('stroke', function(d,i) { return color(d, i) })
- .style('stroke-opacity', 1)
- .style('fill-opacity', .5);
-
- // create the points, maintaining their IDs from the original data set
- var points = groups.selectAll('path.nv-point')
- .data(function(d) {
- return d.values.map(
- function (point, pointIndex) {
- return [point, pointIndex]
- }).filter(
- function(pointArray, pointIndex) {
- return pointActive(pointArray[0], pointIndex)
- })
- });
- points.enter().append('path')
- .style('fill', function (d) { return d.color })
- .style('stroke', function (d) { return d.color })
- .attr('transform', function(d) {
- return 'translate(' + x0(getX(d[0],d[1])) + ',' + y0(getY(d[0],d[1])) + ')'
- })
- .attr('d',
- nv.utils.symbol()
- .type(function(d) { return getShape(d[0]); })
- .size(function(d) { return z(getSize(d[0],d[1])) })
- );
- points.exit().remove();
- groups.exit().selectAll('path.nv-point')
- .watchTransition(renderWatch, 'scatter exit')
- .attr('transform', function(d) {
- return 'translate(' + x(getX(d[0],d[1])) + ',' + y(getY(d[0],d[1])) + ')'
- })
- .remove();
- points.each(function(d) {
- d3.select(this)
- .classed('nv-point', true)
- .classed('nv-point-' + d[1], true)
- .classed('nv-noninteractive', !interactive)
- .classed('hover',false)
- ;
- });
- points
- .watchTransition(renderWatch, 'scatter points')
- .attr('transform', function(d) {
- //nv.log(d, getX(d[0],d[1]), x(getX(d[0],d[1])));
- return 'translate(' + x(getX(d[0],d[1])) + ',' + y(getY(d[0],d[1])) + ')'
- })
- .attr('d',
- nv.utils.symbol()
- .type(function(d) { return getShape(d[0]); })
- .size(function(d) { return z(getSize(d[0],d[1])) })
- );
-
- // Delay updating the invisible interactive layer for smoother animation
- clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer
- timeoutID = setTimeout(updateInteractiveLayer, 300);
- //updateInteractiveLayer();
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
- z0 = z.copy();
-
- });
- renderWatch.renderEnd('scatter immediate');
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- // utility function calls provided by this chart
- chart._calls = new function() {
- this.clearHighlights = function () {
- nv.dom.write(function() {
- container.selectAll(".nv-point.hover").classed("hover", false);
- });
- return null;
- };
- this.highlightPoint = function (seriesIndex, pointIndex, isHoverOver) {
- nv.dom.write(function() {
- container.select(" .nv-series-" + seriesIndex + " .nv-point-" + pointIndex)
- .classed("hover", isHoverOver);
- });
- };
- };
-
- // trigger calls from events too
- dispatch.on('elementMouseover.point', function(d) {
- if (interactive) chart._calls.highlightPoint(d.seriesIndex,d.pointIndex,true);
- });
-
- dispatch.on('elementMouseout.point', function(d) {
- if (interactive) chart._calls.highlightPoint(d.seriesIndex,d.pointIndex,false);
- });
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- xScale: {get: function(){return x;}, set: function(_){x=_;}},
- yScale: {get: function(){return y;}, set: function(_){y=_;}},
- pointScale: {get: function(){return z;}, set: function(_){z=_;}},
- xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
- yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
- pointDomain: {get: function(){return sizeDomain;}, set: function(_){sizeDomain=_;}},
- xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},
- yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},
- pointRange: {get: function(){return sizeRange;}, set: function(_){sizeRange=_;}},
- forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}},
- forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},
- forcePoint: {get: function(){return forceSize;}, set: function(_){forceSize=_;}},
- interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}},
- pointActive: {get: function(){return pointActive;}, set: function(_){pointActive=_;}},
- padDataOuter: {get: function(){return padDataOuter;}, set: function(_){padDataOuter=_;}},
- padData: {get: function(){return padData;}, set: function(_){padData=_;}},
- clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
- clipVoronoi: {get: function(){return clipVoronoi;}, set: function(_){clipVoronoi=_;}},
- clipRadius: {get: function(){return clipRadius;}, set: function(_){clipRadius=_;}},
- showVoronoi: {get: function(){return showVoronoi;}, set: function(_){showVoronoi=_;}},
- id: {get: function(){return id;}, set: function(_){id=_;}},
-
-
- // simple functor options
- x: {get: function(){return getX;}, set: function(_){getX = d3.functor(_);}},
- y: {get: function(){return getY;}, set: function(_){getY = d3.functor(_);}},
- pointSize: {get: function(){return getSize;}, set: function(_){getSize = d3.functor(_);}},
- pointShape: {get: function(){return getShape;}, set: function(_){getShape = d3.functor(_);}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }},
- useVoronoi: {get: function(){return useVoronoi;}, set: function(_){
- useVoronoi = _;
- if (useVoronoi === false) {
- clipVoronoi = false;
- }
- }}
- });
-
- nv.utils.initOptions(chart);
- return chart;
-};
-
-nv.models.scatterChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var scatter = nv.models.scatter()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- , distX = nv.models.distribution()
- , distY = nv.models.distribution()
- , tooltip = nv.models.tooltip()
- ;
-
- var margin = {top: 30, right: 20, bottom: 50, left: 75}
- , width = null
- , height = null
- , container = null
- , color = nv.utils.defaultColor()
- , x = scatter.xScale()
- , y = scatter.yScale()
- , showDistX = false
- , showDistY = false
- , showLegend = true
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = false
- , state = nv.utils.state()
- , defaultState = null
- , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd')
- , noData = null
- , duration = 250
- ;
-
- scatter.xScale(x).yScale(y);
- xAxis.orient('bottom').tickPadding(10);
- yAxis
- .orient((rightAlignYAxis) ? 'right' : 'left')
- .tickPadding(10)
- ;
- distX.axis('x');
- distY.axis('y');
- tooltip
- .headerFormatter(function(d, i) {
- return xAxis.tickFormat()(d, i);
- })
- .valueFormatter(function(d, i) {
- return yAxis.tickFormat()(d, i);
- });
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0
- , renderWatch = nv.utils.renderWatch(dispatch, duration);
-
- var stateGetter = function(data) {
- return function(){
- return {
- active: data.map(function(d) { return !d.disabled })
- };
- }
- };
-
- var stateSetter = function(data) {
- return function(state) {
- if (state.active !== undefined)
- data.forEach(function(series,i) {
- series.disabled = !state.active[i];
- });
- }
- };
-
- function chart(selection) {
- renderWatch.reset();
- renderWatch.models(scatter);
- if (showXAxis) renderWatch.models(xAxis);
- if (showYAxis) renderWatch.models(yAxis);
- if (showDistX) renderWatch.models(distX);
- if (showDistY) renderWatch.models(distY);
-
- selection.each(function(data) {
- var that = this;
-
- container = d3.select(this);
- nv.utils.initSVG(container);
-
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- chart.update = function() {
- if (duration === 0)
- container.call(chart);
- else
- container.transition().duration(duration).call(chart);
- };
- chart.container = this;
-
- state
- .setter(stateSetter(data), chart.update)
- .getter(stateGetter(data))
- .update();
-
- // DEPRECATED set state.disableddisabled
- state.disabled = data.map(function(d) { return !!d.disabled });
-
- if (!defaultState) {
- var key;
- defaultState = {};
- for (key in state) {
- if (state[key] instanceof Array)
- defaultState[key] = state[key].slice(0);
- else
- defaultState[key] = state[key];
- }
- }
-
- // Display noData message if there's nothing to show.
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
- nv.utils.noData(chart, container);
- renderWatch.renderEnd('scatter immediate');
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- // Setup Scales
- x = scatter.xScale();
- y = scatter.yScale();
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-scatterChart').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatterChart nv-chart-' + scatter.id());
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- // background for pointer events
- gEnter.append('rect').attr('class', 'nvd3 nv-background').style("pointer-events","none");
-
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis');
- gEnter.append('g').attr('class', 'nv-scatterWrap');
- gEnter.append('g').attr('class', 'nv-regressionLinesWrap');
- gEnter.append('g').attr('class', 'nv-distWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- // Legend
- if (showLegend) {
- var legendWidth = availableWidth;
- legend.width(legendWidth);
-
- wrap.select('.nv-legendWrap')
- .datum(data)
- .call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- availableHeight = nv.utils.availableHeight(height, container, margin);
- }
-
- wrap.select('.nv-legendWrap')
- .attr('transform', 'translate(0' + ',' + (-margin.top) +')');
- }
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- // Main Chart Component(s)
- scatter
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
-
- wrap.select('.nv-scatterWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(scatter);
-
-
- wrap.select('.nv-regressionLinesWrap')
- .attr('clip-path', 'url(#nv-edge-clip-' + scatter.id() + ')');
-
- var regWrap = wrap.select('.nv-regressionLinesWrap').selectAll('.nv-regLines')
- .data(function (d) {
- return d;
- });
-
- regWrap.enter().append('g').attr('class', 'nv-regLines');
-
- var regLine = regWrap.selectAll('.nv-regLine')
- .data(function (d) {
- return [d]
- });
-
- regLine.enter()
- .append('line').attr('class', 'nv-regLine')
- .style('stroke-opacity', 0);
-
- // don't add lines unless we have slope and intercept to use
- regLine.filter(function(d) {
- return d.intercept && d.slope;
- })
- .watchTransition(renderWatch, 'scatterPlusLineChart: regline')
- .attr('x1', x.range()[0])
- .attr('x2', x.range()[1])
- .attr('y1', function (d, i) {
- return y(x.domain()[0] * d.slope + d.intercept)
- })
- .attr('y2', function (d, i) {
- return y(x.domain()[1] * d.slope + d.intercept)
- })
- .style('stroke', function (d, i, j) {
- return color(d, j)
- })
- .style('stroke-opacity', function (d, i) {
- return (d.disabled || typeof d.slope === 'undefined' || typeof d.intercept === 'undefined') ? 0 : 1
- });
-
- // Setup Axes
- if (showXAxis) {
- xAxis
- .scale(x)
- ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize( -availableHeight , 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y.range()[0] + ')')
- .call(xAxis);
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis')
- .call(yAxis);
- }
-
-
- if (showDistX) {
- distX
- .getData(scatter.x())
- .scale(x)
- .width(availableWidth)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
- gEnter.select('.nv-distWrap').append('g')
- .attr('class', 'nv-distributionX');
- g.select('.nv-distributionX')
- .attr('transform', 'translate(0,' + y.range()[0] + ')')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(distX);
- }
-
- if (showDistY) {
- distY
- .getData(scatter.y())
- .scale(y)
- .width(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
- gEnter.select('.nv-distWrap').append('g')
- .attr('class', 'nv-distributionY');
- g.select('.nv-distributionY')
- .attr('transform', 'translate(' + (rightAlignYAxis ? availableWidth : -distY.size() ) + ',0)')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(distY);
- }
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('stateChange', function(newState) {
- for (var key in newState)
- state[key] = newState[key];
- dispatch.stateChange(state);
- chart.update();
- });
-
- // Update chart from a state object passed to event handler
- dispatch.on('changeState', function(e) {
- if (typeof e.disabled !== 'undefined') {
- data.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
- state.disabled = e.disabled;
- }
- chart.update();
- });
-
- // mouseover needs availableHeight so we just keep scatter mouse events inside the chart block
- scatter.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true);
- container.select('.nv-chart-' + scatter.id() + ' .nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex)
- .attr('y1', 0);
- container.select('.nv-chart-' + scatter.id() + ' .nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex)
- .attr('x2', distY.size());
- });
-
- scatter.dispatch.on('elementMouseover.tooltip', function(evt) {
- container.select('.nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex)
- .attr('y1', evt.pos.top - availableHeight - margin.top);
- container.select('.nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex)
- .attr('x2', evt.pos.left + distX.size() - margin.left);
- tooltip.position(evt.pos).data(evt).hidden(false);
- });
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
-
- });
-
- renderWatch.renderEnd('scatter with line immediate');
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.dispatch = dispatch;
- chart.scatter = scatter;
- chart.legend = legend;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.distX = distX;
- chart.distY = distY;
- chart.tooltip = tooltip;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- container: {get: function(){return container;}, set: function(_){container=_;}},
- showDistX: {get: function(){return showDistX;}, set: function(_){showDistX=_;}},
- showDistY: {get: function(){return showDistY;}, set: function(_){showDistY=_;}},
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
- showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
- showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
- duration: {get: function(){return duration;}, set: function(_){duration=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
- tooltipXContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'This option is removed, put values into main tooltip.');
- }},
- tooltipYContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'This option is removed, put values into main tooltip.');
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- legend.color(color);
- distX.color(color);
- distY.color(color);
- }}
- });
-
- nv.utils.inheritOptions(chart, scatter);
- nv.utils.initOptions(chart);
- return chart;
-};
-
-nv.models.sparkline = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 2, right: 0, bottom: 2, left: 0}
- , width = 400
- , height = 32
- , container = null
- , animate = true
- , x = d3.scale.linear()
- , y = d3.scale.linear()
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , color = nv.utils.getColor(['#000'])
- , xDomain
- , yDomain
- , xRange
- , yRange
- ;
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom;
-
- container = d3.select(this);
- nv.utils.initSVG(container);
-
- // Setup Scales
- x .domain(xDomain || d3.extent(data, getX ))
- .range(xRange || [0, availableWidth]);
-
- y .domain(yDomain || d3.extent(data, getY ))
- .range(yRange || [availableHeight, 0]);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-sparkline').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparkline');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
-
- var paths = wrap.selectAll('path')
- .data(function(d) { return [d] });
- paths.enter().append('path');
- paths.exit().remove();
- paths
- .style('stroke', function(d,i) { return d.color || color(d, i) })
- .attr('d', d3.svg.line()
- .x(function(d,i) { return x(getX(d,i)) })
- .y(function(d,i) { return y(getY(d,i)) })
- );
-
- // TODO: Add CURRENT data point (Need Min, Mac, Current / Most recent)
- var points = wrap.selectAll('circle.nv-point')
- .data(function(data) {
- var yValues = data.map(function(d, i) { return getY(d,i); });
- function pointIndex(index) {
- if (index != -1) {
- var result = data[index];
- result.pointIndex = index;
- return result;
- } else {
- return null;
- }
- }
- var maxPoint = pointIndex(yValues.lastIndexOf(y.domain()[1])),
- minPoint = pointIndex(yValues.indexOf(y.domain()[0])),
- currentPoint = pointIndex(yValues.length - 1);
- return [minPoint, maxPoint, currentPoint].filter(function (d) {return d != null;});
- });
- points.enter().append('circle');
- points.exit().remove();
- points
- .attr('cx', function(d,i) { return x(getX(d,d.pointIndex)) })
- .attr('cy', function(d,i) { return y(getY(d,d.pointIndex)) })
- .attr('r', 2)
- .attr('class', function(d,i) {
- return getX(d, d.pointIndex) == x.domain()[1] ? 'nv-point nv-currentValue' :
- getY(d, d.pointIndex) == y.domain()[0] ? 'nv-point nv-minValue' : 'nv-point nv-maxValue'
- });
- });
-
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
- yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
- xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},
- yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},
- xScale: {get: function(){return x;}, set: function(_){x=_;}},
- yScale: {get: function(){return y;}, set: function(_){y=_;}},
- animate: {get: function(){return animate;}, set: function(_){animate=_;}},
-
- //functor options
- x: {get: function(){return getX;}, set: function(_){getX=d3.functor(_);}},
- y: {get: function(){return getY;}, set: function(_){getY=d3.functor(_);}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }}
- });
-
- nv.utils.initOptions(chart);
- return chart;
-};
-
-nv.models.sparklinePlus = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var sparkline = nv.models.sparkline();
-
- var margin = {top: 15, right: 100, bottom: 10, left: 50}
- , width = null
- , height = null
- , x
- , y
- , index = []
- , paused = false
- , xTickFormat = d3.format(',r')
- , yTickFormat = d3.format(',.2f')
- , showLastValue = true
- , alignValue = true
- , rightAlignValue = false
- , noData = null
- ;
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this);
- nv.utils.initSVG(container);
-
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- chart.update = function() { chart(selection) };
- chart.container = this;
-
- // Display No Data message if there's nothing to show.
- if (!data || !data.length) {
- nv.utils.noData(chart, container)
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- var currentValue = sparkline.y()(data[data.length-1], data.length-1);
-
- // Setup Scales
- x = sparkline.xScale();
- y = sparkline.yScale();
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-sparklineplus').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparklineplus');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-sparklineWrap');
- gEnter.append('g').attr('class', 'nv-valueWrap');
- gEnter.append('g').attr('class', 'nv-hoverArea');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- // Main Chart Component(s)
- var sparklineWrap = g.select('.nv-sparklineWrap');
-
- sparkline.width(availableWidth).height(availableHeight);
- sparklineWrap.call(sparkline);
-
- if (showLastValue) {
- var valueWrap = g.select('.nv-valueWrap');
- var value = valueWrap.selectAll('.nv-currentValue')
- .data([currentValue]);
-
- value.enter().append('text').attr('class', 'nv-currentValue')
- .attr('dx', rightAlignValue ? -8 : 8)
- .attr('dy', '.9em')
- .style('text-anchor', rightAlignValue ? 'end' : 'start');
-
- value
- .attr('x', availableWidth + (rightAlignValue ? margin.right : 0))
- .attr('y', alignValue ? function (d) {
- return y(d)
- } : 0)
- .style('fill', sparkline.color()(data[data.length - 1], data.length - 1))
- .text(yTickFormat(currentValue));
- }
-
- gEnter.select('.nv-hoverArea').append('rect')
- .on('mousemove', sparklineHover)
- .on('click', function() { paused = !paused })
- .on('mouseout', function() { index = []; updateValueLine(); });
-
- g.select('.nv-hoverArea rect')
- .attr('transform', function(d) { return 'translate(' + -margin.left + ',' + -margin.top + ')' })
- .attr('width', availableWidth + margin.left + margin.right)
- .attr('height', availableHeight + margin.top);
-
- //index is currently global (within the chart), may or may not keep it that way
- function updateValueLine() {
- if (paused) return;
-
- var hoverValue = g.selectAll('.nv-hoverValue').data(index);
-
- var hoverEnter = hoverValue.enter()
- .append('g').attr('class', 'nv-hoverValue')
- .style('stroke-opacity', 0)
- .style('fill-opacity', 0);
-
- hoverValue.exit()
- .transition().duration(250)
- .style('stroke-opacity', 0)
- .style('fill-opacity', 0)
- .remove();
-
- hoverValue
- .attr('transform', function(d) { return 'translate(' + x(sparkline.x()(data[d],d)) + ',0)' })
- .transition().duration(250)
- .style('stroke-opacity', 1)
- .style('fill-opacity', 1);
-
- if (!index.length) return;
-
- hoverEnter.append('line')
- .attr('x1', 0)
- .attr('y1', -margin.top)
- .attr('x2', 0)
- .attr('y2', availableHeight);
-
- hoverEnter.append('text').attr('class', 'nv-xValue')
- .attr('x', -6)
- .attr('y', -margin.top)
- .attr('text-anchor', 'end')
- .attr('dy', '.9em');
-
- g.select('.nv-hoverValue .nv-xValue')
- .text(xTickFormat(sparkline.x()(data[index[0]], index[0])));
-
- hoverEnter.append('text').attr('class', 'nv-yValue')
- .attr('x', 6)
- .attr('y', -margin.top)
- .attr('text-anchor', 'start')
- .attr('dy', '.9em');
-
- g.select('.nv-hoverValue .nv-yValue')
- .text(yTickFormat(sparkline.y()(data[index[0]], index[0])));
- }
-
- function sparklineHover() {
- if (paused) return;
-
- var pos = d3.mouse(this)[0] - margin.left;
-
- function getClosestIndex(data, x) {
- var distance = Math.abs(sparkline.x()(data[0], 0) - x);
- var closestIndex = 0;
- for (var i = 0; i < data.length; i++){
- if (Math.abs(sparkline.x()(data[i], i) - x) < distance) {
- distance = Math.abs(sparkline.x()(data[i], i) - x);
- closestIndex = i;
- }
- }
- return closestIndex;
- }
-
- index = [getClosestIndex(data, Math.round(x.invert(pos)))];
- updateValueLine();
- }
-
- });
-
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.sparkline = sparkline;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- xTickFormat: {get: function(){return xTickFormat;}, set: function(_){xTickFormat=_;}},
- yTickFormat: {get: function(){return yTickFormat;}, set: function(_){yTickFormat=_;}},
- showLastValue: {get: function(){return showLastValue;}, set: function(_){showLastValue=_;}},
- alignValue: {get: function(){return alignValue;}, set: function(_){alignValue=_;}},
- rightAlignValue: {get: function(){return rightAlignValue;}, set: function(_){rightAlignValue=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }}
- });
-
- nv.utils.inheritOptions(chart, sparkline);
- nv.utils.initOptions(chart);
-
- return chart;
-};
-
-nv.models.stackedArea = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 960
- , height = 500
- , color = nv.utils.defaultColor() // a function that computes the color
- , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't selet one
- , container = null
- , getX = function(d) { return d.x } // accessor to get the x value from a data point
- , getY = function(d) { return d.y } // accessor to get the y value from a data point
- , style = 'stack'
- , offset = 'zero'
- , order = 'default'
- , interpolate = 'linear' // controls the line interpolation
- , clipEdge = false // if true, masks lines within x and y scale
- , x //can be accessed via chart.xScale()
- , y //can be accessed via chart.yScale()
- , scatter = nv.models.scatter()
- , duration = 250
- , dispatch = d3.dispatch('areaClick', 'areaMouseover', 'areaMouseout','renderEnd', 'elementClick', 'elementMouseover', 'elementMouseout')
- ;
-
- scatter
- .pointSize(2.2) // default size
- .pointDomain([2.2, 2.2]) // all the same size by default
- ;
-
- /************************************
- * offset:
- * 'wiggle' (stream)
- * 'zero' (stacked)
- * 'expand' (normalize to 100%)
- * 'silhouette' (simple centered)
- *
- * order:
- * 'inside-out' (stream)
- * 'default' (input order)
- ************************************/
-
- var renderWatch = nv.utils.renderWatch(dispatch, duration);
-
- function chart(selection) {
- renderWatch.reset();
- renderWatch.models(scatter);
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom;
-
- container = d3.select(this);
- nv.utils.initSVG(container);
-
- // Setup Scales
- x = scatter.xScale();
- y = scatter.yScale();
-
- var dataRaw = data;
- // Injecting point index into each point because d3.layout.stack().out does not give index
- data.forEach(function(aseries, i) {
- aseries.seriesIndex = i;
- aseries.values = aseries.values.map(function(d, j) {
- d.index = j;
- d.seriesIndex = i;
- return d;
- });
- });
-
- var dataFiltered = data.filter(function(series) {
- return !series.disabled;
- });
-
- data = d3.layout.stack()
- .order(order)
- .offset(offset)
- .values(function(d) { return d.values }) //TODO: make values customizeable in EVERY model in this fashion
- .x(getX)
- .y(getY)
- .out(function(d, y0, y) {
- d.display = {
- y: y,
- y0: y0
- };
- })
- (dataFiltered);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-stackedarea').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedarea');
- var defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-areaWrap');
- gEnter.append('g').attr('class', 'nv-scatterWrap');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- // If the user has not specified forceY, make sure 0 is included in the domain
- // Otherwise, use user-specified values for forceY
- if (scatter.forceY().length == 0) {
- scatter.forceY().push(0);
- }
-
- scatter
- .width(availableWidth)
- .height(availableHeight)
- .x(getX)
- .y(function(d) { return d.display.y + d.display.y0 })
- .forceY([0])
- .color(data.map(function(d,i) {
- return d.color || color(d, d.seriesIndex);
- }));
-
- var scatterWrap = g.select('.nv-scatterWrap')
- .datum(data);
-
- scatterWrap.call(scatter);
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-edge-clip-' + id)
- .append('rect');
-
- wrap.select('#nv-edge-clip-' + id + ' rect')
- .attr('width', availableWidth)
- .attr('height', availableHeight);
-
- g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
-
- var area = d3.svg.area()
- .x(function(d,i) { return x(getX(d,i)) })
- .y0(function(d) {
- return y(d.display.y0)
- })
- .y1(function(d) {
- return y(d.display.y + d.display.y0)
- })
- .interpolate(interpolate);
-
- var zeroArea = d3.svg.area()
- .x(function(d,i) { return x(getX(d,i)) })
- .y0(function(d) { return y(d.display.y0) })
- .y1(function(d) { return y(d.display.y0) });
-
- var path = g.select('.nv-areaWrap').selectAll('path.nv-area')
- .data(function(d) { return d });
-
- path.enter().append('path').attr('class', function(d,i) { return 'nv-area nv-area-' + i })
- .attr('d', function(d,i){
- return zeroArea(d.values, d.seriesIndex);
- })
- .on('mouseover', function(d,i) {
- d3.select(this).classed('hover', true);
- dispatch.areaMouseover({
- point: d,
- series: d.key,
- pos: [d3.event.pageX, d3.event.pageY],
- seriesIndex: d.seriesIndex
- });
- })
- .on('mouseout', function(d,i) {
- d3.select(this).classed('hover', false);
- dispatch.areaMouseout({
- point: d,
- series: d.key,
- pos: [d3.event.pageX, d3.event.pageY],
- seriesIndex: d.seriesIndex
- });
- })
- .on('click', function(d,i) {
- d3.select(this).classed('hover', false);
- dispatch.areaClick({
- point: d,
- series: d.key,
- pos: [d3.event.pageX, d3.event.pageY],
- seriesIndex: d.seriesIndex
- });
- });
-
- path.exit().remove();
- path.style('fill', function(d,i){
- return d.color || color(d, d.seriesIndex)
- })
- .style('stroke', function(d,i){ return d.color || color(d, d.seriesIndex) });
- path.watchTransition(renderWatch,'stackedArea path')
- .attr('d', function(d,i) {
- return area(d.values,i)
- });
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- scatter.dispatch.on('elementMouseover.area', function(e) {
- g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', true);
- });
- scatter.dispatch.on('elementMouseout.area', function(e) {
- g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', false);
- });
-
- //Special offset functions
- chart.d3_stackedOffset_stackPercent = function(stackData) {
- var n = stackData.length, //How many series
- m = stackData[0].length, //how many points per series
- i,
- j,
- o,
- y0 = [];
-
- for (j = 0; j < m; ++j) { //Looping through all points
- for (i = 0, o = 0; i < dataRaw.length; i++) { //looping through all series
- o += getY(dataRaw[i].values[j]); //total y value of all series at a certian point in time.
- }
-
- if (o) for (i = 0; i < n; i++) { //(total y value of all series at point in time i) != 0
- stackData[i][j][1] /= o;
- } else { //(total y value of all series at point in time i) == 0
- for (i = 0; i < n; i++) {
- stackData[i][j][1] = 0;
- }
- }
- }
- for (j = 0; j < m; ++j) y0[j] = 0;
- return y0;
- };
-
- });
-
- renderWatch.renderEnd('stackedArea immediate');
- return chart;
- }
-
- //============================================================
- // Global getters and setters
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.scatter = scatter;
-
- scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); });
- scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); });
- scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); });
-
- chart.interpolate = function(_) {
- if (!arguments.length) return interpolate;
- interpolate = _;
- return chart;
- };
-
- chart.duration = function(_) {
- if (!arguments.length) return duration;
- duration = _;
- renderWatch.reset(duration);
- scatter.duration(duration);
- return chart;
- };
-
- chart.dispatch = dispatch;
- chart.scatter = scatter;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
- offset: {get: function(){return offset;}, set: function(_){offset=_;}},
- order: {get: function(){return order;}, set: function(_){order=_;}},
- interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}},
-
- // simple functor options
- x: {get: function(){return getX;}, set: function(_){getX = d3.functor(_);}},
- y: {get: function(){return getY;}, set: function(_){getY = d3.functor(_);}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- }},
- style: {get: function(){return style;}, set: function(_){
- style = _;
- switch (style) {
- case 'stack':
- chart.offset('zero');
- chart.order('default');
- break;
- case 'stream':
- chart.offset('wiggle');
- chart.order('inside-out');
- break;
- case 'stream-center':
- chart.offset('silhouette');
- chart.order('inside-out');
- break;
- case 'expand':
- chart.offset('expand');
- chart.order('default');
- break;
- case 'stack_percent':
- chart.offset(chart.d3_stackedOffset_stackPercent);
- chart.order('default');
- break;
- }
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- scatter.duration(duration);
- }}
- });
-
- nv.utils.inheritOptions(chart, scatter);
- nv.utils.initOptions(chart);
-
- return chart;
-};
-
-nv.models.stackedAreaChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var stacked = nv.models.stackedArea()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- , controls = nv.models.legend()
- , interactiveLayer = nv.interactiveGuideline()
- , tooltip = nv.models.tooltip()
- ;
-
- var margin = {top: 30, right: 25, bottom: 50, left: 60}
- , width = null
- , height = null
- , color = nv.utils.defaultColor()
- , showControls = true
- , showLegend = true
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = false
- , useInteractiveGuideline = false
- , x //can be accessed via chart.xScale()
- , y //can be accessed via chart.yScale()
- , state = nv.utils.state()
- , defaultState = null
- , noData = null
- , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd')
- , controlWidth = 250
- , controlOptions = ['Stacked','Stream','Expanded']
- , controlLabels = {}
- , duration = 250
- ;
-
- state.style = stacked.style();
- xAxis.orient('bottom').tickPadding(7);
- yAxis.orient((rightAlignYAxis) ? 'right' : 'left');
-
- tooltip
- .headerFormatter(function(d, i) {
- return xAxis.tickFormat()(d, i);
- })
- .valueFormatter(function(d, i) {
- return yAxis.tickFormat()(d, i);
- });
-
- interactiveLayer.tooltip
- .headerFormatter(function(d, i) {
- return xAxis.tickFormat()(d, i);
- })
- .valueFormatter(function(d, i) {
- return yAxis.tickFormat()(d, i);
- });
-
- var oldYTickFormat = null,
- oldValueFormatter = null;
-
- controls.updateState(false);
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var renderWatch = nv.utils.renderWatch(dispatch);
- var style = stacked.style();
-
- var stateGetter = function(data) {
- return function(){
- return {
- active: data.map(function(d) { return !d.disabled }),
- style: stacked.style()
- };
- }
- };
-
- var stateSetter = function(data) {
- return function(state) {
- if (state.style !== undefined)
- style = state.style;
- if (state.active !== undefined)
- data.forEach(function(series,i) {
- series.disabled = !state.active[i];
- });
- }
- };
-
- var percentFormatter = d3.format('%');
-
- function chart(selection) {
- renderWatch.reset();
- renderWatch.models(stacked);
- if (showXAxis) renderWatch.models(xAxis);
- if (showYAxis) renderWatch.models(yAxis);
-
- selection.each(function(data) {
- var container = d3.select(this),
- that = this;
- nv.utils.initSVG(container);
-
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- chart.update = function() { container.transition().duration(duration).call(chart); };
- chart.container = this;
-
- state
- .setter(stateSetter(data), chart.update)
- .getter(stateGetter(data))
- .update();
-
- // DEPRECATED set state.disabled
- state.disabled = data.map(function(d) { return !!d.disabled });
-
- if (!defaultState) {
- var key;
- defaultState = {};
- for (key in state) {
- if (state[key] instanceof Array)
- defaultState[key] = state[key].slice(0);
- else
- defaultState[key] = state[key];
- }
- }
-
- // Display No Data message if there's nothing to show.
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
- nv.utils.noData(chart, container)
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- // Setup Scales
- x = stacked.xScale();
- y = stacked.yScale();
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-stackedAreaChart').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedAreaChart').append('g');
- var g = wrap.select('g');
-
- gEnter.append("rect").style("opacity",0);
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis');
- gEnter.append('g').attr('class', 'nv-stackedWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
- gEnter.append('g').attr('class', 'nv-controlsWrap');
- gEnter.append('g').attr('class', 'nv-interactive');
-
- g.select("rect").attr("width",availableWidth).attr("height",availableHeight);
-
- // Legend
- if (showLegend) {
- var legendWidth = (showControls) ? availableWidth - controlWidth : availableWidth;
-
- legend.width(legendWidth);
- g.select('.nv-legendWrap').datum(data).call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- availableHeight = nv.utils.availableHeight(height, container, margin);
- }
-
- g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + (availableWidth-legendWidth) + ',' + (-margin.top) +')');
- }
-
- // Controls
- if (showControls) {
- var controlsData = [
- {
- key: controlLabels.stacked || 'Stacked',
- metaKey: 'Stacked',
- disabled: stacked.style() != 'stack',
- style: 'stack'
- },
- {
- key: controlLabels.stream || 'Stream',
- metaKey: 'Stream',
- disabled: stacked.style() != 'stream',
- style: 'stream'
- },
- {
- key: controlLabels.expanded || 'Expanded',
- metaKey: 'Expanded',
- disabled: stacked.style() != 'expand',
- style: 'expand'
- },
- {
- key: controlLabels.stack_percent || 'Stack %',
- metaKey: 'Stack_Percent',
- disabled: stacked.style() != 'stack_percent',
- style: 'stack_percent'
- }
- ];
-
- controlWidth = (controlOptions.length/3) * 260;
- controlsData = controlsData.filter(function(d) {
- return controlOptions.indexOf(d.metaKey) !== -1;
- });
-
- controls
- .width( controlWidth )
- .color(['#444', '#444', '#444']);
-
- g.select('.nv-controlsWrap')
- .datum(controlsData)
- .call(controls);
-
- if ( margin.top != Math.max(controls.height(), legend.height()) ) {
- margin.top = Math.max(controls.height(), legend.height());
- availableHeight = nv.utils.availableHeight(height, container, margin);
- }
-
- g.select('.nv-controlsWrap')
- .attr('transform', 'translate(0,' + (-margin.top) +')');
- }
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- //Set up interactive layer
- if (useInteractiveGuideline) {
- interactiveLayer
- .width(availableWidth)
- .height(availableHeight)
- .margin({left: margin.left, top: margin.top})
- .svgContainer(container)
- .xScale(x);
- wrap.select(".nv-interactive").call(interactiveLayer);
- }
-
- stacked
- .width(availableWidth)
- .height(availableHeight);
-
- var stackedWrap = g.select('.nv-stackedWrap')
- .datum(data);
-
- stackedWrap.transition().call(stacked);
-
- // Setup Axes
- if (showXAxis) {
- xAxis.scale(x)
- ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize( -availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + availableHeight + ')');
-
- g.select('.nv-x.nv-axis')
- .transition().duration(0)
- .call(xAxis);
- }
-
- if (showYAxis) {
- var ticks;
- if (stacked.offset() === 'wiggle') {
- ticks = 0;
- }
- else {
- ticks = nv.utils.calcTicksY(availableHeight/36, data);
- }
- yAxis.scale(y)
- ._ticks(ticks)
- .tickSize(-availableWidth, 0);
-
- if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') {
- var currentFormat = yAxis.tickFormat();
-
- if ( !oldYTickFormat || currentFormat !== percentFormatter )
- oldYTickFormat = currentFormat;
-
- //Forces the yAxis to use percentage in 'expand' mode.
- yAxis.tickFormat(percentFormatter);
- }
- else {
- if (oldYTickFormat) {
- yAxis.tickFormat(oldYTickFormat);
- oldYTickFormat = null;
- }
- }
-
- g.select('.nv-y.nv-axis')
- .transition().duration(0)
- .call(yAxis);
- }
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- stacked.dispatch.on('areaClick.toggle', function(e) {
- if (data.filter(function(d) { return !d.disabled }).length === 1)
- data.forEach(function(d) {
- d.disabled = false;
- });
- else
- data.forEach(function(d,i) {
- d.disabled = (i != e.seriesIndex);
- });
-
- state.disabled = data.map(function(d) { return !!d.disabled });
- dispatch.stateChange(state);
-
- chart.update();
- });
-
- legend.dispatch.on('stateChange', function(newState) {
- for (var key in newState)
- state[key] = newState[key];
- dispatch.stateChange(state);
- chart.update();
- });
-
- controls.dispatch.on('legendClick', function(d,i) {
- if (!d.disabled) return;
-
- controlsData = controlsData.map(function(s) {
- s.disabled = true;
- return s;
- });
- d.disabled = false;
-
- stacked.style(d.style);
-
-
- state.style = stacked.style();
- dispatch.stateChange(state);
-
- chart.update();
- });
-
- interactiveLayer.dispatch.on('elementMousemove', function(e) {
- stacked.clearHighlights();
- var singlePoint, pointIndex, pointXLocation, allData = [];
- data
- .filter(function(series, i) {
- series.seriesIndex = i;
- return !series.disabled;
- })
- .forEach(function(series,i) {
- pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
- var point = series.values[pointIndex];
- var pointYValue = chart.y()(point, pointIndex);
- if (pointYValue != null) {
- stacked.highlightPoint(i, pointIndex, true);
- }
- if (typeof point === 'undefined') return;
- if (typeof singlePoint === 'undefined') singlePoint = point;
- if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
-
- //If we are in 'expand' mode, use the stacked percent value instead of raw value.
- var tooltipValue = (stacked.style() == 'expand') ? point.display.y : chart.y()(point,pointIndex);
- allData.push({
- key: series.key,
- value: tooltipValue,
- color: color(series,series.seriesIndex),
- stackedValue: point.display
- });
- });
-
- allData.reverse();
-
- //Highlight the tooltip entry based on which stack the mouse is closest to.
- if (allData.length > 2) {
- var yValue = chart.yScale().invert(e.mouseY);
- var yDistMax = Infinity, indexToHighlight = null;
- allData.forEach(function(series,i) {
-
- //To handle situation where the stacked area chart is negative, we need to use absolute values
- //when checking if the mouse Y value is within the stack area.
- yValue = Math.abs(yValue);
- var stackedY0 = Math.abs(series.stackedValue.y0);
- var stackedY = Math.abs(series.stackedValue.y);
- if ( yValue >= stackedY0 && yValue <= (stackedY + stackedY0))
- {
- indexToHighlight = i;
- return;
- }
- });
- if (indexToHighlight != null)
- allData[indexToHighlight].highlight = true;
- }
-
- var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));
-
- var valueFormatter = interactiveLayer.tooltip.valueFormatter();
- // Keeps track of the tooltip valueFormatter if the chart changes to expanded view
- if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') {
- if ( !oldValueFormatter ) {
- oldValueFormatter = valueFormatter;
- }
- //Forces the tooltip to use percentage in 'expand' mode.
- valueFormatter = d3.format(".1%");
- }
- else {
- if (oldValueFormatter) {
- valueFormatter = oldValueFormatter;
- oldValueFormatter = null;
- }
- }
-
- interactiveLayer.tooltip
- .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top})
- .chartContainer(that.parentNode)
- .valueFormatter(valueFormatter)
- .data(
- {
- value: xValue,
- series: allData
- }
- )();
-
- interactiveLayer.renderGuideLine(pointXLocation);
-
- });
-
- interactiveLayer.dispatch.on("elementMouseout",function(e) {
- stacked.clearHighlights();
- });
-
- // Update chart from a state object passed to event handler
- dispatch.on('changeState', function(e) {
-
- if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) {
- data.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
-
- state.disabled = e.disabled;
- }
-
- if (typeof e.style !== 'undefined') {
- stacked.style(e.style);
- style = e.style;
- }
-
- chart.update();
- });
-
- });
-
- renderWatch.renderEnd('stacked Area chart immediate');
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- stacked.dispatch.on('elementMouseover.tooltip', function(evt) {
- evt.point['x'] = stacked.x()(evt.point);
- evt.point['y'] = stacked.y()(evt.point);
- tooltip.data(evt).position(evt.pos).hidden(false);
- });
-
- stacked.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true)
- });
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.dispatch = dispatch;
- chart.stacked = stacked;
- chart.legend = legend;
- chart.controls = controls;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.interactiveLayer = interactiveLayer;
- chart.tooltip = tooltip;
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
- showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
- showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
- showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},
- controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}},
- controlOptions: {get: function(){return controlOptions;}, set: function(_){controlOptions=_;}},
-
- // deprecated options
- tooltips: {get: function(){return tooltip.enabled();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
- tooltip.enabled(!!_);
- }},
- tooltipContent: {get: function(){return tooltip.contentGenerator();}, set: function(_){
- // deprecated after 1.7.1
- nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
- tooltip.contentGenerator(_);
- }},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- stacked.duration(duration);
- xAxis.duration(duration);
- yAxis.duration(duration);
- }},
- color: {get: function(){return color;}, set: function(_){
- color = nv.utils.getColor(_);
- legend.color(color);
- stacked.color(color);
- }},
- rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
- rightAlignYAxis = _;
- yAxis.orient( rightAlignYAxis ? 'right' : 'left');
- }},
- useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){
- useInteractiveGuideline = !!_;
- chart.interactive(!_);
- chart.useVoronoi(!_);
- stacked.scatter.interactive(!_);
- }}
- });
-
- nv.utils.inheritOptions(chart, stacked);
- nv.utils.initOptions(chart);
-
- return chart;
-};
-// based on http://bl.ocks.org/kerryrodden/477c1bfb081b783f80ad
-nv.models.sunburst = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = null
- , height = null
- , mode = "count"
- , modes = {count: function(d) { return 1; }, size: function(d) { return d.size }}
- , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
- , container = null
- , color = nv.utils.defaultColor()
- , duration = 500
- , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMousemove', 'elementMouseover', 'elementMouseout', 'renderEnd')
- ;
-
- var x = d3.scale.linear().range([0, 2 * Math.PI]);
- var y = d3.scale.sqrt();
-
- var partition = d3.layout.partition()
- .sort(null)
- .value(function(d) { return 1; });
-
- var arc = d3.svg.arc()
- .startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); })
- .endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); })
- .innerRadius(function(d) { return Math.max(0, y(d.y)); })
- .outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); });
-
- // Keep track of the current and previous node being displayed as the root.
- var node, prevNode;
- // Keep track of the root node
- var rootNode;
-
- //============================================================
- // chart function
- //------------------------------------------------------------
-
- var renderWatch = nv.utils.renderWatch(dispatch);
-
- function chart(selection) {
- renderWatch.reset();
- selection.each(function(data) {
- container = d3.select(this);
- var availableWidth = nv.utils.availableWidth(width, container, margin);
- var availableHeight = nv.utils.availableHeight(height, container, margin);
- var radius = Math.min(availableWidth, availableHeight) / 2;
- var path;
-
- nv.utils.initSVG(container);
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('.nv-wrap.nv-sunburst').data(data);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sunburst nv-chart-' + id);
-
- var g = wrapEnter.selectAll('nv-sunburst');
-
- wrap.attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');
-
- container.on('click', function (d, i) {
- dispatch.chartClick({
- data: d,
- index: i,
- pos: d3.event,
- id: id
- });
- });
-
- y.range([0, radius]);
-
- node = node || data;
- rootNode = data[0];
- partition.value(modes[mode] || modes["count"]);
- path = g.data(partition.nodes).enter()
- .append("path")
- .attr("d", arc)
- .style("fill", function (d) {
- return color((d.children ? d : d.parent).name);
- })
- .style("stroke", "#FFF")
- .on("click", function(d) {
- if (prevNode !== node && node !== d) prevNode = node;
- node = d;
- path.transition()
- .duration(duration)
- .attrTween("d", arcTweenZoom(d));
- })
- .each(stash)
- .on("dblclick", function(d) {
- if (prevNode.parent == d) {
- path.transition()
- .duration(duration)
- .attrTween("d", arcTweenZoom(rootNode));
- }
- })
- .each(stash)
- .on('mouseover', function(d,i){
- d3.select(this).classed('hover', true).style('opacity', 0.8);
- dispatch.elementMouseover({
- data: d,
- color: d3.select(this).style("fill")
- });
- })
- .on('mouseout', function(d,i){
- d3.select(this).classed('hover', false).style('opacity', 1);
- dispatch.elementMouseout({
- data: d
- });
- })
- .on('mousemove', function(d,i){
- dispatch.elementMousemove({
- data: d
- });
- });
-
-
-
- // Setup for switching data: stash the old values for transition.
- function stash(d) {
- d.x0 = d.x;
- d.dx0 = d.dx;
- }
-
- // When switching data: interpolate the arcs in data space.
- function arcTweenData(a, i) {
- var oi = d3.interpolate({x: a.x0, dx: a.dx0}, a);
-
- function tween(t) {
- var b = oi(t);
- a.x0 = b.x;
- a.dx0 = b.dx;
- return arc(b);
- }
-
- if (i == 0) {
- // If we are on the first arc, adjust the x domain to match the root node
- // at the current zoom level. (We only need to do this once.)
- var xd = d3.interpolate(x.domain(), [node.x, node.x + node.dx]);
- return function (t) {
- x.domain(xd(t));
- return tween(t);
- };
- } else {
- return tween;
- }
- }
-
- // When zooming: interpolate the scales.
- function arcTweenZoom(d) {
- var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
- yd = d3.interpolate(y.domain(), [d.y, 1]),
- yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
- return function (d, i) {
- return i
- ? function (t) {
- return arc(d);
- }
- : function (t) {
- x.domain(xd(t));
- y.domain(yd(t)).range(yr(t));
- return arc(d);
- };
- };
- }
-
- });
-
- renderWatch.renderEnd('sunburst immediate');
- return chart;
- }
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- mode: {get: function(){return mode;}, set: function(_){mode=_;}},
- id: {get: function(){return id;}, set: function(_){id=_;}},
- duration: {get: function(){return duration;}, set: function(_){duration=_;}},
-
- // options that require extra logic in the setter
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top != undefined ? _.top : margin.top;
- margin.right = _.right != undefined ? _.right : margin.right;
- margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom;
- margin.left = _.left != undefined ? _.left : margin.left;
- }},
- color: {get: function(){return color;}, set: function(_){
- color=nv.utils.getColor(_);
- }}
- });
-
- nv.utils.initOptions(chart);
- return chart;
-};
-nv.models.sunburstChart = function() {
- "use strict";
-
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var sunburst = nv.models.sunburst();
- var tooltip = nv.models.tooltip();
-
- var margin = {top: 30, right: 20, bottom: 20, left: 20}
- , width = null
- , height = null
- , color = nv.utils.defaultColor()
- , id = Math.round(Math.random() * 100000)
- , defaultState = null
- , noData = null
- , duration = 250
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd')
- ;
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var renderWatch = nv.utils.renderWatch(dispatch);
- tooltip.headerEnabled(false).duration(0).valueFormatter(function(d, i) {
- return d;
- });
-
- //============================================================
- // Chart function
- //------------------------------------------------------------
-
- function chart(selection) {
- renderWatch.reset();
- renderWatch.models(sunburst);
-
- selection.each(function(data) {
- var container = d3.select(this);
- nv.utils.initSVG(container);
-
- var that = this;
- var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
-
- chart.update = function() {
- if (duration === 0)
- container.call(chart);
- else
- container.transition().duration(duration).call(chart)
- };
- chart.container = this;
-
- // Display No Data message if there's nothing to show.
- if (!data || !data.length) {
- nv.utils.noData(chart, container);
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- // Setup containers and skeleton of chart
- var wrap = container.selectAll('g.nv-wrap.nv-sunburstChart').data(data);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sunburstChart').append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-sunburstWrap');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- // Main Chart Component(s)
- sunburst.width(availableWidth).height(availableHeight);
- var sunWrap = g.select('.nv-sunburstWrap').datum(data);
- d3.transition(sunWrap).call(sunburst);
-
- });
-
- renderWatch.renderEnd('sunburstChart immediate');
- return chart;
- }
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- sunburst.dispatch.on('elementMouseover.tooltip', function(evt) {
- evt['series'] = {
- key: evt.data.name,
- value: evt.data.size,
- color: evt.color
- };
- tooltip.data(evt).hidden(false);
- });
-
- sunburst.dispatch.on('elementMouseout.tooltip', function(evt) {
- tooltip.hidden(true);
- });
-
- sunburst.dispatch.on('elementMousemove.tooltip', function(evt) {
- tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
- });
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.dispatch = dispatch;
- chart.sunburst = sunburst;
- chart.tooltip = tooltip;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- // use Object get/set functionality to map between vars and chart functions
- chart._options = Object.create({}, {
- // simple options, just get/set the necessary values
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
-
- // options that require extra logic in the setter
- color: {get: function(){return color;}, set: function(_){
- color = _;
- sunburst.color(color);
- }},
- duration: {get: function(){return duration;}, set: function(_){
- duration = _;
- renderWatch.reset(duration);
- sunburst.duration(duration);
- }},
- margin: {get: function(){return margin;}, set: function(_){
- margin.top = _.top !== undefined ? _.top : margin.top;
- margin.right = _.right !== undefined ? _.right : margin.right;
- margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
- margin.left = _.left !== undefined ? _.left : margin.left;
- }}
- });
- nv.utils.inheritOptions(chart, sunburst);
- nv.utils.initOptions(chart);
- return chart;
-};
-
-nv.version = "1.8.1";
-})(); \ No newline at end of file
diff --git a/wqflask/wqflask/static/new/packages/nvd3/nv.d3.min.css b/wqflask/wqflask/static/new/packages/nvd3/nv.d3.min.css
deleted file mode 100644
index 7a6f7fe9..00000000
--- a/wqflask/wqflask/static/new/packages/nvd3/nv.d3.min.css
+++ /dev/null
@@ -1 +0,0 @@
-.nvd3 .nv-axis{pointer-events:none;opacity:1}.nvd3 .nv-axis path{fill:none;stroke:#000;stroke-opacity:.75;shape-rendering:crispEdges}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{fill:none;stroke:#e5e5e5;shape-rendering:crispEdges}.nvd3 .nv-axis .zero line,.nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nvd3 .nv-axis.nv-disabled{opacity:0}.nvd3 .nv-bars rect{fill-opacity:.75;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:rgba(0,0,0,0)}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect,.nvd3 .nv-discretebar .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover,.nvd3 .nv-candlestickBar .nv-ticks rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:rgba(0,0,0,0)}.nvd3 .nv-boxplot circle{fill-opacity:.5}.nvd3 .nv-boxplot circle:hover{fill-opacity:1}.nvd3 .nv-boxplot rect:hover{fill-opacity:1}.nvd3 line.nv-boxplot-median{stroke:#000}.nv-boxplot-tick:hover{stroke-width:2.5px}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet .nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-candlestickBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect{stroke:#d62728;fill:#d62728}.with-transitions .nv-candlestickBar .nv-ticks .nv-tick{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-candlestickBar .nv-ticks line{stroke:#333}.nvd3 .nv-legend .nv-disabled rect{}.nvd3 .nv-check-box .nv-box{fill-opacity:0;stroke-width:2}.nvd3 .nv-check-box .nv-check{fill-opacity:0;stroke-width:4}.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check{opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3 .nv-groups path.nv-line{fill:none}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-scatter .nv-groups .nv-point.hover,.nvd3 .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}svg.nvd3-svg{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-ms-user-select:none;-moz-user-select:none;user-select:none;display:block;width:100%;height:100%}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nvd3 text{font:400 12px Arial}.nvd3 .title{font:700 14px Arial}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125;shape-rendering:crispEdges}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .nv-disabled circle{fill-opacity:0}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3 .background path{fill:none;stroke:#EEE;stroke-opacity:.4;shape-rendering:crispEdges}.nvd3 .foreground path{fill:none;stroke-opacity:.7}.nvd3 .nv-parallelCoordinates-brush .extent{fill:#fff;fill-opacity:.6;stroke:gray;shape-rendering:crispEdges}.nvd3 .nv-parallelCoordinates .hover{fill-opacity:1;stroke-width:3px}.nvd3 .missingValuesline line{fill:none;stroke:#000;stroke-width:1;stroke-opacity:1;stroke-dasharray:5,5}.nvd3.nv-pie path{stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-pie .nv-pie-title{font-size:24px;fill:rgba(19,196,249,.59)}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{stroke:#fff;stroke-width:1px;stroke-opacity:1}.nvd3.nv-pie .hover path{fill-opacity:.7}.nvd3.nv-pie .nv-label{pointer-events:none}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nv-noninteractive{pointer-events:none}.nv-distx,.nv-disty{pointer-events:none}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-hoverArea{fill-opacity:0;stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvtooltip{position:absolute;background-color:rgba(255,255,255,1);color:rgba(0,0,0,1);padding:1px;border:1px solid rgba(0,0,0,.2);z-index:10000;display:block;font-family:Arial;font-size:13px;text-align:left;pointer-events:none;white-space:nowrap;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.nvtooltip{background:rgba(255,255,255,.8);border:1px solid rgba(0,0,0,.5);border-radius:4px}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 50ms linear;-moz-transition:opacity 50ms linear;-webkit-transition:opacity 50ms linear;transition-delay:200ms;-moz-transition-delay:200ms;-webkit-transition-delay:200ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{margin:0;padding:4px 14px;line-height:18px;font-weight:400;background-color:rgba(247,247,247,.75);color:rgba(0,0,0,1);text-align:center;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.nvtooltip p{margin:0;padding:5px 14px;text-align:center}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key{font-weight:400}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{width:8px;height:8px;vertical-align:middle}.nvtooltip table td.legend-color-guide div{width:12px;height:12px;border:1px solid #999}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{pointer-events:none;display:none}.nvd3 .nv-interactiveGuideLine{pointer-events:none}.nvd3 line.nv-guideline{stroke:#ccc} \ No newline at end of file
diff --git a/wqflask/wqflask/static/new/packages/nvd3/nv.d3.min.js b/wqflask/wqflask/static/new/packages/nvd3/nv.d3.min.js
deleted file mode 100644
index ab17e9fe..00000000
--- a/wqflask/wqflask/static/new/packages/nvd3/nv.d3.min.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* nvd3 version 1.8.1 (https://github.com/novus/nvd3) 2015-05-25 */
-!function(){var a={};a.dev=!1,a.tooltip=a.tooltip||{},a.utils=a.utils||{},a.models=a.models||{},a.charts={},a.logs={},a.dom={},a.dispatch=d3.dispatch("render_start","render_end"),Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d&&a?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),a.dev&&(a.dispatch.on("render_start",function(b){a.logs.startTime=+new Date}),a.dispatch.on("render_end",function(b){a.logs.endTime=+new Date,a.logs.totalTime=a.logs.endTime-a.logs.startTime,a.log("total",a.logs.totalTime)})),a.log=function(){if(a.dev&&window.console&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(a.dev&&window.console&&"function"==typeof console.log&&Function.prototype.bind){var b=Function.prototype.bind.call(console.log,console);b.apply(console,arguments)}return arguments[arguments.length-1]},a.deprecated=function(a,b){console&&console.warn&&console.warn("nvd3 warning: `"+a+"` has been deprecated. ",b||"")},a.render=function(b){b=b||1,a.render.active=!0,a.dispatch.render_start();var c=function(){for(var d,e,f=0;b>f&&(e=a.render.queue[f]);f++)d=e.generate(),typeof e.callback==typeof Function&&e.callback(d);a.render.queue.splice(0,f),a.render.queue.length?setTimeout(c):(a.dispatch.render_end(),a.render.active=!1)};setTimeout(c)},a.render.active=!1,a.render.queue=[],a.addGraph=function(b){typeof arguments[0]==typeof Function&&(b={generate:arguments[0],callback:arguments[1]}),a.render.queue.push(b),a.render.active||a.render()},"undefined"!=typeof module&&"undefined"!=typeof exports&&(module.exports=a),"undefined"!=typeof window&&(window.nv=a),a.dom.write=function(a){return void 0!==window.fastdom?fastdom.write(a):a()},a.dom.read=function(a){return void 0!==window.fastdom?fastdom.read(a):a()},a.interactiveGuideline=function(){"use strict";function b(l){l.each(function(l){function m(){var a=d3.mouse(this),d=a[0],e=a[1],i=!0,j=!1;if(k&&(d=d3.event.offsetX,e=d3.event.offsetY,"svg"!==d3.event.target.tagName&&(i=!1),d3.event.target.className.baseVal.match("nv-legend")&&(j=!0)),i&&(d-=f.left,e-=f.top),0>d||0>e||d>o||e>p||d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement||j){if(k&&d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement&&(void 0===d3.event.relatedTarget.className||d3.event.relatedTarget.className.match(c.nvPointerEventsClass)))return;return h.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void c.hidden(!0)}c.hidden(!1);var l=g.invert(d);h.elementMousemove({mouseX:d,mouseY:e,pointXValue:l}),"dblclick"===d3.event.type&&h.elementDblclick({mouseX:d,mouseY:e,pointXValue:l}),"click"===d3.event.type&&h.elementClick({mouseX:d,mouseY:e,pointXValue:l})}var n=d3.select(this),o=d||960,p=e||400,q=n.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([l]),r=q.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");r.append("g").attr("class","nv-interactiveGuideLine"),j&&(j.on("touchmove",m).on("mousemove",m,!0).on("mouseout",m,!0).on("dblclick",m).on("click",m),b.guideLine=null,b.renderGuideLine=function(c){i&&(b.guideLine&&b.guideLine.attr("x1")===c||a.dom.write(function(){var b=q.select(".nv-interactiveGuideLine").selectAll("line").data(null!=c?[a.utils.NaNtoZero(c)]:[],String);b.enter().append("line").attr("class","nv-guideline").attr("x1",function(a){return a}).attr("x2",function(a){return a}).attr("y1",p).attr("y2",0),b.exit().remove()}))})})}var c=a.models.tooltip();c.duration(0).hideDelay(0)._isInteractiveLayer(!0).hidden(!1);var d=null,e=null,f={left:0,top:0},g=d3.scale.linear(),h=d3.dispatch("elementMousemove","elementMouseout","elementClick","elementDblclick"),i=!0,j=null,k="ActiveXObject"in window;return b.dispatch=h,b.tooltip=c,b.margin=function(a){return arguments.length?(f.top="undefined"!=typeof a.top?a.top:f.top,f.left="undefined"!=typeof a.left?a.left:f.left,b):f},b.width=function(a){return arguments.length?(d=a,b):d},b.height=function(a){return arguments.length?(e=a,b):e},b.xScale=function(a){return arguments.length?(g=a,b):g},b.showGuideLine=function(a){return arguments.length?(i=a,b):i},b.svgContainer=function(a){return arguments.length?(j=a,b):j},b},a.interactiveBisect=function(a,b,c){"use strict";if(!(a instanceof Array))return null;var d;d="function"!=typeof c?function(a){return a.x}:c;var e=function(a,b){return d(a)-b},f=d3.bisector(e).left,g=d3.max([0,f(a,b)-1]),h=d(a[g]);if("undefined"==typeof h&&(h=g),h===b)return g;var i=d3.min([g+1,a.length-1]),j=d(a[i]);return"undefined"==typeof j&&(j=i),Math.abs(j-b)>=Math.abs(h-b)?g:i},a.nearestValueIndex=function(a,b,c){"use strict";var d=1/0,e=null;return a.forEach(function(a,f){var g=Math.abs(b-a);null!=a&&d>=g&&c>g&&(d=g,e=f)}),e},function(){"use strict";a.models.tooltip=function(){function b(){if(k){var a=d3.select(k);"svg"!==a.node().tagName&&(a=a.select("svg"));var b=a.node()?a.attr("viewBox"):null;if(b){b=b.split(" ");var c=parseInt(a.style("width"),10)/b[2];p.left=p.left*c,p.top=p.top*c}}}function c(){if(!n){var a;a=k?k:document.body,n=d3.select(a).append("div").attr("class","nvtooltip "+(j?j:"xy-tooltip")).attr("id",v),n.style("top",0).style("left",0),n.style("opacity",0),n.selectAll("div, table, td, tr").classed(w,!0),n.classed(w,!0),o=n.node()}}function d(){if(r&&B(e)){b();var f=p.left,g=null!==i?i:p.top;return a.dom.write(function(){c();var b=A(e);b&&(o.innerHTML=b),k&&u?a.dom.read(function(){var a=k.getElementsByTagName("svg")[0],b={left:0,top:0};if(a){var c=a.getBoundingClientRect(),d=k.getBoundingClientRect(),e=c.top;if(0>e){var i=k.getBoundingClientRect();e=Math.abs(e)>i.height?0:e}b.top=Math.abs(e-d.top),b.left=Math.abs(c.left-d.left)}f+=k.offsetLeft+b.left-2*k.scrollLeft,g+=k.offsetTop+b.top-2*k.scrollTop,h&&h>0&&(g=Math.floor(g/h)*h),C([f,g])}):C([f,g])}),d}}var e=null,f="w",g=25,h=0,i=null,j=null,k=null,l=!0,m=400,n=null,o=null,p={left:null,top:null},q={left:0,top:0},r=!0,s=100,t=!0,u=!1,v="nvtooltip-"+Math.floor(1e5*Math.random()),w="nv-pointer-events-none",x=function(a,b){return a},y=function(a){return a},z=function(a,b){return a},A=function(a){if(null===a)return"";var b=d3.select(document.createElement("table"));if(t){var c=b.selectAll("thead").data([a]).enter().append("thead");c.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(y(a.value))}var d=b.selectAll("tbody").data([a]).enter().append("tbody"),e=d.selectAll("tr").data(function(a){return a.series}).enter().append("tr").classed("highlight",function(a){return a.highlight});e.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(a){return a.color}),e.append("td").classed("key",!0).html(function(a,b){return z(a.key,b)}),e.append("td").classed("value",!0).html(function(a,b){return x(a.value,b)}),e.selectAll("td").each(function(a){if(a.highlight){var b=d3.scale.linear().domain([0,1]).range(["#fff",a.color]),c=.6;d3.select(this).style("border-bottom-color",b(c)).style("border-top-color",b(c))}});var f=b.node().outerHTML;return void 0!==a.footer&&(f+="<div class='footer'>"+a.footer+"</div>"),f},B=function(a){if(a&&a.series){if(a.series instanceof Array)return!!a.series.length;if(a.series instanceof Object)return a.series=[a.series],!0}return!1},C=function(b){o&&a.dom.read(function(){var c,d,e=parseInt(o.offsetHeight,10),h=parseInt(o.offsetWidth,10),i=a.utils.windowSize().width,j=a.utils.windowSize().height,k=window.pageYOffset,p=window.pageXOffset;j=window.innerWidth>=document.body.scrollWidth?j:j-16,i=window.innerHeight>=document.body.scrollHeight?i:i-16;var r,t,u=function(a){var b=d;do isNaN(a.offsetTop)||(b+=a.offsetTop),a=a.offsetParent;while(a);return b},v=function(a){var b=c;do isNaN(a.offsetLeft)||(b+=a.offsetLeft),a=a.offsetParent;while(a);return b};switch(f){case"e":c=b[0]-h-g,d=b[1]-e/2,r=v(o),t=u(o),p>r&&(c=b[0]+g>p?b[0]+g:p-r+c),k>t&&(d=k-t+d),t+e>k+j&&(d=k+j-t+d-e);break;case"w":c=b[0]+g,d=b[1]-e/2,r=v(o),t=u(o),r+h>i&&(c=b[0]-h-g),k>t&&(d=k+5),t+e>k+j&&(d=k+j-t+d-e);break;case"n":c=b[0]-h/2-5,d=b[1]+g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),t+e>k+j&&(d=k+j-t+d-e);break;case"s":c=b[0]-h/2,d=b[1]-e-g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),k>t&&(d=k);break;case"none":c=b[0],d=b[1]-g,r=v(o),t=u(o)}c-=q.left,d-=q.top;var w=o.getBoundingClientRect(),k=window.pageYOffset||document.documentElement.scrollTop,p=window.pageXOffset||document.documentElement.scrollLeft,x="translate("+(w.left+p)+"px, "+(w.top+k)+"px)",y="translate("+c+"px, "+d+"px)",z=d3.interpolateString(x,y),A=n.style("opacity")<.1;l?n.transition().delay(m).duration(0).style("opacity",0):n.interrupt().transition().duration(A?0:s).styleTween("transform",function(a){return z},"important").style("-webkit-transform",y).style("opacity",1)})};return d.nvPointerEventsClass=w,d.options=a.utils.optionsFunc.bind(d),d._options=Object.create({},{duration:{get:function(){return s},set:function(a){s=a}},gravity:{get:function(){return f},set:function(a){f=a}},distance:{get:function(){return g},set:function(a){g=a}},snapDistance:{get:function(){return h},set:function(a){h=a}},classes:{get:function(){return j},set:function(a){j=a}},chartContainer:{get:function(){return k},set:function(a){k=a}},fixedTop:{get:function(){return i},set:function(a){i=a}},enabled:{get:function(){return r},set:function(a){r=a}},hideDelay:{get:function(){return m},set:function(a){m=a}},contentGenerator:{get:function(){return A},set:function(a){A=a}},valueFormatter:{get:function(){return x},set:function(a){x=a}},headerFormatter:{get:function(){return y},set:function(a){y=a}},keyFormatter:{get:function(){return z},set:function(a){z=a}},headerEnabled:{get:function(){return t},set:function(a){t=a}},_isInteractiveLayer:{get:function(){return u},set:function(a){u=!!a}},position:{get:function(){return p},set:function(a){p.left=void 0!==a.left?a.left:p.left,p.top=void 0!==a.top?a.top:p.top}},offset:{get:function(){return q},set:function(a){q.left=void 0!==a.left?a.left:q.left,q.top=void 0!==a.top?a.top:q.top}},hidden:{get:function(){return l},set:function(a){l!=a&&(l=!!a,d())}},data:{get:function(){return e},set:function(a){a.point&&(a.value=a.point.x,a.series=a.series||{},a.series.value=a.point.y,a.series.color=a.point.color||a.series.color),e=a}},tooltipElem:{get:function(){return o},set:function(a){}},id:{get:function(){return v},set:function(a){}}}),a.utils.initOptions(d),d}}(),a.utils.windowSize=function(){var a={width:640,height:480};return window.innerWidth&&window.innerHeight?(a.width=window.innerWidth,a.height=window.innerHeight,a):"CSS1Compat"==document.compatMode&&document.documentElement&&document.documentElement.offsetWidth?(a.width=document.documentElement.offsetWidth,a.height=document.documentElement.offsetHeight,a):document.body&&document.body.offsetWidth?(a.width=document.body.offsetWidth,a.height=document.body.offsetHeight,a):a},a.utils.windowResize=function(b){return window.addEventListener?window.addEventListener("resize",b):a.log("ERROR: Failed to bind to window.resize with: ",b),{callback:b,clear:function(){window.removeEventListener("resize",b)}}},a.utils.getColor=function(b){if(void 0===b)return a.utils.defaultColor();if(Array.isArray(b)){var c=d3.scale.ordinal().range(b);return function(a,b){var d=void 0===b?a:b;return a.color||c(d)}}return b},a.utils.defaultColor=function(){return a.utils.getColor(d3.scale.category20().range())},a.utils.customTheme=function(a,b,c){b=b||function(a){return a.key},c=c||d3.scale.category20().range();var d=c.length;return function(e,f){var g=b(e);return"function"==typeof a[g]?a[g]():void 0!==a[g]?a[g]:(d||(d=c.length),d-=1,c[d])}},a.utils.pjax=function(b,c){var d=function(d){d3.html(d,function(d){var e=d3.select(c).node();e.parentNode.replaceChild(d3.select(d).select(c).node(),e),a.utils.pjax(b,c)})};d3.selectAll(b).on("click",function(){history.pushState(this.href,this.textContent,this.href),d(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&d(d3.event.state)})},a.utils.calcApproxTextWidth=function(a){if("function"==typeof a.style&&"function"==typeof a.text){var b=parseInt(a.style("font-size").replace("px",""),10),c=a.text().length;return c*b*.5}return 0},a.utils.NaNtoZero=function(a){return"number"!=typeof a||isNaN(a)||null===a||a===1/0||a===-(1/0)?0:a},d3.selection.prototype.watchTransition=function(a){var b=[this].concat([].slice.call(arguments,1));return a.transition.apply(a,b)},a.utils.renderWatch=function(b,c){if(!(this instanceof a.utils.renderWatch))return new a.utils.renderWatch(b,c);var d=void 0!==c?c:250,e=[],f=this;this.models=function(a){return a=[].slice.call(arguments,0),a.forEach(function(a){a.__rendered=!1,function(a){a.dispatch.on("renderEnd",function(b){a.__rendered=!0,f.renderEnd("model")})}(a),e.indexOf(a)<0&&e.push(a)}),this},this.reset=function(a){void 0!==a&&(d=a),e=[]},this.transition=function(a,b,c){if(b=arguments.length>1?[].slice.call(arguments,1):[],c=b.length>1?b.pop():void 0!==d?d:250,a.__rendered=!1,e.indexOf(a)<0&&e.push(a),0===c)return a.__rendered=!0,a.delay=function(){return this},a.duration=function(){return this},a;0===a.length?a.__rendered=!0:a.every(function(a){return!a.length})?a.__rendered=!0:a.__rendered=!1;var g=0;return a.transition().duration(c).each(function(){++g}).each("end",function(c,d){0===--g&&(a.__rendered=!0,f.renderEnd.apply(this,b))})},this.renderEnd=function(){e.every(function(a){return a.__rendered})&&(e.forEach(function(a){a.__rendered=!1}),b.renderEnd.apply(this,arguments))}},a.utils.deepExtend=function(b){var c=arguments.length>1?[].slice.call(arguments,1):[];c.forEach(function(c){for(var d in c){var e=b[d]instanceof Array,f="object"==typeof b[d],g="object"==typeof c[d];f&&!e&&g?a.utils.deepExtend(b[d],c[d]):b[d]=c[d]}})},a.utils.state=function(){if(!(this instanceof a.utils.state))return new a.utils.state;var b={},c=function(){},d=function(){return{}},e=null,f=null;this.dispatch=d3.dispatch("change","set"),this.dispatch.on("set",function(a){c(a,!0)}),this.getter=function(a){return d=a,this},this.setter=function(a,b){return b||(b=function(){}),c=function(c,d){a(c),d&&b()},this},this.init=function(b){e=e||{},a.utils.deepExtend(e,b)};var g=function(){var a=d();if(JSON.stringify(a)===JSON.stringify(b))return!1;for(var c in a)void 0===b[c]&&(b[c]={}),b[c]=a[c],f=!0;return!0};this.update=function(){e&&(c(e,!1),e=null),g.call(this)&&this.dispatch.change(b)}},a.utils.optionsFunc=function(a){return a&&d3.map(a).forEach(function(a,b){"function"==typeof this[a]&&this[a](b)}.bind(this)),this},a.utils.calcTicksX=function(b,c){var d=1,e=0;for(e;e<c.length;e+=1){var f=c[e]&&c[e].values?c[e].values.length:0;d=f>d?f:d}return a.log("Requested number of ticks: ",b),a.log("Calculated max values to be: ",d),b=b>d?b=d-1:b,b=1>b?1:b,b=Math.floor(b),a.log("Calculating tick count as: ",b),b},a.utils.calcTicksY=function(b,c){return a.utils.calcTicksX(b,c)},a.utils.initOption=function(a,b){a._calls&&a._calls[b]?a[b]=a._calls[b]:(a[b]=function(c){return arguments.length?(a._overrides[b]=!0,a._options[b]=c,a):a._options[b]},a["_"+b]=function(c){return arguments.length?(a._overrides[b]||(a._options[b]=c),a):a._options[b]})},a.utils.initOptions=function(b){b._overrides=b._overrides||{};var c=Object.getOwnPropertyNames(b._options||{}),d=Object.getOwnPropertyNames(b._calls||{});c=c.concat(d);for(var e in c)a.utils.initOption(b,c[e])},a.utils.inheritOptionsD3=function(a,b,c){a._d3options=c.concat(a._d3options||[]),c.unshift(b),c.unshift(a),d3.rebind.apply(this,c)},a.utils.arrayUnique=function(a){return a.sort().filter(function(b,c){return!c||b!=a[c-1]})},a.utils.symbolMap=d3.map(),a.utils.symbol=function(){function b(b,e){var f=c.call(this,b,e),g=d.call(this,b,e);return-1!==d3.svg.symbolTypes.indexOf(f)?d3.svg.symbol().type(f).size(g)():a.utils.symbolMap.get(f)(g)}var c,d=64;return b.type=function(a){return arguments.length?(c=d3.functor(a),b):c},b.size=function(a){return arguments.length?(d=d3.functor(a),b):d},b},a.utils.inheritOptions=function(b,c){var d=Object.getOwnPropertyNames(c._options||{}),e=Object.getOwnPropertyNames(c._calls||{}),f=c._inherited||[],g=c._d3options||[],h=d.concat(e).concat(f).concat(g);h.unshift(c),h.unshift(b),d3.rebind.apply(this,h),b._inherited=a.utils.arrayUnique(d.concat(e).concat(f).concat(d).concat(b._inherited||[])),b._d3options=a.utils.arrayUnique(g.concat(b._d3options||[]))},a.utils.initSVG=function(a){a.classed({"nvd3-svg":!0})},a.utils.sanitizeHeight=function(a,b){return a||parseInt(b.style("height"),10)||400},a.utils.sanitizeWidth=function(a,b){return a||parseInt(b.style("width"),10)||960},a.utils.availableHeight=function(b,c,d){return a.utils.sanitizeHeight(b,c)-d.top-d.bottom},a.utils.availableWidth=function(b,c,d){return a.utils.sanitizeWidth(b,c)-d.left-d.right},a.utils.noData=function(b,c){var d=b.options(),e=d.margin(),f=d.noData(),g=null==f?["No Data Available."]:[f],h=a.utils.availableHeight(d.height(),c,e),i=a.utils.availableWidth(d.width(),c,e),j=e.left+i/2,k=e.top+h/2;c.selectAll("g").remove();var l=c.selectAll(".nv-noData").data(g);l.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),l.attr("x",j).attr("y",k).text(function(a){return a})},a.models.axis=function(){"use strict";function b(g){return s.reset(),g.each(function(b){var g=d3.select(this);a.utils.initSVG(g);var p=g.selectAll("g.nv-wrap.nv-axis").data([b]),q=p.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),t=(q.append("g"),p.select("g"));null!==n?c.ticks(n):("top"==c.orient()||"bottom"==c.orient())&&c.ticks(Math.abs(d.range()[1]-d.range()[0])/100),t.watchTransition(s,"axis").call(c),r=r||c.scale();var u=c.tickFormat();null==u&&(u=r.tickFormat());var v=t.selectAll("text.nv-axislabel").data([h||null]);v.exit().remove();var w,x,y;switch(c.orient()){case"top":v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",0).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d(b))+",0)"}).select("text").attr("dy","-0.5em").attr("y",-c.tickPadding()).attr("text-anchor","middle").text(function(a,b){var c=u(a);return(""+c).match("NaN")?"":c}),x.watchTransition(s,"min-max top").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d.range()[c])+",0)"}));break;case"bottom":w=o+36;var z=30,A=0,B=t.selectAll("g").select("text"),C="";if(j%360){B.each(function(a,b){var c=this.getBoundingClientRect(),d=c.width;A=c.height,d>z&&(z=d)}),C="rotate("+j+" 0,"+(A/2+c.tickPadding())+")";var D=Math.abs(Math.sin(j*Math.PI/180));w=(D?D*z:z)+30,B.attr("transform",C).style("text-anchor",j%360>0?"start":"end")}v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",w).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data([d.domain()[0],d.domain()[d.domain().length-1]]),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",c.tickPadding()).attr("transform",C).style("text-anchor",j?j%360>0?"start":"end":"middle").text(function(a,b){var c=u(a);return(""+c).match("NaN")?"":c}),x.watchTransition(s,"min-max bottom").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"})),l&&B.attr("transform",function(a,b){return"translate(0,"+(b%2==0?"0":"12")+")"});break;case"right":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"begin").attr("transform",k?"rotate(90)":"").attr("y",k?-Math.max(e.right,f)+12:-10).attr("x",k?d3.max(d.range())/2:c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",c.tickPadding()).style("text-anchor","start").text(function(a,b){var c=u(a);return(""+c).match("NaN")?"":c}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1));break;case"left":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"end").attr("transform",k?"rotate(-90)":"").attr("y",k?-Math.max(e.left,f)+25-(o||0):-10).attr("x",k?-d3.max(d.range())/2:-c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(r(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-c.tickPadding()).attr("text-anchor","end").text(function(a,b){var c=u(a);return(""+c).match("NaN")?"":c}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1))}if(v.text(function(a){return a}),!i||"left"!==c.orient()&&"right"!==c.orient()||(t.selectAll("g").each(function(a,b){d3.select(this).select("text").attr("opacity",1),(d(a)<d.range()[1]+10||d(a)>d.range()[0]-10)&&((a>1e-10||-1e-10>a)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0))}),d.domain()[0]==d.domain()[1]&&0==d.domain()[0]&&p.selectAll("g.nv-axisMaxMin").style("opacity",function(a,b){return b?0:1})),i&&("top"===c.orient()||"bottom"===c.orient())){var E=[];p.selectAll("g.nv-axisMaxMin").each(function(a,b){try{b?E.push(d(a)-this.getBoundingClientRect().width-4):E.push(d(a)+this.getBoundingClientRect().width+4)}catch(c){b?E.push(d(a)-4):E.push(d(a)+4)}}),t.selectAll("g").each(function(a,b){(d(a)<E[0]||d(a)>E[1])&&(a>1e-10||-1e-10>a?d3.select(this).remove():d3.select(this).select("text").remove())})}t.selectAll(".tick").filter(function(a){return!parseFloat(Math.round(1e5*a)/1e6)&&void 0!==a}).classed("zero",!0),r=d.copy()}),s.renderEnd("axis immediate"),b}var c=d3.svg.axis(),d=d3.scale.linear(),e={top:0,right:0,bottom:0,left:0},f=75,g=60,h=null,i=!0,j=0,k=!0,l=!1,m=!1,n=null,o=0,p=250,q=d3.dispatch("renderEnd");c.scale(d).orient("bottom").tickFormat(function(a){return a});var r,s=a.utils.renderWatch(q,p);return b.axis=c,b.dispatch=q,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{axisLabelDistance:{get:function(){return o},set:function(a){o=a}},staggerLabels:{get:function(){return l},set:function(a){l=a}},rotateLabels:{get:function(){return j},set:function(a){j=a}},rotateYLabel:{get:function(){return k},set:function(a){k=a}},showMaxMin:{get:function(){return i},set:function(a){i=a}},axisLabel:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return g},set:function(a){g=a}},ticks:{get:function(){return n},set:function(a){n=a}},width:{get:function(){return f},set:function(a){f=a}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},duration:{get:function(){return p},set:function(a){p=a,s.reset(p)}},scale:{get:function(){return d},set:function(e){d=e,c.scale(d),m="function"==typeof d.rangeBands,a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"])}}}),a.utils.initOptions(b),a.utils.inheritOptionsD3(b,c,["orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"]),a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"]),b},a.models.boxPlot=function(){"use strict";function b(l){return v.reset(),l.each(function(b){var l=j-i.left-i.right,p=k-i.top-i.bottom;r=d3.select(this),a.utils.initSVG(r),m.domain(c||b.map(function(a,b){return o(a,b)})).rangeBands(e||[0,l],.1);var w=[];if(!d){var x=d3.min(b.map(function(a){var b=[];return b.push(a.values.Q1),a.values.hasOwnProperty("whisker_low")&&null!==a.values.whisker_low&&b.push(a.values.whisker_low),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.min(b)})),y=d3.max(b.map(function(a){var b=[];return b.push(a.values.Q3),a.values.hasOwnProperty("whisker_high")&&null!==a.values.whisker_high&&b.push(a.values.whisker_high),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.max(b)}));w=[x,y]}n.domain(d||w),n.range(f||[p,0]),g=g||m,h=h||n.copy().range([n(0),n(0)]);var z=r.selectAll("g.nv-wrap").data([b]);z.enter().append("g").attr("class","nvd3 nv-wrap");z.attr("transform","translate("+i.left+","+i.top+")");var A=z.selectAll(".nv-boxplot").data(function(a){return a}),B=A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);A.attr("class","nv-boxplot").attr("transform",function(a,b,c){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}).classed("hover",function(a){return a.hover}),A.watchTransition(v,"nv-boxplot: boxplots").style("stroke-opacity",1).style("fill-opacity",.75).delay(function(a,c){return c*t/b.length}).attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}),A.exit().remove(),B.each(function(a,b){var c=d3.select(this);["low","high"].forEach(function(d){a.values.hasOwnProperty("whisker_"+d)&&null!==a.values["whisker_"+d]&&(c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-whisker nv-boxplot-"+d),c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-tick nv-boxplot-"+d))})});var C=A.selectAll(".nv-boxplot-outlier").data(function(a){return a.values.hasOwnProperty("outliers")&&null!==a.values.outliers?a.values.outliers:[]});C.enter().append("circle").style("fill",function(a,b,c){return q(a,c)}).style("stroke",function(a,b,c){return q(a,c)}).on("mouseover",function(a,b,c){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:a,color:q(a,c)},e:d3.event})}).on("mouseout",function(a,b,c){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:a,color:q(a,c)},e:d3.event})}).on("mousemove",function(a,b){s.elementMousemove({e:d3.event})}),C.attr("class","nv-boxplot-outlier"),C.watchTransition(v,"nv-boxplot: nv-boxplot-outlier").attr("cx",.45*m.rangeBand()).attr("cy",function(a,b,c){return n(a)}).attr("r","3"),C.exit().remove();var D=function(){return null===u?.9*m.rangeBand():Math.min(75,.9*m.rangeBand())},E=function(){return.45*m.rangeBand()-D()/2},F=function(){return.45*m.rangeBand()+D()/2};["low","high"].forEach(function(a){var b="low"===a?"Q1":"Q3";A.select("line.nv-boxplot-whisker.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",.45*m.rangeBand()).attr("y1",function(b,c){return n(b.values["whisker_"+a])}).attr("x2",.45*m.rangeBand()).attr("y2",function(a,c){return n(a.values[b])}),A.select("line.nv-boxplot-tick.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",E).attr("y1",function(b,c){return n(b.values["whisker_"+a])}).attr("x2",F).attr("y2",function(b,c){return n(b.values["whisker_"+a])})}),["low","high"].forEach(function(a){B.selectAll(".nv-boxplot-"+a).on("mouseover",function(b,c,d){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mouseout",function(b,c,d){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mousemove",function(a,b){s.elementMousemove({e:d3.event})})}),B.append("rect").attr("class","nv-boxplot-box").on("mouseover",function(a,b){d3.select(this).classed("hover",!0),s.elementMouseover({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),s.elementMouseout({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mousemove",function(a,b){s.elementMousemove({e:d3.event})}),A.select("rect.nv-boxplot-box").watchTransition(v,"nv-boxplot: boxes").attr("y",function(a,b){return n(a.values.Q3)}).attr("width",D).attr("x",E).attr("height",function(a,b){return Math.abs(n(a.values.Q3)-n(a.values.Q1))||1}).style("fill",function(a,b){return a.color||q(a,b)}).style("stroke",function(a,b){return a.color||q(a,b)}),B.append("line").attr("class","nv-boxplot-median"),A.select("line.nv-boxplot-median").watchTransition(v,"nv-boxplot: boxplots line").attr("x1",E).attr("y1",function(a,b){return n(a.values.Q2)}).attr("x2",F).attr("y2",function(a,b){return n(a.values.Q2)}),g=m.copy(),h=n.copy()}),v.renderEnd("nv-boxplot immediate"),b}var c,d,e,f,g,h,i={top:0,right:0,bottom:0,left:0},j=960,k=500,l=Math.floor(1e4*Math.random()),m=d3.scale.ordinal(),n=d3.scale.linear(),o=function(a){return a.x},p=function(a){return a.y},q=a.utils.defaultColor(),r=null,s=d3.dispatch("elementMouseover","elementMouseout","elementMousemove","renderEnd"),t=250,u=null,v=a.utils.renderWatch(s,t);return b.dispatch=s,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},maxBoxWidth:{get:function(){return u},set:function(a){u=a}},x:{get:function(){return o},set:function(a){o=a}},y:{get:function(){return p},set:function(a){p=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return l},set:function(a){l=a}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}},duration:{get:function(){return t},set:function(a){t=a,v.reset(t)}}}),a.utils.initOptions(b),b},a.models.boxPlotChart=function(){"use strict";function b(k){return t.reset(),t.models(e),l&&t.models(f),m&&t.models(g),k.each(function(k){var p=d3.select(this);a.utils.initSVG(p);var t=(i||parseInt(p.style("width"))||960)-h.left-h.right,u=(j||parseInt(p.style("height"))||400)-h.top-h.bottom;if(b.update=function(){r.beforeUpdate(),p.transition().duration(s).call(b)},b.container=this,!(k&&k.length&&k.filter(function(a){return a.values.hasOwnProperty("Q1")&&a.values.hasOwnProperty("Q2")&&a.values.hasOwnProperty("Q3")}).length)){var v=p.selectAll(".nv-noData").data([q]);return v.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),v.attr("x",h.left+t/2).attr("y",h.top+u/2).text(function(a){return a}),b}p.selectAll(".nv-noData").remove(),
-c=e.xScale(),d=e.yScale().clamp(!0);var w=p.selectAll("g.nv-wrap.nv-boxPlotWithAxes").data([k]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-boxPlotWithAxes").append("g"),y=x.append("defs"),z=w.select("g");x.append("g").attr("class","nv-x nv-axis"),x.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),x.append("g").attr("class","nv-barsWrap"),z.attr("transform","translate("+h.left+","+h.top+")"),n&&z.select(".nv-y.nv-axis").attr("transform","translate("+t+",0)"),e.width(t).height(u);var A=z.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));if(A.transition().call(e),y.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),z.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(o?2:1)).attr("height",16).attr("x",-c.rangeBand()/(o?1:2)),l){f.scale(c).ticks(a.utils.calcTicksX(t/100,k)).tickSize(-u,0),z.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),z.select(".nv-x.nv-axis").call(f);var B=z.select(".nv-x.nv-axis").selectAll("g");o&&B.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}m&&(g.scale(d).ticks(Math.floor(u/36)).tickSize(-t,0),z.select(".nv-y.nv-axis").call(g)),z.select(".nv-zeroLine line").attr("x1",0).attr("x2",t).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("nv-boxplot chart immediate"),b}var c,d,e=a.models.boxPlot(),f=a.models.axis(),g=a.models.axis(),h={top:15,right:10,bottom:50,left:60},i=null,j=null,k=a.utils.getColor(),l=!0,m=!0,n=!1,o=!1,p=a.models.tooltip(),q="No Data Available.",r=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(n?"right":"left").tickFormat(d3.format(",.1f")),p.duration(0);var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){p.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){p.data(a).hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(a){p.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.boxplot=e,b.xAxis=f,b.yAxis=g,b.tooltip=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},staggerLabels:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return l},set:function(a){l=a}},showYAxis:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return tooltips},set:function(a){tooltips=a}},tooltipContent:{get:function(){return p},set:function(a){p=a}},noData:{get:function(){return q},set:function(a){q=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!==a.top?a.top:h.top,h.right=void 0!==a.right?a.right:h.right,h.bottom=void 0!==a.bottom?a.bottom:h.bottom,h.left=void 0!==a.left?a.left:h.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}},rightAlignYAxis:{get:function(){return n},set:function(a){n=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.bullet=function(){"use strict";function b(d){return d.each(function(b,d){var p=m-c.left-c.right,s=n-c.top-c.bottom;o=d3.select(this),a.utils.initSVG(o);var t=f.call(this,b,d).slice().sort(d3.descending),u=g.call(this,b,d).slice().sort(d3.descending),v=h.call(this,b,d).slice().sort(d3.descending),w=i.call(this,b,d).slice(),x=j.call(this,b,d).slice(),y=k.call(this,b,d).slice(),z=d3.scale.linear().domain(d3.extent(d3.merge([l,t]))).range(e?[p,0]:[0,p]);this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range());this.__chart__=z;var A=d3.min(t),B=d3.max(t),C=t[1],D=o.selectAll("g.nv-wrap.nv-bullet").data([b]),E=D.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),F=E.append("g"),G=D.select("g");F.append("rect").attr("class","nv-range nv-rangeMax"),F.append("rect").attr("class","nv-range nv-rangeAvg"),F.append("rect").attr("class","nv-range nv-rangeMin"),F.append("rect").attr("class","nv-measure"),D.attr("transform","translate("+c.left+","+c.top+")");var H=function(a){return Math.abs(z(a)-z(0))},I=function(a){return z(0>a?a:0)};G.select("rect.nv-rangeMax").attr("height",s).attr("width",H(B>0?B:A)).attr("x",I(B>0?B:A)).datum(B>0?B:A),G.select("rect.nv-rangeAvg").attr("height",s).attr("width",H(C)).attr("x",I(C)).datum(C),G.select("rect.nv-rangeMin").attr("height",s).attr("width",H(B)).attr("x",I(B)).attr("width",H(B>0?A:B)).attr("x",I(B>0?A:B)).datum(B>0?A:B),G.select("rect.nv-measure").style("fill",q).attr("height",s/3).attr("y",s/3).attr("width",0>v?z(0)-z(v[0]):z(v[0])-z(0)).attr("x",I(v)).on("mouseover",function(){r.elementMouseover({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mouseout",function(){r.elementMouseout({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})});var J=s/6,K=u.map(function(a,b){return{value:a,label:x[b]}});F.selectAll("path.nv-markerTriangle").data(K).enter().append("path").attr("class","nv-markerTriangle").attr("transform",function(a){return"translate("+z(a.value)+","+s/2+")"}).attr("d","M0,"+J+"L"+J+","+-J+" "+-J+","+-J+"Z").on("mouseover",function(a){r.elementMouseover({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill"),pos:[z(a.value),s/2]})}).on("mousemove",function(a){r.elementMousemove({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){r.elementMouseout({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}),D.selectAll(".nv-range").on("mouseover",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseover({value:a,label:c,color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseout({value:a,label:c,color:d3.select(this).style("fill")})})}),b}var c={top:0,right:0,bottom:0,left:0},d="left",e=!1,f=function(a){return a.ranges},g=function(a){return a.markers?a.markers:[0]},h=function(a){return a.measures},i=function(a){return a.rangeLabels?a.rangeLabels:[]},j=function(a){return a.markerLabels?a.markerLabels:[]},k=function(a){return a.measureLabels?a.measureLabels:[]},l=[0],m=380,n=30,o=null,p=null,q=a.utils.getColor(["#1f77b4"]),r=d3.dispatch("elementMouseover","elementMouseout","elementMousemove");return b.dispatch=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return f},set:function(a){f=a}},markers:{get:function(){return g},set:function(a){g=a}},measures:{get:function(){return h},set:function(a){h=a}},forceX:{get:function(){return l},set:function(a){l=a}},width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},tickFormat:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},orient:{get:function(){return d},set:function(a){d=a,e="right"==d||"bottom"==d}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.bulletChart=function(){"use strict";function b(d){return d.each(function(e,o){var p=d3.select(this);a.utils.initSVG(p);var q=a.utils.availableWidth(k,p,g),r=l-g.top-g.bottom;if(b.update=function(){b(d)},b.container=this,!e||!h.call(this,e,o))return a.utils.noData(b,p),b;p.selectAll(".nv-noData").remove();var s=h.call(this,e,o).slice().sort(d3.descending),t=i.call(this,e,o).slice().sort(d3.descending),u=j.call(this,e,o).slice().sort(d3.descending),v=p.selectAll("g.nv-wrap.nv-bulletChart").data([e]),w=v.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),x=w.append("g"),y=v.select("g");x.append("g").attr("class","nv-bulletWrap"),x.append("g").attr("class","nv-titles"),v.attr("transform","translate("+g.left+","+g.top+")");var z=d3.scale.linear().domain([0,Math.max(s[0],t[0],u[0])]).range(f?[q,0]:[0,q]),A=this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range());this.__chart__=z;var B=x.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(l-g.top-g.bottom)/2+")");B.append("text").attr("class","nv-title").text(function(a){return a.title}),B.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(a){return a.subtitle}),c.width(q).height(r);var C=y.select(".nv-bulletWrap");d3.transition(C).call(c);var D=m||z.tickFormat(q/100),E=y.selectAll("g.nv-tick").data(z.ticks(n?n:q/50),function(a){return this.textContent||D(a)}),F=E.enter().append("g").attr("class","nv-tick").attr("transform",function(a){return"translate("+A(a)+",0)"}).style("opacity",1e-6);F.append("line").attr("y1",r).attr("y2",7*r/6),F.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",7*r/6).text(D);var G=d3.transition(E).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1);G.select("line").attr("y1",r).attr("y2",7*r/6),G.select("text").attr("y",7*r/6),d3.transition(E.exit()).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1e-6).remove()}),d3.timer.flush(),b}var c=a.models.bullet(),d=a.models.tooltip(),e="left",f=!1,g={top:5,right:40,bottom:20,left:120},h=function(a){return a.ranges},i=function(a){return a.markers?a.markers:[0]},j=function(a){return a.measures},k=null,l=55,m=null,n=null,o=null,p=d3.dispatch("tooltipShow","tooltipHide");return d.duration(0).headerEnabled(!1),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.label,value:a.value,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(a){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(a){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.bullet=c,b.dispatch=p,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return h},set:function(a){h=a}},markers:{get:function(){return i},set:function(a){i=a}},measures:{get:function(){return j},set:function(a){j=a}},width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},tickFormat:{get:function(){return m},set:function(a){m=a}},ticks:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return o},set:function(a){o=a}},tooltips:{get:function(){return d.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),d.enabled(!!b)}},tooltipContent:{get:function(){return d.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),d.contentGenerator(b)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},orient:{get:function(){return e},set:function(a){e=a,f="right"==e||"bottom"==e}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.candlestickBar=function(){"use strict";function b(x){return x.each(function(b){c=d3.select(this);var x=a.utils.availableWidth(i,c,h),y=a.utils.availableHeight(j,c,h);a.utils.initSVG(c);var A=x/b[0].values.length*.45;l.domain(d||d3.extent(b[0].values.map(n).concat(t))),v?l.range(f||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]):l.range(f||[5+A/2,x-A/2-5]),m.domain(e||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(g||[y,0]),l.domain()[0]===l.domain()[1]&&(l.domain()[0]?l.domain([l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]):l.domain([-1,1])),m.domain()[0]===m.domain()[1]&&(m.domain()[0]?m.domain([m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]):m.domain([-1,1]));var B=d3.select(this).selectAll("g.nv-wrap.nv-candlestickBar").data([b[0].values]),C=B.enter().append("g").attr("class","nvd3 nv-wrap nv-candlestickBar"),D=C.append("defs"),E=C.append("g"),F=B.select("g");E.append("g").attr("class","nv-ticks"),B.attr("transform","translate("+h.left+","+h.top+")"),c.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:k})}),D.append("clipPath").attr("id","nv-chart-clip-path-"+k).append("rect"),B.select("#nv-chart-clip-path-"+k+" rect").attr("width",x).attr("height",y),F.attr("clip-path",w?"url(#nv-chart-clip-path-"+k+")":"");var G=B.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});G.exit().remove();var H=G.enter().append("g").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b});H.append("line").attr("class","nv-candlestick-lines").attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),H.append("rect").attr("class","nv-candlestick-rects nv-bars").attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)});c.selectAll(".nv-candlestick-lines").transition().attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),c.selectAll(".nv-candlestick-rects").transition().attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}),b}var c,d,e,f,g,h={top:0,right:0,bottom:0,left:0},i=null,j=null,k=Math.floor(1e4*Math.random()),l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,d){b.clearHighlights(),c.select(".nv-candlestickBar .nv-tick-0-"+a).classed("hover",d)},b.clearHighlights=function(){c.select(".nv-candlestickBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return k},set:function(a){k=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!=a.top?a.top:h.top,h.right=void 0!=a.right?a.right:h.right,h.bottom=void 0!=a.bottom?a.bottom:h.bottom,h.left=void 0!=a.left?a.left:h.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.cumulativeLineChart=function(){"use strict";function b(l){return H.reset(),H.models(f),r&&H.models(g),s&&H.models(h),l.each(function(l){function A(a,c){d3.select(b.container).style("cursor","ew-resize")}function E(a,b){G.x=d3.event.x,G.i=Math.round(F.invert(G.x)),K()}function H(a,c){d3.select(b.container).style("cursor","auto"),y.index=G.i,C.stateChange(y)}function K(){ba.data([G]);var a=b.duration();b.duration(0),b.update(),b.duration(a)}var L=d3.select(this);a.utils.initSVG(L),L.classed("nv-chart-"+x,!0);var M=this,N=a.utils.availableWidth(o,L,m),O=a.utils.availableHeight(p,L,m);if(b.update=function(){0===D?L.call(b):L.transition().duration(D).call(b)},b.container=this,y.setter(J(l),b.update).getter(I(l)).update(),y.disabled=l.map(function(a){return!!a.disabled}),!z){var P;z={};for(P in y)y[P]instanceof Array?z[P]=y[P].slice(0):z[P]=y[P]}var Q=d3.behavior.drag().on("dragstart",A).on("drag",E).on("dragend",H);if(!(l&&l.length&&l.filter(function(a){return a.values.length}).length))return a.utils.noData(b,L),b;if(L.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale(),w)f.yDomain(null);else{var R=l.filter(function(a){return!a.disabled}).map(function(a,b){var c=d3.extent(a.values,f.y());return c[0]<-.95&&(c[0]=-.95),[(c[0]-c[1])/(1+c[1]),(c[1]-c[0])/(1+c[0])]}),S=[d3.min(R,function(a){return a[0]}),d3.max(R,function(a){return a[1]})];f.yDomain(S)}F.domain([0,l[0].values.length-1]).range([0,N]).clamp(!0);var l=c(G.i,l),T=v?"none":"all",U=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([l]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),W=U.select("g");if(V.append("g").attr("class","nv-interactive"),V.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),V.append("g").attr("class","nv-y nv-axis"),V.append("g").attr("class","nv-background"),V.append("g").attr("class","nv-linesWrap").style("pointer-events",T),V.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),V.append("g").attr("class","nv-legendWrap"),V.append("g").attr("class","nv-controlsWrap"),q&&(i.width(N),W.select(".nv-legendWrap").datum(l).call(i),m.top!=i.height()&&(m.top=i.height(),O=a.utils.availableHeight(p,L,m)),W.select(".nv-legendWrap").attr("transform","translate(0,"+-m.top+")")),u){var X=[{key:"Re-scale y-axis",disabled:!w}];j.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),W.select(".nv-controlsWrap").datum(X).attr("transform","translate(0,"+-m.top+")").call(j)}U.attr("transform","translate("+m.left+","+m.top+")"),t&&W.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)");var Y=l.filter(function(a){return a.tempDisabled});U.select(".tempDisabled").remove(),Y.length&&U.append("text").attr("class","tempDisabled").attr("x",N/2).attr("y","-.71em").style("text-anchor","end").text(Y.map(function(a){return a.key}).join(", ")+" values cannot be calculated for this time period."),v&&(k.width(N).height(O).margin({left:m.left,top:m.top}).svgContainer(L).xScale(d),U.select(".nv-interactive").call(k)),V.select(".nv-background").append("rect"),W.select(".nv-background rect").attr("width",N).attr("height",O),f.y(function(a){return a.display.y}).width(N).height(O).color(l.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!l[b].disabled&&!l[b].tempDisabled}));var Z=W.select(".nv-linesWrap").datum(l.filter(function(a){return!a.disabled&&!a.tempDisabled}));Z.call(f),l.forEach(function(a,b){a.seriesIndex=b});var $=l.filter(function(a){return!a.disabled&&!!B(a)}),_=W.select(".nv-avgLinesWrap").selectAll("line").data($,function(a){return a.key}),aa=function(a){var b=e(B(a));return 0>b?0:b>O?O:b};_.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(a,b){return f.color()(a,a.seriesIndex)}).attr("x1",0).attr("x2",N).attr("y1",aa).attr("y2",aa),_.style("stroke-opacity",function(a){var b=e(B(a));return 0>b||b>O?0:1}).attr("x1",0).attr("x2",N).attr("y1",aa).attr("y2",aa),_.exit().remove();var ba=Z.selectAll(".nv-indexLine").data([G]);ba.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(Q),ba.attr("transform",function(a){return"translate("+F(a.i)+",0)"}).attr("height",O),r&&(g.scale(d)._ticks(a.utils.calcTicksX(N/70,l)).tickSize(-O,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),W.select(".nv-x.nv-axis").call(g)),s&&(h.scale(e)._ticks(a.utils.calcTicksY(O/36,l)).tickSize(-N,0),W.select(".nv-y.nv-axis").call(h)),W.select(".nv-background rect").on("click",function(){G.x=d3.mouse(this)[0],G.i=Math.round(F.invert(G.x)),y.index=G.i,C.stateChange(y),K()}),f.dispatch.on("elementClick",function(a){G.i=a.pointIndex,G.x=F(G.i),y.index=G.i,C.stateChange(y),K()}),j.dispatch.on("legendClick",function(a,c){a.disabled=!a.disabled,w=!a.disabled,y.rescaleY=w,C.stateChange(y),b.update()}),i.dispatch.on("stateChange",function(a){for(var c in a)y[c]=a[c];C.stateChange(y),b.update()}),k.dispatch.on("elementMousemove",function(c){f.clearHighlights();var d,e,i,j=[];if(l.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,c.pointXValue,b.x()),f.highlightPoint(h,e,!0);var k=g.values[e];"undefined"!=typeof k&&("undefined"==typeof d&&(d=k),"undefined"==typeof i&&(i=b.xScale()(b.x()(k,e))),j.push({key:g.key,value:b.y()(k,e),color:n(g,g.seriesIndex)}))}),j.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(j.map(function(a){return a.value}),o,q);null!==r&&(j[r].highlight=!0)}var s=g.tickFormat()(b.x()(d,e),e);k.tooltip.position({left:i+m.left,top:c.mouseY+m.top}).chartContainer(M.parentNode).valueFormatter(function(a,b){return h.tickFormat()(a)}).data({value:s,series:j})(),k.renderGuideLine(i)}),k.dispatch.on("elementMouseout",function(a){f.clearHighlights()}),C.on("changeState",function(a){"undefined"!=typeof a.disabled&&(l.forEach(function(b,c){b.disabled=a.disabled[c]}),y.disabled=a.disabled),"undefined"!=typeof a.index&&(G.i=a.index,G.x=F(G.i),y.index=a.index,ba.data([G])),"undefined"!=typeof a.rescaleY&&(w=a.rescaleY),b.update()})}),H.renderEnd("cumulativeLineChart immediate"),b}function c(a,b){return K||(K=f.y()),b.map(function(b,c){if(!b.values)return b;var d=b.values[a];if(null==d)return b;var e=K(d,a);return-.95>e&&!E?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(K(a,b)-e)/(1+e)},a}),b)})}var d,e,f=a.models.line(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.models.legend(),k=a.interactiveGuideline(),l=a.models.tooltip(),m={top:30,right:30,bottom:50,left:60},n=a.utils.defaultColor(),o=null,p=null,q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=!0,x=f.id(),y=a.utils.state(),z=null,A=null,B=function(a){return a.average},C=d3.dispatch("stateChange","changeState","renderEnd"),D=250,E=!1;y.index=0,y.rescaleY=w,g.orient("bottom").tickPadding(7),h.orient(t?"right":"left"),l.valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)}),j.updateState(!1);var F=d3.scale.linear(),G={i:0,x:0},H=a.utils.renderWatch(C,D),I=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),index:G.i,rescaleY:w}}},J=function(a){return function(b){void 0!==b.index&&(G.i=b.index),void 0!==b.rescaleY&&(w=b.rescaleY),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};f.dispatch.on("elementMouseover.tooltip",function(a){var c={x:b.x()(a.point),y:b.y()(a.point),color:a.point.color};a.point=c,l.data(a).position(a.pos).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(a){l.hidden(!0)});var K=null;return b.dispatch=C,b.lines=f,b.legend=i,b.controls=j,b.xAxis=g,b.yAxis=h,b.interactiveLayer=k,b.state=y,b.tooltip=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},rescaleY:{get:function(){return w},set:function(a){w=a}},showControls:{get:function(){return u},set:function(a){u=a}},showLegend:{get:function(){return q},set:function(a){q=a}},average:{get:function(){return B},set:function(a){B=a}},defaultState:{get:function(){return z},set:function(a){z=a}},noData:{get:function(){return A},set:function(a){A=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},noErrorCheck:{get:function(){return E},set:function(a){E=a}},tooltips:{get:function(){return l.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),l.enabled(!!b)}},tooltipContent:{get:function(){return l.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),l.contentGenerator(b)}},margin:{get:function(){return m},set:function(a){m.top=void 0!==a.top?a.top:m.top,m.right=void 0!==a.right?a.right:m.right,m.bottom=void 0!==a.bottom?a.bottom:m.bottom,m.left=void 0!==a.left?a.left:m.left}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),i.color(n)}},useInteractiveGuideline:{get:function(){return v},set:function(a){v=a,a===!0&&(b.interactive(!1),b.useVoronoi(!1))}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,h.orient(a?"right":"left")}},duration:{get:function(){return D},set:function(a){D=a,f.duration(D),g.duration(D),h.duration(D),H.reset(D)}}}),a.utils.inheritOptions(b,f),a.utils.initOptions(b),b},a.models.discreteBar=function(){"use strict";function b(m){return y.reset(),m.each(function(b){var m=k-j.left-j.right,x=l-j.top-j.bottom;c=d3.select(this),a.utils.initSVG(c),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var z=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0}})});n.domain(d||d3.merge(z).map(function(a){return a.x})).rangeBands(f||[0,m],.1),o.domain(e||d3.extent(d3.merge(z).map(function(a){return a.y}).concat(r))),t?o.range(g||[x-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]):o.range(g||[x,0]),h=h||n,i=i||o.copy().range([o(0),o(0)]);var A=c.selectAll("g.nv-wrap.nv-discretebar").data([b]),B=A.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),C=B.append("g");A.select("g");C.append("g").attr("class","nv-groups"),A.attr("transform","translate("+j.left+","+j.top+")");var D=A.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().watchTransition(y,"discreteBar: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),D.watchTransition(y,"discreteBar: groups").style("stroke-opacity",1).style("fill-opacity",.75);var E=D.selectAll("g.nv-bar").data(function(a){return a.values});E.exit().remove();var F=E.enter().append("g").attr("transform",function(a,b,c){return"translate("+(n(p(a,b))+.05*n.rangeBand())+", "+o(0)+")"}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),v.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),v.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){v.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){v.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()});F.append("rect").attr("height",0).attr("width",.9*n.rangeBand()/b.length),t?(F.append("text").attr("text-anchor","middle"),E.select("text").text(function(a,b){return u(q(a,b))}).watchTransition(y,"discreteBar: bars text").attr("x",.9*n.rangeBand()/2).attr("y",function(a,b){return q(a,b)<0?o(q(a,b))-o(0)+12:-4})):E.selectAll("text").remove(),E.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(a,b){return a.color||s(a,b)}).style("stroke",function(a,b){return a.color||s(a,b)}).select("rect").attr("class",w).watchTransition(y,"discreteBar: bars rect").attr("width",.9*n.rangeBand()/b.length),E.watchTransition(y,"discreteBar: bars").attr("transform",function(a,b){var c=n(p(a,b))+.05*n.rangeBand(),d=q(a,b)<0?o(0):o(0)-o(q(a,b))<1?o(0)-1:o(q(a,b));return"translate("+c+", "+d+")"}).select("rect").attr("height",function(a,b){return Math.max(Math.abs(o(q(a,b))-o(e&&e[0]||0))||1)}),h=n.copy(),i=o.copy()}),y.renderEnd("discreteBar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=d3.scale.ordinal(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=[0],s=a.utils.defaultColor(),t=!1,u=d3.format(",.2f"),v=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),w="discreteBar",x=250,y=a.utils.renderWatch(v,x);return b.dispatch=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},forceY:{get:function(){return r},set:function(a){r=a}},showValues:{get:function(){return t},set:function(a){t=a}},x:{get:function(){return p},set:function(a){p=a}},y:{get:function(){return q},set:function(a){q=a}},xScale:{get:function(){return n},set:function(a){n=a}},yScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},valueFormat:{get:function(){return u},set:function(a){u=a}},id:{get:function(){return m},set:function(a){m=a}},rectClass:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b)}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x)}}}),a.utils.initOptions(b),b},a.models.discreteBarChart=function(){"use strict";function b(h){return t.reset(),t.models(e),m&&t.models(f),n&&t.models(g),h.each(function(h){var l=d3.select(this);a.utils.initSVG(l);var q=a.utils.availableWidth(j,l,i),t=a.utils.availableHeight(k,l,i);if(b.update=function(){r.beforeUpdate(),l.transition().duration(s).call(b)},b.container=this,!(h&&h.length&&h.filter(function(a){return a.values.length}).length))return a.utils.noData(b,l),b;l.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var u=l.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([h]),v=u.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),w=v.append("defs"),x=u.select("g");v.append("g").attr("class","nv-x nv-axis"),v.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),v.append("g").attr("class","nv-barsWrap"),x.attr("transform","translate("+i.left+","+i.top+")"),o&&x.select(".nv-y.nv-axis").attr("transform","translate("+q+",0)"),e.width(q).height(t);var y=x.select(".nv-barsWrap").datum(h.filter(function(a){return!a.disabled}));if(y.transition().call(e),w.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),
-x.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(p?2:1)).attr("height",16).attr("x",-c.rangeBand()/(p?1:2)),m){f.scale(c)._ticks(a.utils.calcTicksX(q/100,h)).tickSize(-t,0),x.select(".nv-x.nv-axis").attr("transform","translate(0,"+(d.range()[0]+(e.showValues()&&d.domain()[0]<0?16:0))+")"),x.select(".nv-x.nv-axis").call(f);var z=x.select(".nv-x.nv-axis").selectAll("g");p&&z.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}n&&(g.scale(d)._ticks(a.utils.calcTicksY(t/36,h)).tickSize(-q,0),x.select(".nv-y.nv-axis").call(g)),x.select(".nv-zeroLine line").attr("x1",0).attr("x2",q).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("discreteBar chart immediate"),b}var c,d,e=a.models.discreteBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.tooltip(),i={top:15,right:10,bottom:50,left:60},j=null,k=null,l=a.utils.getColor(),m=!0,n=!0,o=!1,p=!1,q=null,r=d3.dispatch("beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(o?"right":"left").tickFormat(d3.format(",.1f")),h.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).keyFormatter(function(a,b){return f.tickFormat()(a,b)});var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},h.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){h.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(a){h.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.discretebar=e,b.xAxis=f,b.yAxis=g,b.tooltip=h,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},staggerLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return m},set:function(a){m=a}},showYAxis:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return q},set:function(a){q=a}},tooltips:{get:function(){return h.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),h.enabled(!!b)}},tooltipContent:{get:function(){return h.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),h.contentGenerator(b)}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),e.color(l)}},rightAlignYAxis:{get:function(){return o},set:function(a){o=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.distribution=function(){"use strict";function b(k){return m.reset(),k.each(function(b){var k=(e-("x"===g?d.left+d.right:d.top+d.bottom),"x"==g?"y":"x"),l=d3.select(this);a.utils.initSVG(l),c=c||j;var n=l.selectAll("g.nv-distribution").data([b]),o=n.enter().append("g").attr("class","nvd3 nv-distribution"),p=(o.append("g"),n.select("g"));n.attr("transform","translate("+d.left+","+d.top+")");var q=p.selectAll("g.nv-dist").data(function(a){return a},function(a){return a.key});q.enter().append("g"),q.attr("class",function(a,b){return"nv-dist nv-series-"+b}).style("stroke",function(a,b){return i(a,b)});var r=q.selectAll("line.nv-dist"+g).data(function(a){return a.values});r.enter().append("line").attr(g+"1",function(a,b){return c(h(a,b))}).attr(g+"2",function(a,b){return c(h(a,b))}),m.transition(q.exit().selectAll("line.nv-dist"+g),"dist exit").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}).style("stroke-opacity",0).remove(),r.attr("class",function(a,b){return"nv-dist"+g+" nv-dist"+g+"-"+b}).attr(k+"1",0).attr(k+"2",f),m.transition(r,"dist").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}),c=j.copy()}),m.renderEnd("distribution immediate"),b}var c,d={top:0,right:0,bottom:0,left:0},e=400,f=8,g="x",h=function(a){return a[g]},i=a.utils.defaultColor(),j=d3.scale.linear(),k=250,l=d3.dispatch("renderEnd"),m=a.utils.renderWatch(l,k);return b.options=a.utils.optionsFunc.bind(b),b.dispatch=l,b.margin=function(a){return arguments.length?(d.top="undefined"!=typeof a.top?a.top:d.top,d.right="undefined"!=typeof a.right?a.right:d.right,d.bottom="undefined"!=typeof a.bottom?a.bottom:d.bottom,d.left="undefined"!=typeof a.left?a.left:d.left,b):d},b.width=function(a){return arguments.length?(e=a,b):e},b.axis=function(a){return arguments.length?(g=a,b):g},b.size=function(a){return arguments.length?(f=a,b):f},b.getData=function(a){return arguments.length?(h=d3.functor(a),b):h},b.scale=function(a){return arguments.length?(j=a,b):j},b.color=function(c){return arguments.length?(i=a.utils.getColor(c),b):i},b.duration=function(a){return arguments.length?(k=a,m.reset(k),b):k},b},a.models.furiousLegend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?g(a,b):"#fff":m?void 0:a.disabled?g(a,b):"#fff"}function r(a,b){return m&&"furious"==o?a.disengaged?"#fff":g(a,b):a.disabled?"#fff":g(a,b)}return p.each(function(b){var p=d-c.left-c.right,s=d3.select(this);a.utils.initSVG(s);var t=s.selectAll("g.nv-legend").data([b]),u=(t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),t.select("g"));t.attr("transform","translate("+c.left+","+c.top+")");var v,w=u.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),x=w.enter().append("g").attr("class","nv-series");if("classic"==o)x.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),v=w.select("circle");else if("furious"==o){x.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),v=w.select("rect"),x.append("g").attr("class","nv-check-box").property("innerHTML",'<path d="M0.5,5 L22.5,5 L22.5,26.5 L0.5,26.5 L0.5,5 Z" class="nv-box"></path><path d="M5.5,12.8618467 L11.9185089,19.2803556 L31,0.198864511" class="nv-check"></path>').attr("transform","translate(-10,-8)scale(0.5)");var y=w.select(".nv-check-box");y.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}x.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var z=w.select("text.nv-legend-text");w.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=w.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=w.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),w.classed("nv-disabled",function(a){return a.userDisabled}),w.exit().remove(),z.attr("fill",q).text(f);var A;switch(o){case"furious":A=23;break;case"classic":A=20}if(h){var B=[];w.each(function(b,c){var d,e=d3.select(this).select("text");try{if(d=e.node().getComputedTextLength(),0>=d)throw Error()}catch(f){d=a.utils.calcApproxTextWidth(e)}B.push(d+i)});for(var C=0,D=0,E=[];p>D&&C<B.length;)E[C]=B[C],D+=B[C++];for(0===C&&(C=1);D>p&&C>1;){E=[],C--;for(var F=0;F<B.length;F++)B[F]>(E[F%C]||0)&&(E[F%C]=B[F]);D=E.reduce(function(a,b,c,d){return a+b})}for(var G=[],H=0,I=0;C>H;H++)G[H]=I,I+=E[H];w.attr("transform",function(a,b){return"translate("+G[b%C]+","+(5+Math.floor(b/C)*A)+")"}),j?u.attr("transform","translate("+(d-c.right-D)+","+c.top+")"):u.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(B.length/C)*A}else{var J,K=5,L=5,M=0;w.attr("transform",function(a,b){var e=d3.select(this).select("text").node().getComputedTextLength()+i;return J=L,d<c.left+c.right+J+e&&(L=J=5,K+=A),L+=e,L>M&&(M=L),"translate("+J+","+K+")"}),u.attr("transform","translate("+(d-c.right-M)+","+c.top+")"),e=c.top+c.bottom+K+15}"furious"==o&&v.attr("width",function(a,b){return z[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),v.style("fill",r).style("stroke",function(a,b){return a.color||g(a,b)})}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=28,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBar=function(){"use strict";function b(x){return x.each(function(b){w.reset(),k=d3.select(this);var x=a.utils.availableWidth(h,k,g),y=a.utils.availableHeight(i,k,g);a.utils.initSVG(k),l.domain(c||d3.extent(b[0].values.map(n).concat(p))),r?l.range(e||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]):l.range(e||[0,x]),m.domain(d||d3.extent(b[0].values.map(o).concat(q))).range(f||[y,0]),l.domain()[0]===l.domain()[1]&&(l.domain()[0]?l.domain([l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]):l.domain([-1,1])),m.domain()[0]===m.domain()[1]&&(m.domain()[0]?m.domain([m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]):m.domain([-1,1]));var z=k.selectAll("g.nv-wrap.nv-historicalBar-"+j).data([b[0].values]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+j),B=A.append("defs"),C=A.append("g"),D=z.select("g");C.append("g").attr("class","nv-bars"),z.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){u.chartClick({data:a,index:b,pos:d3.event,id:j})}),B.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),z.select("#nv-chart-clip-path-"+j+" rect").attr("width",x).attr("height",y),D.attr("clip-path",s?"url(#nv-chart-clip-path-"+j+")":"");var E=z.select(".nv-bars").selectAll(".nv-bar").data(function(a){return a},function(a,b){return n(a,b)});E.exit().remove(),E.enter().append("rect").attr("x",0).attr("y",function(b,c){return a.utils.NaNtoZero(m(Math.max(0,o(b,c))))}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.abs(m(o(b,c))-m(0)))}).attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).on("mouseover",function(a,b){v&&(d3.select(this).classed("hover",!0),u.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mouseout",function(a,b){v&&(d3.select(this).classed("hover",!1),u.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mousemove",function(a,b){v&&u.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v&&(u.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}).on("dblclick",function(a,b){v&&(u.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}),E.attr("fill",function(a,b){return t(a,b)}).attr("class",function(a,b,c){return(o(a,b)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+c+"-"+b}).watchTransition(w,"bars").attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).attr("width",x/b[0].values.length*.9),E.watchTransition(w,"bars").attr("y",function(b,c){var d=o(b,c)<0?m(0):m(0)-m(o(b,c))<1?m(0)-1:m(o(b,c));return a.utils.NaNtoZero(d)}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.max(Math.abs(m(o(b,c))-m(0)),1))})}),w.renderEnd("historicalBar immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=[],q=[0],r=!1,s=!0,t=a.utils.defaultColor(),u=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),v=!0,w=a.utils.renderWatch(u,0);return b.highlightPoint=function(a,b){k.select(".nv-bars .nv-bar-0-"+a).classed("hover",b)},b.clearHighlights=function(){k.select(".nv-bars .nv-bar.hover").classed("hover",!1)},b.dispatch=u,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},forceX:{get:function(){return p},set:function(a){p=a}},forceY:{get:function(){return q},set:function(a){q=a}},padData:{get:function(){return r},set:function(a){r=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},clipEdge:{get:function(){return s},set:function(a){s=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return v},set:function(a){v=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return t},set:function(b){t=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBarChart=function(b){"use strict";function c(b){return b.each(function(k){z.reset(),z.models(f),q&&z.models(g),r&&z.models(h);var w=d3.select(this),A=this;a.utils.initSVG(w);var B=a.utils.availableWidth(n,w,l),C=a.utils.availableHeight(o,w,l);if(c.update=function(){w.transition().duration(y).call(c)},c.container=this,u.disabled=k.map(function(a){return!!a.disabled}),!v){var D;v={};for(D in u)u[D]instanceof Array?v[D]=u[D].slice(0):v[D]=u[D]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(c,w),c;w.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale();var E=w.selectAll("g.nv-wrap.nv-historicalBarChart").data([k]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),G=E.select("g");F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-barsWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),p&&(i.width(B),G.select(".nv-legendWrap").datum(k).call(i),l.top!=i.height()&&(l.top=i.height(),C=a.utils.availableHeight(o,w,l)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-l.top+")")),E.attr("transform","translate("+l.left+","+l.top+")"),s&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),t&&(j.width(B).height(C).margin({left:l.left,top:l.top}).svgContainer(w).xScale(d),E.select(".nv-interactive").call(j)),f.width(B).height(C).color(k.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!k[b].disabled}));var H=G.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));H.transition().call(f),q&&(g.scale(d)._ticks(a.utils.calcTicksX(B/100,k)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),G.select(".nv-x.nv-axis").transition().call(g)),r&&(h.scale(e)._ticks(a.utils.calcTicksY(C/36,k)).tickSize(-B,0),G.select(".nv-y.nv-axis").transition().call(h)),j.dispatch.on("elementMousemove",function(b){f.clearHighlights();var d,e,i,n=[];k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,b.pointXValue,c.x()),f.highlightPoint(e,!0);var j=g.values[e];void 0!==j&&(void 0===d&&(d=j),void 0===i&&(i=c.xScale()(c.x()(j,e))),n.push({key:g.key,value:c.y()(j,e),color:m(g,g.seriesIndex),data:g.values[e]}))});var o=g.tickFormat()(c.x()(d,e));j.tooltip.position({left:i+l.left,top:b.mouseY+l.top}).chartContainer(A.parentNode).valueFormatter(function(a,b){return h.tickFormat()(a)}).data({value:o,index:e,series:n})(),j.renderGuideLine(i)}),j.dispatch.on("elementMouseout",function(a){x.tooltipHide(),f.clearHighlights()}),i.dispatch.on("legendClick",function(a,d){a.disabled=!a.disabled,k.filter(function(a){return!a.disabled}).length||k.map(function(a){return a.disabled=!1,E.selectAll(".nv-series").classed("disabled",!1),a}),u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),b.transition().call(c)}),i.dispatch.on("legendDblclick",function(a){k.forEach(function(a){a.disabled=!0}),a.disabled=!1,u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),c.update()}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),c.update()})}),z.renderEnd("historicalBarChart immediate"),c}var d,e,f=b||a.models.historicalBar(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:90,bottom:50,left:90},m=a.utils.defaultColor(),n=null,o=null,p=!1,q=!0,r=!0,s=!1,t=!1,u={},v=null,w=null,x=d3.dispatch("tooltipHide","stateChange","changeState","renderEnd"),y=250;g.orient("bottom").tickPadding(7),h.orient(s?"right":"left"),k.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)});var z=a.utils.renderWatch(x,0);return f.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:c.x()(a.data),value:c.y()(a.data),color:a.color},k.data(a).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(a){k.hidden(!0)}),f.dispatch.on("elementMousemove.tooltip",function(a){k.position({top:d3.event.pageY,left:d3.event.pageX})()}),c.dispatch=x,c.bars=f,c.legend=i,c.xAxis=g,c.yAxis=h,c.interactiveLayer=j,c.tooltip=k,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{width:{get:function(){return n},set:function(a){n=a}},height:{get:function(){return o},set:function(a){o=a}},showLegend:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return q},set:function(a){q=a}},showYAxis:{get:function(){return r},set:function(a){r=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b),i.color(m),f.color(m)}},duration:{get:function(){return y},set:function(a){y=a,z.reset(y),h.duration(y),g.duration(y)}},rightAlignYAxis:{get:function(){return s},set:function(a){s=a,h.orient(a?"right":"left")}},useInteractiveGuideline:{get:function(){return t},set:function(a){t=a,a===!0&&c.interactive(!1)}}}),a.utils.inheritOptions(c,f),a.utils.initOptions(c),c},a.models.ohlcBarChart=function(){var b=a.models.historicalBarChart(a.models.ohlcBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open<c.close?"2ca02c":"d62728";return'<h3 style="color: #'+d+'">'+a.value+"</h3><table><tr><td>open:</td><td>"+b.yAxis.tickFormat()(c.open)+"</td></tr><tr><td>close:</td><td>"+b.yAxis.tickFormat()(c.close)+"</td></tr><tr><td>high</td><td>"+b.yAxis.tickFormat()(c.high)+"</td></tr><tr><td>low:</td><td>"+b.yAxis.tickFormat()(c.low)+"</td></tr></table>"}),b},a.models.candlestickBarChart=function(){var b=a.models.historicalBarChart(a.models.candlestickBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open<c.close?"2ca02c":"d62728";return'<h3 style="color: #'+d+'">'+a.value+"</h3><table><tr><td>open:</td><td>"+b.yAxis.tickFormat()(c.open)+"</td></tr><tr><td>close:</td><td>"+b.yAxis.tickFormat()(c.close)+"</td></tr><tr><td>high</td><td>"+b.yAxis.tickFormat()(c.high)+"</td></tr><tr><td>low:</td><td>"+b.yAxis.tickFormat()(c.low)+"</td></tr></table>"}),b},a.models.legend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?"#000":"#fff":m?void 0:(a.color||(a.color=g(a,b)),a.disabled?a.color:"#fff")}function r(a,b){return m&&"furious"==o&&a.disengaged?"#eee":a.color||g(a,b)}function s(a,b){return m&&"furious"==o?1:a.disabled?0:1}return p.each(function(b){var g=d-c.left-c.right,p=d3.select(this);a.utils.initSVG(p);var t=p.selectAll("g.nv-legend").data([b]),u=t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),v=t.select("g");t.attr("transform","translate("+c.left+","+c.top+")");var w,x,y=v.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),z=y.enter().append("g").attr("class","nv-series");switch(o){case"furious":x=23;break;case"classic":x=20}if("classic"==o)z.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),w=y.select("circle");else if("furious"==o){z.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),w=y.select(".nv-legend-symbol"),z.append("g").attr("class","nv-check-box").property("innerHTML",'<path d="M0.5,5 L22.5,5 L22.5,26.5 L0.5,26.5 L0.5,5 Z" class="nv-box"></path><path d="M5.5,12.8618467 L11.9185089,19.2803556 L31,0.198864511" class="nv-check"></path>').attr("transform","translate(-10,-8)scale(0.5)");var A=y.select(".nv-check-box");A.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}z.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var B=y.select("text.nv-legend-text");y.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=y.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=y.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),y.classed("nv-disabled",function(a){return a.userDisabled}),y.exit().remove(),B.attr("fill",q).text(f);var C=0;if(h){var D=[];y.each(function(b,c){var d,e=d3.select(this).select("text");try{if(d=e.node().getComputedTextLength(),0>=d)throw Error()}catch(f){d=a.utils.calcApproxTextWidth(e)}D.push(d+i)});var E=0,F=[];for(C=0;g>C&&E<D.length;)F[E]=D[E],C+=D[E++];for(0===E&&(E=1);C>g&&E>1;){F=[],E--;for(var G=0;G<D.length;G++)D[G]>(F[G%E]||0)&&(F[G%E]=D[G]);C=F.reduce(function(a,b,c,d){return a+b})}for(var H=[],I=0,J=0;E>I;I++)H[I]=J,J+=F[I];y.attr("transform",function(a,b){return"translate("+H[b%E]+","+(5+Math.floor(b/E)*x)+")"}),j?v.attr("transform","translate("+(d-c.right-C)+","+c.top+")"):v.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(D.length/E)*x}else{var K,L=5,M=5,N=0;y.attr("transform",function(a,b){var e=d3.select(this).select("text").node().getComputedTextLength()+i;return K=M,d<c.left+c.right+K+e&&(M=K=5,L+=x),M+=e,M>N&&(N=M),K+N>C&&(C=K+N),"translate("+K+","+L+")"}),v.attr("transform","translate("+(d-c.right-N)+","+c.top+")"),e=c.top+c.bottom+L+15}if("furious"==o){w.attr("width",function(a,b){return B[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),u.insert("rect",":first-child").attr("class","nv-legend-bg").attr("fill","#eee").attr("opacity",0);var O=v.select(".nv-legend-bg");O.transition().duration(300).attr("x",-x).attr("width",C+x-12).attr("height",e+10).attr("y",-c.top-10).attr("opacity",m?1:0)}w.style("fill",r).style("fill-opacity",s).style("stroke",r)}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=32,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.line=function(){"use strict";function b(r){return v.reset(),v.models(e),r.each(function(b){i=d3.select(this);var r=a.utils.availableWidth(g,i,f),s=a.utils.availableHeight(h,i,f);a.utils.initSVG(i),c=e.xScale(),d=e.yScale(),t=t||c,u=u||d;var w=i.selectAll("g.nv-wrap.nv-line").data([b]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),y=x.append("defs"),z=x.append("g"),A=w.select("g");z.append("g").attr("class","nv-groups"),z.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+f.left+","+f.top+")"),e.width(r).height(s);var B=w.select(".nv-scatterWrap");B.call(e),y.append("clipPath").attr("id","nv-edge-clip-"+e.id()).append("rect"),w.select("#nv-edge-clip-"+e.id()+" rect").attr("width",r).attr("height",s>0?s:0),A.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":""),B.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":"");var C=w.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});C.enter().append("g").style("stroke-opacity",1e-6).style("stroke-width",function(a){return a.strokeWidth||j}).style("fill-opacity",1e-6),C.exit().remove(),C.attr("class",function(a,b){return(a.classed||"")+" nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return k(a,b)}).style("stroke",function(a,b){return k(a,b)}),C.watchTransition(v,"line: groups").style("stroke-opacity",1).style("fill-opacity",function(a){return a.fillOpacity||.5});var D=C.selectAll("path.nv-area").data(function(a){return o(a)?[a]:[]});D.enter().append("path").attr("class","nv-area").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y0(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))}).y1(function(a,b){return u(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])}),C.exit().selectAll("path.nv-area").remove(),D.watchTransition(v,"line: areaPaths").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y0(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))}).y1(function(a,b){return d(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])});var E=C.selectAll("path.nv-line").data(function(a){return[a.values]});E.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))})),E.watchTransition(v,"line: linePaths").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))})),t=c.copy(),u=d.copy()}),v.renderEnd("line immediate"),b}var c,d,e=a.models.scatter(),f={top:0,right:0,bottom:0,left:0},g=960,h=500,i=null,j=1.5,k=a.utils.defaultColor(),l=function(a){return a.x},m=function(a){return a.y},n=function(a,b){return!isNaN(m(a,b))&&null!==m(a,b)},o=function(a){return a.area},p=!1,q="linear",r=250,s=d3.dispatch("elementClick","elementMouseover","elementMouseout","renderEnd");e.pointSize(16).pointDomain([16,256]);var t,u,v=a.utils.renderWatch(s,r);return b.dispatch=s,b.scatter=e,e.dispatch.on("elementClick",function(){s.elementClick.apply(this,arguments)}),e.dispatch.on("elementMouseover",function(){s.elementMouseover.apply(this,arguments)}),e.dispatch.on("elementMouseout",function(){s.elementMouseout.apply(this,arguments)}),b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},defined:{get:function(){return n},set:function(a){n=a}},interpolate:{get:function(){return q},set:function(a){q=a}},clipEdge:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},duration:{get:function(){return r},set:function(a){r=a,v.reset(r),e.duration(r)}},isArea:{get:function(){return o},set:function(a){o=d3.functor(a)}},x:{get:function(){return l},set:function(a){l=a,e.x(a)}},y:{get:function(){return m},set:function(a){m=a,e.y(a)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineChart=function(){"use strict";function b(j){return y.reset(),y.models(e),
-p&&y.models(f),q&&y.models(g),j.each(function(j){var v=d3.select(this),y=this;a.utils.initSVG(v);var B=a.utils.availableWidth(m,v,k),C=a.utils.availableHeight(n,v,k);if(b.update=function(){0===x?v.call(b):v.transition().duration(x).call(b)},b.container=this,t.setter(A(j),b.update).getter(z(j)).update(),t.disabled=j.map(function(a){return!!a.disabled}),!u){var D;u={};for(D in t)t[D]instanceof Array?u[D]=t[D].slice(0):u[D]=t[D]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,v),b;v.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var E=v.selectAll("g.nv-wrap.nv-lineChart").data([j]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),G=E.select("g");F.append("rect").style("opacity",0),F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-linesWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),G.select("rect").attr("width",B).attr("height",C>0?C:0),o&&(h.width(B),G.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),C=a.utils.availableHeight(n,v,k)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-k.top+")")),E.attr("transform","translate("+k.left+","+k.top+")"),r&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),s&&(i.width(B).height(C).margin({left:k.left,top:k.top}).svgContainer(v).xScale(c),E.select(".nv-interactive").call(i)),e.width(B).height(C).color(j.map(function(a,b){return a.color||l(a,b)}).filter(function(a,b){return!j[b].disabled}));var H=G.select(".nv-linesWrap").datum(j.filter(function(a){return!a.disabled}));H.call(e),p&&(f.scale(c)._ticks(a.utils.calcTicksX(B/100,j)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),G.select(".nv-x.nv-axis").call(f)),q&&(g.scale(d)._ticks(a.utils.calcTicksY(C/36,j)).tickSize(-B,0),G.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)t[c]=a[c];w.stateChange(t),b.update()}),i.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,h,m,n=[];if(j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,g){h=a.interactiveBisect(f.values,c.pointXValue,b.x());var i=f.values[h],j=b.y()(i,h);null!=j&&e.highlightPoint(g,h,!0),void 0!==i&&(void 0===d&&(d=i),void 0===m&&(m=b.xScale()(b.x()(i,h))),n.push({key:f.key,value:j,color:l(f,f.seriesIndex)}))}),n.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(n.map(function(a){return a.value}),o,q);null!==r&&(n[r].highlight=!0)}var s=f.tickFormat()(b.x()(d,h));i.tooltip.position({left:c.mouseX+k.left,top:c.mouseY+k.top}).chartContainer(y.parentNode).valueFormatter(function(a,b){return null==a?"N/A":g.tickFormat()(a)}).data({value:s,index:h,series:n})(),i.renderGuideLine(m)}),i.dispatch.on("elementClick",function(c){var d,f=[];j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(e){var g=a.interactiveBisect(e.values,c.pointXValue,b.x()),h=e.values[g];if("undefined"!=typeof h){"undefined"==typeof d&&(d=b.xScale()(b.x()(h,g)));var i=b.yScale()(b.y()(h,g));f.push({point:h,pointIndex:g,pos:[d,i],seriesIndex:e.seriesIndex,series:e})}}),e.dispatch.elementClick(f)}),i.dispatch.on("elementMouseout",function(a){e.clearHighlights()}),w.on("changeState",function(a){"undefined"!=typeof a.disabled&&j.length===a.disabled.length&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),t.disabled=a.disabled),b.update()})}),y.renderEnd("lineChart immediate"),b}var c,d,e=a.models.line(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.interactiveGuideline(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=a.utils.defaultColor(),m=null,n=null,o=!0,p=!0,q=!0,r=!1,s=!1,t=a.utils.state(),u=null,v=null,w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),x=250;f.orient("bottom").tickPadding(7),g.orient(r?"right":"left"),j.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)});var y=a.utils.renderWatch(w,x),z=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},A=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){j.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){j.hidden(!0)}),b.dispatch=w,b.lines=e,b.legend=h,b.xAxis=f,b.yAxis=g,b.interactiveLayer=i,b.tooltip=j,b.dispatch=w,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return p},set:function(a){p=a}},showYAxis:{get:function(){return q},set:function(a){q=a}},defaultState:{get:function(){return u},set:function(a){u=a}},noData:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x),e.duration(x),f.duration(x),g.duration(x)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),h.color(l),e.color(l)}},rightAlignYAxis:{get:function(){return r},set:function(a){r=a,g.orient(r?"right":"left")}},useInteractiveGuideline:{get:function(){return s},set:function(a){s=a,s&&(e.interactive(!1),e.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.linePlusBarChart=function(){"use strict";function b(v){return v.each(function(v){function J(a){var b=+("e"==a),c=b?1:-1,d=X/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function S(){u.empty()||u.extent(I),ka.data([u.empty()?e.domain():I]).each(function(a,b){var c=e(a[0])-e.range()[0],d=e.range()[1]-e(a[1]);d3.select(this).select(".left").attr("width",0>c?0:c),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>d?0:d)})}function T(){I=u.empty()?null:u.extent(),c=u.empty()?e.domain():u.extent(),K.brush({extent:c,brush:u}),S(),l.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),j.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var b=da.select(".nv-focus .nv-barsWrap").datum(Z.length?Z.map(function(a,b){return{key:a.key,values:a.values.filter(function(a,b){return l.x()(a,b)>=c[0]&&l.x()(a,b)<=c[1]})}}):[{values:[]}]),h=da.select(".nv-focus .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$.map(function(a,b){return{area:a.area,fillOpacity:a.fillOpacity,key:a.key,values:a.values.filter(function(a,b){return j.x()(a,b)>=c[0]&&j.x()(a,b)<=c[1]})}}));d=Z.length?l.xScale():j.xScale(),n.scale(d)._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-W,0),n.domain([Math.ceil(c[0]),Math.floor(c[1])]),da.select(".nv-x.nv-axis").transition().duration(L).call(n),b.transition().duration(L).call(l),h.transition().duration(L).call(j),da.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),p.scale(f)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(-V,0),q.scale(g)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(Z.length?0:-V,0),da.select(".nv-focus .nv-y1.nv-axis").style("opacity",Z.length?1:0),da.select(".nv-focus .nv-y2.nv-axis").style("opacity",$.length&&!$[0].disabled?1:0).attr("transform","translate("+d.range()[1]+",0)"),da.select(".nv-focus .nv-y1.nv-axis").transition().duration(L).call(p),da.select(".nv-focus .nv-y2.nv-axis").transition().duration(L).call(q)}var U=d3.select(this);a.utils.initSVG(U);var V=a.utils.availableWidth(y,U,w),W=a.utils.availableHeight(z,U,w)-(E?H:0),X=H-x.top-x.bottom;if(b.update=function(){U.transition().duration(L).call(b)},b.container=this,M.setter(R(v),b.update).getter(Q(v)).update(),M.disabled=v.map(function(a){return!!a.disabled}),!N){var Y;N={};for(Y in M)M[Y]instanceof Array?N[Y]=M[Y].slice(0):N[Y]=M[Y]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length))return a.utils.noData(b,U),b;U.selectAll(".nv-noData").remove();var Z=v.filter(function(a){return!a.disabled&&a.bar}),$=v.filter(function(a){return!a.bar});d=l.xScale(),e=o.scale(),f=l.yScale(),g=j.yScale(),h=m.yScale(),i=k.yScale();var _=v.filter(function(a){return!a.disabled&&a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})}),aa=v.filter(function(a){return!a.disabled&&!a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})});d.range([0,V]),e.domain(d3.extent(d3.merge(_.concat(aa)),function(a){return a.x})).range([0,V]);var ba=U.selectAll("g.nv-wrap.nv-linePlusBar").data([v]),ca=ba.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),da=ba.select("g");ca.append("g").attr("class","nv-legendWrap");var ea=ca.append("g").attr("class","nv-focus");ea.append("g").attr("class","nv-x nv-axis"),ea.append("g").attr("class","nv-y1 nv-axis"),ea.append("g").attr("class","nv-y2 nv-axis"),ea.append("g").attr("class","nv-barsWrap"),ea.append("g").attr("class","nv-linesWrap");var fa=ca.append("g").attr("class","nv-context");if(fa.append("g").attr("class","nv-x nv-axis"),fa.append("g").attr("class","nv-y1 nv-axis"),fa.append("g").attr("class","nv-y2 nv-axis"),fa.append("g").attr("class","nv-barsWrap"),fa.append("g").attr("class","nv-linesWrap"),fa.append("g").attr("class","nv-brushBackground"),fa.append("g").attr("class","nv-x nv-brush"),D){var ga=t.align()?V/2:V,ha=t.align()?ga:0;t.width(ga),da.select(".nv-legendWrap").datum(v.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(a.bar?O:P),a})).call(t),w.top!=t.height()&&(w.top=t.height(),W=a.utils.availableHeight(z,U,w)-H),da.select(".nv-legendWrap").attr("transform","translate("+ha+","+-w.top+")")}ba.attr("transform","translate("+w.left+","+w.top+")"),da.select(".nv-context").style("display",E?"initial":"none"),m.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),k.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var ia=da.select(".nv-context .nv-barsWrap").datum(Z.length?Z:[{values:[]}]),ja=da.select(".nv-context .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$);da.select(".nv-context").attr("transform","translate(0,"+(W+w.bottom+x.top)+")"),ia.transition().call(m),ja.transition().call(k),G&&(o._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-X,0),da.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+h.range()[0]+")"),da.select(".nv-context .nv-x.nv-axis").transition().call(o)),F&&(r.scale(h)._ticks(X/36).tickSize(-V,0),s.scale(i)._ticks(X/36).tickSize(Z.length?0:-V,0),da.select(".nv-context .nv-y3.nv-axis").style("opacity",Z.length?1:0).attr("transform","translate(0,"+e.range()[0]+")"),da.select(".nv-context .nv-y2.nv-axis").style("opacity",$.length?1:0).attr("transform","translate("+e.range()[1]+",0)"),da.select(".nv-context .nv-y1.nv-axis").transition().call(r),da.select(".nv-context .nv-y2.nv-axis").transition().call(s)),u.x(e).on("brush",T),I&&u.extent(I);var ka=da.select(".nv-brushBackground").selectAll("g").data([I||u.extent()]),la=ka.enter().append("g");la.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",X),la.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",X);var ma=da.select(".nv-x.nv-brush").call(u);ma.selectAll("rect").attr("height",X),ma.selectAll(".resize").append("path").attr("d",J),t.dispatch.on("stateChange",function(a){for(var c in a)M[c]=a[c];K.stateChange(M),b.update()}),K.on("changeState",function(a){"undefined"!=typeof a.disabled&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),M.disabled=a.disabled),b.update()}),T()}),b}var c,d,e,f,g,h,i,j=a.models.line(),k=a.models.line(),l=a.models.historicalBar(),m=a.models.historicalBar(),n=a.models.axis(),o=a.models.axis(),p=a.models.axis(),q=a.models.axis(),r=a.models.axis(),s=a.models.axis(),t=a.models.legend(),u=d3.svg.brush(),v=a.models.tooltip(),w={top:30,right:30,bottom:30,left:60},x={top:0,right:30,bottom:20,left:60},y=null,z=null,A=function(a){return a.x},B=function(a){return a.y},C=a.utils.defaultColor(),D=!0,E=!0,F=!1,G=!0,H=50,I=null,J=null,K=d3.dispatch("brush","stateChange","changeState"),L=0,M=a.utils.state(),N=null,O=" (left axis)",P=" (right axis)";j.clipEdge(!0),k.interactive(!1),n.orient("bottom").tickPadding(5),p.orient("left"),q.orient("right"),o.orient("bottom").tickPadding(5),r.orient("left"),s.orient("right"),v.headerEnabled(!0).headerFormatter(function(a,b){return n.tickFormat()(a,b)});var Q=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},R=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return j.dispatch.on("elementMouseover.tooltip",function(a){v.duration(100).valueFormatter(function(a,b){return q.tickFormat()(a,b)}).data(a).position(a.pos).hidden(!1)}),j.dispatch.on("elementMouseout.tooltip",function(a){v.hidden(!0)}),l.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={value:b.y()(a.data),color:a.color},v.duration(0).valueFormatter(function(a,b){return p.tickFormat()(a,b)}).data(a).hidden(!1)}),l.dispatch.on("elementMouseout.tooltip",function(a){v.hidden(!0)}),l.dispatch.on("elementMousemove.tooltip",function(a){v.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=K,b.legend=t,b.lines=j,b.lines2=k,b.bars=l,b.bars2=m,b.xAxis=n,b.x2Axis=o,b.y1Axis=p,b.y2Axis=q,b.y3Axis=r,b.y4Axis=s,b.tooltip=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return y},set:function(a){y=a}},height:{get:function(){return z},set:function(a){z=a}},showLegend:{get:function(){return D},set:function(a){D=a}},brushExtent:{get:function(){return I},set:function(a){I=a}},noData:{get:function(){return J},set:function(a){J=a}},focusEnable:{get:function(){return E},set:function(a){E=a}},focusHeight:{get:function(){return H},set:function(a){H=a}},focusShowAxisX:{get:function(){return G},set:function(a){G=a}},focusShowAxisY:{get:function(){return F},set:function(a){F=a}},legendLeftAxisHint:{get:function(){return O},set:function(a){O=a}},legendRightAxisHint:{get:function(){return P},set:function(a){P=a}},tooltips:{get:function(){return v.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),v.enabled(!!b)}},tooltipContent:{get:function(){return v.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),v.contentGenerator(b)}},margin:{get:function(){return w},set:function(a){w.top=void 0!==a.top?a.top:w.top,w.right=void 0!==a.right?a.right:w.right,w.bottom=void 0!==a.bottom?a.bottom:w.bottom,w.left=void 0!==a.left?a.left:w.left}},duration:{get:function(){return L},set:function(a){L=a}},color:{get:function(){return C},set:function(b){C=a.utils.getColor(b),t.color(C)}},x:{get:function(){return A},set:function(a){A=a,j.x(a),k.x(a),l.x(a),m.x(a)}},y:{get:function(){return B},set:function(a){B=a,j.y(a),k.y(a),l.y(a),m.y(a)}}}),a.utils.inheritOptions(b,j),a.utils.initOptions(b),b},a.models.lineWithFocusChart=function(){"use strict";function b(o){return o.each(function(o){function z(a){var b=+("e"==a),c=b?1:-1,d=M/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function G(){n.empty()||n.extent(y),U.data([n.empty()?e.domain():y]).each(function(a,b){var d=e(a[0])-c.range()[0],f=K-e(a[1]);d3.select(this).select(".left").attr("width",0>d?0:d),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>f?0:f)})}function H(){y=n.empty()?null:n.extent();var a=n.empty()?e.domain():n.extent();if(!(Math.abs(a[0]-a[1])<=1)){A.brush({extent:a,brush:n}),G();var b=Q.select(".nv-focus .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}).map(function(b,c){return{key:b.key,area:b.area,values:b.values.filter(function(b,c){return g.x()(b,c)>=a[0]&&g.x()(b,c)<=a[1]})}}));b.transition().duration(B).call(g),Q.select(".nv-focus .nv-x.nv-axis").transition().duration(B).call(i),Q.select(".nv-focus .nv-y.nv-axis").transition().duration(B).call(j)}}var I=d3.select(this),J=this;a.utils.initSVG(I);var K=a.utils.availableWidth(t,I,q),L=a.utils.availableHeight(u,I,q)-v,M=v-r.top-r.bottom;if(b.update=function(){I.transition().duration(B).call(b)},b.container=this,C.setter(F(o),b.update).getter(E(o)).update(),C.disabled=o.map(function(a){return!!a.disabled}),!D){var N;D={};for(N in C)C[N]instanceof Array?D[N]=C[N].slice(0):D[N]=C[N]}if(!(o&&o.length&&o.filter(function(a){return a.values.length}).length))return a.utils.noData(b,I),b;I.selectAll(".nv-noData").remove(),c=g.xScale(),d=g.yScale(),e=h.xScale(),f=h.yScale();var O=I.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([o]),P=O.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),Q=O.select("g");P.append("g").attr("class","nv-legendWrap");var R=P.append("g").attr("class","nv-focus");R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-linesWrap"),R.append("g").attr("class","nv-interactive");var S=P.append("g").attr("class","nv-context");S.append("g").attr("class","nv-x nv-axis"),S.append("g").attr("class","nv-y nv-axis"),S.append("g").attr("class","nv-linesWrap"),S.append("g").attr("class","nv-brushBackground"),S.append("g").attr("class","nv-x nv-brush"),x&&(m.width(K),Q.select(".nv-legendWrap").datum(o).call(m),q.top!=m.height()&&(q.top=m.height(),L=a.utils.availableHeight(u,I,q)-v),Q.select(".nv-legendWrap").attr("transform","translate(0,"+-q.top+")")),O.attr("transform","translate("+q.left+","+q.top+")"),w&&(p.width(K).height(L).margin({left:q.left,top:q.top}).svgContainer(I).xScale(c),O.select(".nv-interactive").call(p)),g.width(K).height(L).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),h.defined(g.defined()).width(K).height(M).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),Q.select(".nv-context").attr("transform","translate(0,"+(L+q.bottom+r.top)+")");var T=Q.select(".nv-context .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}));d3.transition(T).call(h),i.scale(c)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-L,0),j.scale(d)._ticks(a.utils.calcTicksY(L/36,o)).tickSize(-K,0),Q.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L+")"),n.x(e).on("brush",function(){H()}),y&&n.extent(y);var U=Q.select(".nv-brushBackground").selectAll("g").data([y||n.extent()]),V=U.enter().append("g");V.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",M),V.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",M);var W=Q.select(".nv-x.nv-brush").call(n);W.selectAll("rect").attr("height",M),W.selectAll(".resize").append("path").attr("d",z),H(),k.scale(e)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-M,0),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),d3.transition(Q.select(".nv-context .nv-x.nv-axis")).call(k),l.scale(f)._ticks(a.utils.calcTicksY(M/36,o)).tickSize(-K,0),d3.transition(Q.select(".nv-context .nv-y.nv-axis")).call(l),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),m.dispatch.on("stateChange",function(a){for(var c in a)C[c]=a[c];A.stateChange(C),b.update()}),p.dispatch.on("elementMousemove",function(c){g.clearHighlights();var d,f,h,k=[];if(o.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(i,j){var l=n.empty()?e.domain():n.extent(),m=i.values.filter(function(a,b){return g.x()(a,b)>=l[0]&&g.x()(a,b)<=l[1]});f=a.interactiveBisect(m,c.pointXValue,g.x());var o=m[f],p=b.y()(o,f);null!=p&&g.highlightPoint(j,f,!0),void 0!==o&&(void 0===d&&(d=o),void 0===h&&(h=b.xScale()(b.x()(o,f))),k.push({key:i.key,value:b.y()(o,f),color:s(i,i.seriesIndex)}))}),k.length>2){var l=b.yScale().invert(c.mouseY),m=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),r=.03*m,t=a.nearestValueIndex(k.map(function(a){return a.value}),l,r);null!==t&&(k[t].highlight=!0)}var u=i.tickFormat()(b.x()(d,f));p.tooltip.position({left:c.mouseX+q.left,top:c.mouseY+q.top}).chartContainer(J.parentNode).valueFormatter(function(a,b){return null==a?"N/A":j.tickFormat()(a)}).data({value:u,index:f,series:k})(),p.renderGuideLine(h)}),p.dispatch.on("elementMouseout",function(a){g.clearHighlights()}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&o.forEach(function(b,c){b.disabled=a.disabled[c]}),b.update()})}),b}var c,d,e,f,g=a.models.line(),h=a.models.line(),i=a.models.axis(),j=a.models.axis(),k=a.models.axis(),l=a.models.axis(),m=a.models.legend(),n=d3.svg.brush(),o=a.models.tooltip(),p=a.interactiveGuideline(),q={top:30,right:30,bottom:30,left:60},r={top:0,right:30,bottom:20,left:60},s=a.utils.defaultColor(),t=null,u=null,v=50,w=!1,x=!0,y=null,z=null,A=d3.dispatch("brush","stateChange","changeState"),B=250,C=a.utils.state(),D=null;g.clipEdge(!0).duration(0),h.interactive(!1),i.orient("bottom").tickPadding(5),j.orient("left"),k.orient("bottom").tickPadding(5),l.orient("left"),o.valueFormatter(function(a,b){return j.tickFormat()(a,b)}).headerFormatter(function(a,b){return i.tickFormat()(a,b)});var E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return g.dispatch.on("elementMouseover.tooltip",function(a){o.data(a).position(a.pos).hidden(!1)}),g.dispatch.on("elementMouseout.tooltip",function(a){o.hidden(!0)}),b.dispatch=A,b.legend=m,b.lines=g,b.lines2=h,b.xAxis=i,b.yAxis=j,b.x2Axis=k,b.y2Axis=l,b.interactiveLayer=p,b.tooltip=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return t},set:function(a){t=a}},height:{get:function(){return u},set:function(a){u=a}},focusHeight:{get:function(){return v},set:function(a){v=a}},showLegend:{get:function(){return x},set:function(a){x=a}},brushExtent:{get:function(){return y},set:function(a){y=a}},defaultState:{get:function(){return D},set:function(a){D=a}},noData:{get:function(){return z},set:function(a){z=a}},tooltips:{get:function(){return o.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),o.enabled(!!b)}},tooltipContent:{get:function(){return o.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),o.contentGenerator(b)}},margin:{get:function(){return q},set:function(a){q.top=void 0!==a.top?a.top:q.top,q.right=void 0!==a.right?a.right:q.right,q.bottom=void 0!==a.bottom?a.bottom:q.bottom,q.left=void 0!==a.left?a.left:q.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b),m.color(s)}},interpolate:{get:function(){return g.interpolate()},set:function(a){g.interpolate(a),h.interpolate(a)}},xTickFormat:{get:function(){return i.tickFormat()},set:function(a){i.tickFormat(a),k.tickFormat(a)}},yTickFormat:{get:function(){return j.tickFormat()},set:function(a){j.tickFormat(a),l.tickFormat(a)}},duration:{get:function(){return B},set:function(a){B=a,j.duration(B),l.duration(B),i.duration(B),k.duration(B)}},x:{get:function(){return g.x()},set:function(a){g.x(a),h.x(a)}},y:{get:function(){return g.y()},set:function(a){g.y(a),h.y(a)}},useInteractiveGuideline:{get:function(){return w},set:function(a){w=a,w&&(g.interactive(!1),g.useVoronoi(!1))}}}),a.utils.inheritOptions(b,g),a.utils.initOptions(b),b},a.models.multiBar=function(){"use strict";function b(G){return E.reset(),G.each(function(b){var G=k-j.left-j.right,H=l-j.top-j.bottom;p=d3.select(this),a.utils.initSVG(p);var I=0;if(z&&b.length&&(z=[{values:b[0].values.map(function(a){return{x:a.x,y:0,series:a.series,size:.01}})}]),v){var J=d3.layout.stack().offset(w).values(function(a){return a.values}).y(r)(!b.length&&z?z:b);J.forEach(function(a,c){a.nonStackable?(b[c].nonStackableSeries=I++,J[c]=b[c]):c>0&&J[c-1].nonStackable&&J[c].values.map(function(a,b){a.y0-=J[c-1].values[b].y,a.y1=a.y0+a.y})}),b=J}b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),v&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a,f){if(!b[f].nonStackable){var g=a.values[c];g.size=Math.abs(g.y),g.y<0?(g.y1=e,e-=g.size):(g.y1=g.size+d,d+=g.size)}})});var K=d&&e?[]:b.map(function(a,b){return a.values.map(function(a,c){return{x:q(a,c),y:r(a,c),y0:a.y0,y1:a.y1,idx:b,yErr:s(a,c)}})});m.domain(d||d3.merge(K).map(function(a){return a.x})).rangeBands(f||[0,G],C),n.domain(e||d3.extent(d3.merge(d3.merge(K).map(function(a){var c=a.y;v&&!b[a.idx].nonStackable&&(c=a.y>0?a.y1:a.y1+a.y);var d=a.yErr;return d?d.length?[c+d[0],c+d[1]]:(d=Math.abs(d),[c-d,c+d]):[c]})).concat(t))).range(g||[H,0]),m.domain()[0]===m.domain()[1]&&(m.domain()[0]?m.domain([m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]):m.domain([-1,1])),n.domain()[0]===n.domain()[1]&&(n.domain()[0]?n.domain([n.domain()[0]+.01*n.domain()[0],n.domain()[1]-.01*n.domain()[1]]):n.domain([-1,1])),h=h||m,i=i||n;var L=p.selectAll("g.nv-wrap.nv-multibar").data([b]),M=L.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),N=M.append("defs"),O=M.append("g"),P=L.select("g");O.append("g").attr("class","nv-groups"),L.attr("transform","translate("+j.left+","+j.top+")"),N.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),L.select("#nv-edge-clip-"+o+" rect").attr("width",G).attr("height",H),P.attr("clip-path",u?"url(#nv-edge-clip-"+o+")":"");var Q=L.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});Q.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);var R=E.transition(Q.exit().selectAll("g.nv-bar"),"multibarExit",Math.min(100,B)).attr("y",function(a,c,d){var e=i(0)||0;return v&&b[a.series]&&!b[a.series].nonStackable&&(e=i(a.y0)),e}).attr("height",0).remove();R.delay&&R.delay(function(a,b){var c=b*(B/(F+1))-b;return c}),Q.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return x(a,b)}).style("stroke",function(a,b){return x(a,b)}),Q.style("stroke-opacity",1).style("fill-opacity",.75);var S=Q.selectAll("g.nv-bar").data(function(a){return z&&!b.length?z.values:a.values});S.exit().remove();var T=S.enter().append("g").attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(a,c,d){var e=v&&!b[d].nonStackable?0:d*m.rangeBand()/b.length,f=i(v&&!b[d].nonStackable?a.y0:0)||0;return"translate("+e+","+f+")"});T.append("rect").attr("height",0).attr("width",function(a,c,d){return m.rangeBand()/(v&&!b[d].nonStackable?1:b.length)}).style("fill",function(a,b,c){return x(a,c,b)}).style("stroke",function(a,b,c){return x(a,c,b)}),S.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),D.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){D.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){D.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){D.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),s(b[0].values[0],0)&&(T.append("polyline"),S.select("polyline").attr("fill","none").attr("stroke",function(a,b,c){return y(a,c,b)}).attr("points",function(a,c){var d=s(a,c),e=.8*m.rangeBand()/(2*(v?1:b.length));d=d.length?d:[-Math.abs(d),Math.abs(d)],d=d.map(function(a){return n(a)-n(0)});var f=[[-e,d[0]],[e,d[0]],[0,d[0]],[0,d[1]],[-e,d[1]],[e,d[1]]];return f.map(function(a){return a.join(",")}).join(" ")}).attr("transform",function(a,c){var d=m.rangeBand()/(2*(v?1:b.length)),e=r(a,c)<0?n(r(a,c))-n(0):0;return"translate("+d+", "+e+")"})),S.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}),A&&(c||(c=b.map(function(){return!0})),S.select("rect").style("fill",function(a,b,d){return d3.rgb(A(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(A(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}));var U=S.watchTransition(E,"multibar",Math.min(250,B)).delay(function(a,c){return c*B/b[0].values.length});v?U.attr("transform",function(a,c,d){var e=0;e=b[d].nonStackable?r(a,c)<0?n(0):n(0)-n(r(a,c))<-1?n(0)-1:n(r(a,c))||0:n(a.y1);var f=0;b[d].nonStackable&&(f=a.series*m.rangeBand()/b.length,b.length!==I&&(f=b[d].nonStackableSeries*m.rangeBand()/(2*I)));var g=f+m(q(a,c));return"translate("+g+","+e+")"}).select("rect").attr("height",function(a,c,d){return b[d].nonStackable?Math.max(Math.abs(n(r(a,c))-n(0)),1)||0:Math.max(Math.abs(n(a.y+a.y0)-n(a.y0)),1)}).attr("width",function(a,c,d){if(b[d].nonStackable){var e=m.rangeBand()/I;return b.length!==I&&(e=m.rangeBand()/(2*I)),e}return m.rangeBand()}):U.attr("transform",function(a,c){var d=a.series*m.rangeBand()/b.length+m(q(a,c)),e=r(a,c)<0?n(0):n(0)-n(r(a,c))<1?n(0)-1:n(r(a,c))||0;return"translate("+d+","+e+")"}).select("rect").attr("width",m.rangeBand()/b.length).attr("height",function(a,b){return Math.max(Math.abs(n(r(a,b))-n(0)),1)||0}),h=m.copy(),i=n.copy(),b[0]&&b[0].values&&(F=b[0].values.length)}),E.renderEnd("multibar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=d3.scale.ordinal(),n=d3.scale.linear(),o=Math.floor(1e4*Math.random()),p=null,q=function(a){return a.x},r=function(a){return a.y},s=function(a){return a.yErr},t=[0],u=!0,v=!1,w="zero",x=a.utils.defaultColor(),y=a.utils.defaultColor(),z=!1,A=null,B=500,C=.1,D=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),E=a.utils.renderWatch(D,B),F=0;return b.dispatch=D,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},yErr:{get:function(){return s},set:function(a){s=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return t},set:function(a){t=a}},stacked:{get:function(){return v},set:function(a){v=a}},stackOffset:{get:function(){return w},set:function(a){w=a}},clipEdge:{get:function(){return u},set:function(a){u=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return o},set:function(a){o=a}},hideable:{get:function(){
-return z},set:function(a){z=a}},groupSpacing:{get:function(){return C},set:function(a){C=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return B},set:function(a){B=a,E.reset(B)}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}},barColor:{get:function(){return A},set:function(b){A=b?a.utils.getColor(b):null}},errorBarColor:{get:function(){return y},set:function(b){y=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarChart=function(){"use strict";function b(j){return D.reset(),D.models(e),r&&D.models(f),s&&D.models(g),j.each(function(j){var z=d3.select(this);a.utils.initSVG(z);var D=a.utils.availableWidth(l,z,k),H=a.utils.availableHeight(m,z,k);if(b.update=function(){0===C?z.call(b):z.transition().duration(C).call(b)},b.container=this,x.setter(G(j),b.update).getter(F(j)).update(),x.disabled=j.map(function(a){return!!a.disabled}),!y){var I;y={};for(I in x)x[I]instanceof Array?y[I]=x[I].slice(0):y[I]=x[I]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,z),b;z.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var J=z.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([j]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),L=J.select("g");if(K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-legendWrap"),K.append("g").attr("class","nv-controlsWrap"),q&&(h.width(D-B()),L.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),H=a.utils.availableHeight(m,z,k)),L.select(".nv-legendWrap").attr("transform","translate("+B()+","+-k.top+")")),o){var M=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(B()).color(["#444","#444","#444"]),L.select(".nv-controlsWrap").datum(M).attr("transform","translate(0,"+-k.top+")").call(i)}J.attr("transform","translate("+k.left+","+k.top+")"),t&&L.select(".nv-y.nv-axis").attr("transform","translate("+D+",0)"),e.disabled(j.map(function(a){return a.disabled})).width(D).height(H).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var N=L.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(N.call(e),r){f.scale(c)._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-H,0),L.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),L.select(".nv-x.nv-axis").call(f);var O=L.select(".nv-x.nv-axis > g").selectAll("g");if(O.selectAll("line, text").style("opacity",1),v){var P=function(a,b){return"translate("+a+","+b+")"},Q=5,R=17;O.selectAll("text").attr("transform",function(a,b,c){return P(0,c%2==0?Q:R)});var S=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;L.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(a,b){return P(0,0===b||S%2!==0?R:Q)})}u&&O.filter(function(a,b){return b%Math.ceil(j[0].values.length/(D/100))!==0}).selectAll("text, line").style("opacity",0),w&&O.selectAll(".tick text").attr("transform","rotate("+w+" 0,0)").style("text-anchor",w>0?"start":"end"),L.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}s&&(g.scale(d)._ticks(a.utils.calcTicksY(H/36,j)).tickSize(-D,0),L.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)x[c]=a[c];A.stateChange(x),b.update()}),i.dispatch.on("legendClick",function(a,c){if(a.disabled){switch(M=M.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":case p.grouped:e.stacked(!1);break;case"Stacked":case p.stacked:e.stacked(!0)}x.stacked=e.stacked(),A.stateChange(x),b.update()}}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),x.stacked=a.stacked,E=a.stacked),b.update()})}),D.renderEnd("multibarchart immediate"),b}var c,d,e=a.models.multiBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=0,x=a.utils.state(),y=null,z=null,A=d3.dispatch("stateChange","changeState","renderEnd"),B=function(){return o?180:0},C=250;x.stacked=!1,e.stacked(!1),f.orient("bottom").tickPadding(7).showMaxMin(!1).tickFormat(function(a){return a}),g.orient(t?"right":"left").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var D=a.utils.renderWatch(A),E=!1,F=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:E}}},G=function(a){return function(b){void 0!==b.stacked&&(E=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(a){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=A,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=x,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return z},set:function(a){z=a}},reduceXTicks:{get:function(){return u},set:function(a){u=a}},rotateLabels:{get:function(){return w},set:function(a){w=a}},staggerLabels:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return C},set:function(a){C=a,e.duration(C),f.duration(C),g.duration(C),D.reset(C)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiBarHorizontal=function(){"use strict";function b(m){return F.reset(),m.each(function(b){var m=k-j.left-j.right,D=l-j.top-j.bottom;n=d3.select(this),a.utils.initSVG(n),x&&(b=d3.layout.stack().offset("zero").values(function(a){return a.values}).y(r)(b)),b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),x&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a){var b=a.values[c];b.size=Math.abs(b.y),b.y<0?(b.y1=e-b.size,e-=b.size):(b.y1=d,d+=b.size)})});var G=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:q(a,b),y:r(a,b),y0:a.y0,y1:a.y1,yErr:s(a,b)}})});o.domain(d||d3.merge(G).map(function(a){return a.x})).rangeBands(f||[0,D],B),p.domain(e||d3.extent(d3.merge(d3.merge(G).map(function(a){var b=a.y;x&&(b=a.y>0?a.y1+a.y:a.y1);var c=a.yErr;return c?c.length?[b+c[0],b+c[1]]:(c=Math.abs(c),[b-c,b+c]):[b]})).concat(t))),y&&!x?p.range(g||[p.domain()[0]<0?A:0,m-(p.domain()[1]>0?A:0)]):p.range(g||[0,m]),h=h||o,i=i||d3.scale.linear().domain(p.domain()).range([p(0),p(0)]);var H=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([b]),I=H.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),J=(I.append("defs"),I.append("g"));H.select("g");J.append("g").attr("class","nv-groups"),H.attr("transform","translate("+j.left+","+j.top+")");var K=H.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});K.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),K.exit().watchTransition(F,"multibarhorizontal: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),K.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return u(a,b)}).style("stroke",function(a,b){return u(a,b)}),K.watchTransition(F,"multibarhorizontal: groups").style("stroke-opacity",1).style("fill-opacity",.75);var L=K.selectAll("g.nv-bar").data(function(a){return a.values});L.exit().remove();var M=L.enter().append("g").attr("transform",function(a,c,d){return"translate("+i(x?a.y0:0)+","+(x?0:d*o.rangeBand()/b.length+o(q(a,c)))+")"});M.append("rect").attr("width",0).attr("height",o.rangeBand()/(x?1:b.length)),L.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),E.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),E.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){E.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){E.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){E.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){E.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),s(b[0].values[0],0)&&(M.append("polyline"),L.select("polyline").attr("fill","none").attr("stroke",function(a,b,c){return w(a,c,b)}).attr("points",function(a,c){var d=s(a,c),e=.8*o.rangeBand()/(2*(x?1:b.length));d=d.length?d:[-Math.abs(d),Math.abs(d)],d=d.map(function(a){return p(a)-p(0)});var f=[[d[0],-e],[d[0],e],[d[0],0],[d[1],0],[d[1],-e],[d[1],e]];return f.map(function(a){return a.join(",")}).join(" ")}).attr("transform",function(a,c){var d=o.rangeBand()/(2*(x?1:b.length));return"translate("+(r(a,c)<0?0:p(r(a,c))-p(0))+", "+d+")"})),M.append("text"),y&&!x?(L.select("text").attr("text-anchor",function(a,b){return r(a,b)<0?"end":"start"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){var c=C(r(a,b)),d=s(a,b);return void 0===d?c:d.length?c+"+"+C(Math.abs(d[1]))+"-"+C(Math.abs(d[0])):c+"±"+C(Math.abs(d))}),L.watchTransition(F,"multibarhorizontal: bars").select("text").attr("x",function(a,b){return r(a,b)<0?-4:p(r(a,b))-p(0)+4})):L.selectAll("text").text(""),z&&!x?(M.append("text").classed("nv-bar-label",!0),L.select("text.nv-bar-label").attr("text-anchor",function(a,b){return r(a,b)<0?"start":"end"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){return q(a,b)}),L.watchTransition(F,"multibarhorizontal: bars").select("text.nv-bar-label").attr("x",function(a,b){return r(a,b)<0?p(0)-p(r(a,b))+4:-4})):L.selectAll("text.nv-bar-label").text(""),L.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}),v&&(c||(c=b.map(function(){return!0})),L.style("fill",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()})),x?L.watchTransition(F,"multibarhorizontal: bars").attr("transform",function(a,b){return"translate("+p(a.y1)+","+o(q(a,b))+")"}).select("rect").attr("width",function(a,b){return Math.abs(p(r(a,b)+a.y0)-p(a.y0))}).attr("height",o.rangeBand()):L.watchTransition(F,"multibarhorizontal: bars").attr("transform",function(a,c){return"translate("+p(r(a,c)<0?r(a,c):0)+","+(a.series*o.rangeBand()/b.length+o(q(a,c)))+")"}).select("rect").attr("height",o.rangeBand()/b.length).attr("width",function(a,b){return Math.max(Math.abs(p(r(a,b))-p(0)),1)}),h=o.copy(),i=p.copy()}),F.renderEnd("multibarHorizontal immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=null,o=d3.scale.ordinal(),p=d3.scale.linear(),q=function(a){return a.x},r=function(a){return a.y},s=function(a){return a.yErr},t=[0],u=a.utils.defaultColor(),v=null,w=a.utils.defaultColor(),x=!1,y=!1,z=!1,A=60,B=.1,C=d3.format(",.2f"),D=250,E=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),F=a.utils.renderWatch(E,D);return b.dispatch=E,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},yErr:{get:function(){return s},set:function(a){s=a}},xScale:{get:function(){return o},set:function(a){o=a}},yScale:{get:function(){return p},set:function(a){p=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return t},set:function(a){t=a}},stacked:{get:function(){return x},set:function(a){x=a}},showValues:{get:function(){return y},set:function(a){y=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return m},set:function(a){m=a}},valueFormat:{get:function(){return C},set:function(a){C=a}},valuePadding:{get:function(){return A},set:function(a){A=a}},groupSpacing:{get:function(){return B},set:function(a){B=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return D},set:function(a){D=a,F.reset(D)}},color:{get:function(){return u},set:function(b){u=a.utils.getColor(b)}},barColor:{get:function(){return v},set:function(b){v=b?a.utils.getColor(b):null}},errorBarColor:{get:function(){return w},set:function(b){w=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarHorizontalChart=function(){"use strict";function b(j){return C.reset(),C.models(e),r&&C.models(f),s&&C.models(g),j.each(function(j){var w=d3.select(this);a.utils.initSVG(w);var C=a.utils.availableWidth(l,w,k),D=a.utils.availableHeight(m,w,k);if(b.update=function(){w.transition().duration(z).call(b)},b.container=this,t=e.stacked(),u.setter(B(j),b.update).getter(A(j)).update(),u.disabled=j.map(function(a){return!!a.disabled}),!v){var E;v={};for(E in u)u[E]instanceof Array?v[E]=u[E].slice(0):v[E]=u[E]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,w),b;w.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var F=w.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([j]),G=F.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),H=F.select("g");if(G.append("g").attr("class","nv-x nv-axis"),G.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),G.append("g").attr("class","nv-barsWrap"),G.append("g").attr("class","nv-legendWrap"),G.append("g").attr("class","nv-controlsWrap"),q&&(h.width(C-y()),H.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),D=a.utils.availableHeight(m,w,k)),H.select(".nv-legendWrap").attr("transform","translate("+y()+","+-k.top+")")),o){var I=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(y()).color(["#444","#444","#444"]),H.select(".nv-controlsWrap").datum(I).attr("transform","translate(0,"+-k.top+")").call(i)}F.attr("transform","translate("+k.left+","+k.top+")"),e.disabled(j.map(function(a){return a.disabled})).width(C).height(D).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var J=H.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(J.transition().call(e),r){f.scale(c)._ticks(a.utils.calcTicksY(D/24,j)).tickSize(-C,0),H.select(".nv-x.nv-axis").call(f);var K=H.select(".nv-x.nv-axis").selectAll("g");K.selectAll("line, text")}s&&(g.scale(d)._ticks(a.utils.calcTicksX(C/100,j)).tickSize(-D,0),H.select(".nv-y.nv-axis").attr("transform","translate(0,"+D+")"),H.select(".nv-y.nv-axis").call(g)),H.select(".nv-zeroLine line").attr("x1",d(0)).attr("x2",d(0)).attr("y1",0).attr("y2",-D),h.dispatch.on("stateChange",function(a){for(var c in a)u[c]=a[c];x.stateChange(u),b.update()}),i.dispatch.on("legendClick",function(a,c){if(a.disabled){switch(I=I.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":e.stacked(!1);break;case"Stacked":e.stacked(!0)}u.stacked=e.stacked(),x.stateChange(u),t=e.stacked(),b.update()}}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),u.stacked=a.stacked,t=a.stacked),b.update()})}),C.renderEnd("multibar horizontal chart immediate"),b}var c,d,e=a.models.multiBarHorizontal(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend().height(30),i=a.models.legend().height(30),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=a.utils.state(),v=null,w=null,x=d3.dispatch("stateChange","changeState","renderEnd"),y=function(){return o?180:0},z=250;u.stacked=!1,e.stacked(t),f.orient("left").tickPadding(5).showMaxMin(!1).tickFormat(function(a){return a}),g.orient("bottom").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var A=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:t}}},B=function(a){return function(b){void 0!==b.stacked&&(t=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},C=a.utils.renderWatch(x,z);return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(a){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=x,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=u,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z),e.duration(z),f.duration(z),g.duration(z)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiChart=function(){"use strict";function b(j){return j.each(function(j){function k(a){var b=2===j[a.seriesIndex].yAxis?z:y;a.value=a.point.x,a.series={value:a.point.y,color:a.point.color},B.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function l(a){var b=2===j[a.seriesIndex].yAxis?z:y;a.point.x=v.x()(a.point),a.point.y=v.y()(a.point),B.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function n(a){var b=2===j[a.data.series].yAxis?z:y;a.value=t.x()(a.data),a.series={value:t.y()(a.data),color:a.color},B.duration(0).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}var C=d3.select(this);a.utils.initSVG(C),b.update=function(){C.transition().call(b)},b.container=this;var D=a.utils.availableWidth(g,C,e),E=a.utils.availableHeight(h,C,e),F=j.filter(function(a){return"line"==a.type&&1==a.yAxis}),G=j.filter(function(a){return"line"==a.type&&2==a.yAxis}),H=j.filter(function(a){return"bar"==a.type&&1==a.yAxis}),I=j.filter(function(a){return"bar"==a.type&&2==a.yAxis}),J=j.filter(function(a){return"area"==a.type&&1==a.yAxis}),K=j.filter(function(a){return"area"==a.type&&2==a.yAxis});if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,C),b;C.selectAll(".nv-noData").remove();var L=j.filter(function(a){return!a.disabled&&1==a.yAxis}).map(function(a){return a.values.map(function(a,b){return{x:a.x,y:a.y}})}),M=j.filter(function(a){return!a.disabled&&2==a.yAxis}).map(function(a){return a.values.map(function(a,b){return{x:a.x,y:a.y}})});o.domain(d3.extent(d3.merge(L.concat(M)),function(a){return a.x})).range([0,D]);var N=C.selectAll("g.wrap.multiChart").data([j]),O=N.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y1 nv-axis"),O.append("g").attr("class","nv-y2 nv-axis"),O.append("g").attr("class","lines1Wrap"),O.append("g").attr("class","lines2Wrap"),O.append("g").attr("class","bars1Wrap"),O.append("g").attr("class","bars2Wrap"),O.append("g").attr("class","stack1Wrap"),O.append("g").attr("class","stack2Wrap"),O.append("g").attr("class","legendWrap");var P=N.select("g"),Q=j.map(function(a,b){return j[b].color||f(a,b)});if(i){var R=A.align()?D/2:D,S=A.align()?R:0;A.width(R),A.color(Q),P.select(".legendWrap").datum(j.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(1==a.yAxis?"":" (right axis)"),a})).call(A),e.top!=A.height()&&(e.top=A.height(),E=a.utils.availableHeight(h,C,e)),P.select(".legendWrap").attr("transform","translate("+S+","+-e.top+")")}r.width(D).height(E).interpolate(m).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"line"==j[b].type})),s.width(D).height(E).interpolate(m).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"line"==j[b].type})),t.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"bar"==j[b].type})),u.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"bar"==j[b].type})),v.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"area"==j[b].type})),w.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"area"==j[b].type})),P.attr("transform","translate("+e.left+","+e.top+")");var T=P.select(".lines1Wrap").datum(F.filter(function(a){return!a.disabled})),U=P.select(".bars1Wrap").datum(H.filter(function(a){return!a.disabled})),V=P.select(".stack1Wrap").datum(J.filter(function(a){return!a.disabled})),W=P.select(".lines2Wrap").datum(G.filter(function(a){return!a.disabled})),X=P.select(".bars2Wrap").datum(I.filter(function(a){return!a.disabled})),Y=P.select(".stack2Wrap").datum(K.filter(function(a){return!a.disabled})),Z=J.length?J.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[],$=K.length?K.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[];p.domain(c||d3.extent(d3.merge(L).concat(Z),function(a){return a.y})).range([0,E]),q.domain(d||d3.extent(d3.merge(M).concat($),function(a){return a.y})).range([0,E]),r.yDomain(p.domain()),t.yDomain(p.domain()),v.yDomain(p.domain()),s.yDomain(q.domain()),u.yDomain(q.domain()),w.yDomain(q.domain()),J.length&&d3.transition(V).call(v),K.length&&d3.transition(Y).call(w),H.length&&d3.transition(U).call(t),I.length&&d3.transition(X).call(u),F.length&&d3.transition(T).call(r),G.length&&d3.transition(W).call(s),x._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-E,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+E+")"),d3.transition(P.select(".nv-x.nv-axis")).call(x),y._ticks(a.utils.calcTicksY(E/36,j)).tickSize(-D,0),d3.transition(P.select(".nv-y1.nv-axis")).call(y),z._ticks(a.utils.calcTicksY(E/36,j)).tickSize(-D,0),d3.transition(P.select(".nv-y2.nv-axis")).call(z),P.select(".nv-y1.nv-axis").classed("nv-disabled",L.length?!1:!0).attr("transform","translate("+o.range()[0]+",0)"),P.select(".nv-y2.nv-axis").classed("nv-disabled",M.length?!1:!0).attr("transform","translate("+o.range()[1]+",0)"),A.dispatch.on("stateChange",function(a){b.update()}),r.dispatch.on("elementMouseover.tooltip",k),s.dispatch.on("elementMouseover.tooltip",k),r.dispatch.on("elementMouseout.tooltip",function(a){B.hidden(!0)}),s.dispatch.on("elementMouseout.tooltip",function(a){B.hidden(!0)}),v.dispatch.on("elementMouseover.tooltip",l),w.dispatch.on("elementMouseover.tooltip",l),v.dispatch.on("elementMouseout.tooltip",function(a){B.hidden(!0)}),w.dispatch.on("elementMouseout.tooltip",function(a){B.hidden(!0)}),t.dispatch.on("elementMouseover.tooltip",n),u.dispatch.on("elementMouseover.tooltip",n),t.dispatch.on("elementMouseout.tooltip",function(a){B.hidden(!0)}),u.dispatch.on("elementMouseout.tooltip",function(a){B.hidden(!0)}),t.dispatch.on("elementMousemove.tooltip",function(a){B.position({top:d3.event.pageY,left:d3.event.pageX})()}),u.dispatch.on("elementMousemove.tooltip",function(a){B.position({top:d3.event.pageY,left:d3.event.pageX})()})}),b}var c,d,e={top:30,right:20,bottom:50,left:60},f=a.utils.defaultColor(),g=null,h=null,i=!0,j=null,k=function(a){return a.x},l=function(a){return a.y},m="monotone",n=!0,o=d3.scale.linear(),p=d3.scale.linear(),q=d3.scale.linear(),r=a.models.line().yScale(p),s=a.models.line().yScale(q),t=a.models.multiBar().stacked(!1).yScale(p),u=a.models.multiBar().stacked(!1).yScale(q),v=a.models.stackedArea().yScale(p),w=a.models.stackedArea().yScale(q),x=a.models.axis().scale(o).orient("bottom").tickPadding(5),y=a.models.axis().scale(p).orient("left"),z=a.models.axis().scale(q).orient("right"),A=a.models.legend().height(30),B=a.models.tooltip(),C=d3.dispatch();return b.dispatch=C,b.lines1=r,b.lines2=s,b.bars1=t,b.bars2=u,b.stack1=v,b.stack2=w,b.xAxis=x,b.yAxis1=y,b.yAxis2=z,b.tooltip=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},showLegend:{get:function(){return i},set:function(a){i=a}},yDomain1:{get:function(){return c},set:function(a){c=a}},yDomain2:{get:function(){return d},set:function(a){d=a}},noData:{get:function(){return j},set:function(a){j=a}},interpolate:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return B.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),B.enabled(!!b)}},tooltipContent:{get:function(){return B.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),B.contentGenerator(b)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return f},set:function(b){f=a.utils.getColor(b)}},x:{get:function(){return k},set:function(a){k=a,r.x(a),s.x(a),t.x(a),u.x(a),v.x(a),w.x(a)}},y:{get:function(){return l},set:function(a){l=a,r.y(a),s.y(a),v.y(a),w.y(a),t.y(a),u.y(a)}},useVoronoi:{get:function(){return n},set:function(a){n=a,r.useVoronoi(a),s.useVoronoi(a),v.useVoronoi(a),w.useVoronoi(a)}}}),a.utils.initOptions(b),b},a.models.ohlcBar=function(){"use strict";function b(y){return y.each(function(b){k=d3.select(this);var y=a.utils.availableWidth(h,k,g),A=a.utils.availableHeight(i,k,g);a.utils.initSVG(k);var B=y/b[0].values.length*.9;l.domain(c||d3.extent(b[0].values.map(n).concat(t))),v?l.range(e||[.5*y/b[0].values.length,y*(b[0].values.length-.5)/b[0].values.length]):l.range(e||[5+B/2,y-B/2-5]),m.domain(d||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(f||[A,0]),l.domain()[0]===l.domain()[1]&&(l.domain()[0]?l.domain([l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]):l.domain([-1,1])),m.domain()[0]===m.domain()[1]&&(m.domain()[0]?m.domain([m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]):m.domain([-1,1]));var C=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([b[0].values]),D=C.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),E=D.append("defs"),F=D.append("g"),G=C.select("g");F.append("g").attr("class","nv-ticks"),C.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:j})}),E.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),C.select("#nv-chart-clip-path-"+j+" rect").attr("width",y).attr("height",A),G.attr("clip-path",w?"url(#nv-chart-clip-path-"+j+")":"");var H=C.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});H.exit().remove(),H.enter().append("path").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}).attr("d",function(a,b){return"m0,0l0,"+(m(p(a,b))-m(r(a,b)))+"l"+-B/2+",0l"+B/2+",0l0,"+(m(s(a,b))-m(p(a,b)))+"l0,"+(m(q(a,b))-m(s(a,b)))+"l"+B/2+",0l"+-B/2+",0z"}).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("fill",function(a,b){return x[0]}).attr("stroke",function(a,b){return x[0]}).attr("x",0).attr("y",function(a,b){return m(Math.max(0,o(a,b)))}).attr("height",function(a,b){return Math.abs(m(o(a,b))-m(0))}),H.attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}),d3.transition(H).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("d",function(a,c){var d=y/b[0].values.length*.9;return"m0,0l0,"+(m(p(a,c))-m(r(a,c)))+"l"+-d/2+",0l"+d/2+",0l0,"+(m(s(a,c))-m(p(a,c)))+"l0,"+(m(q(a,c))-m(s(a,c)))+"l"+d/2+",0l"+-d/2+",0z"})}),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low;
-},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,c){b.clearHighlights(),k.select(".nv-ohlcBar .nv-tick-0-"+a).classed("hover",c)},b.clearHighlights=function(){k.select(".nv-ohlcBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!=a.top?a.top:g.top,g.right=void 0!=a.right?a.right:g.right,g.bottom=void 0!=a.bottom?a.bottom:g.bottom,g.left=void 0!=a.left?a.left:g.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinates=function(){"use strict";function b(p){return p.each(function(b){function p(a){return F(h.map(function(b){if(isNaN(a[b])||isNaN(parseFloat(a[b]))){var c=g[b].domain(),d=g[b].range(),e=c[0]-(c[1]-c[0])/9;if(J.indexOf(b)<0){var h=d3.scale.linear().domain([e,c[1]]).range([x-12,d[1]]);g[b].brush.y(h),J.push(b)}return[f(b),g[b](e)]}return J.length>0?(D.style("display","inline"),E.style("display","inline")):(D.style("display","none"),E.style("display","none")),[f(b),g[b](a[b])]}))}function q(){var a=h.filter(function(a){return!g[a].brush.empty()}),b=a.map(function(a){return g[a].brush.extent()});k=[],a.forEach(function(a,c){k[c]={dimension:a,extent:b[c]}}),l=[],M.style("display",function(c){var d=a.every(function(a,d){return isNaN(c[a])&&b[d][0]==g[a].brush.y().domain()[0]?!0:b[d][0]<=c[a]&&c[a]<=b[d][1]});return d&&l.push(c),d?null:"none"}),o.brush({filters:k,active:l})}function r(a,b){m[a]=this.parentNode.__origin__=f(a),L.attr("visibility","hidden")}function s(a,b){m[a]=Math.min(w,Math.max(0,this.parentNode.__origin__+=d3.event.x)),M.attr("d",p),h.sort(function(a,b){return u(a)-u(b)}),f.domain(h),N.attr("transform",function(a){return"translate("+u(a)+")"})}function t(a,b){delete this.parentNode.__origin__,delete m[a],d3.select(this.parentNode).attr("transform","translate("+f(a)+")"),M.attr("d",p),L.attr("d",p).attr("visibility",null)}function u(a){var b=m[a];return null==b?f(a):b}var v=d3.select(this),w=a.utils.availableWidth(d,v,c),x=a.utils.availableHeight(e,v,c);a.utils.initSVG(v),l=b,f.rangePoints([0,w],1).domain(h);var y={};h.forEach(function(a){var c=d3.extent(b,function(b){return+b[a]});return y[a]=!1,void 0===c[0]&&(y[a]=!0,c[0]=0,c[1]=0),c[0]===c[1]&&(c[0]=c[0]-1,c[1]=c[1]+1),g[a]=d3.scale.linear().domain(c).range([.9*(x-12),0]),g[a].brush=d3.svg.brush().y(g[a]).on("brush",q),"name"!=a});var z=v.selectAll("g.nv-wrap.nv-parallelCoordinates").data([b]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-parallelCoordinates"),B=A.append("g"),C=z.select("g");B.append("g").attr("class","nv-parallelCoordinates background"),B.append("g").attr("class","nv-parallelCoordinates foreground"),B.append("g").attr("class","nv-parallelCoordinates missingValuesline"),z.attr("transform","translate("+c.left+","+c.top+")");var D,E,F=d3.svg.line().interpolate("cardinal").tension(n),G=d3.svg.axis().orient("left"),H=d3.behavior.drag().on("dragstart",r).on("drag",s).on("dragend",t),I=f.range()[1]-f.range()[0],J=[],K=[0+I/2,x-12,w-I/2,x-12];D=z.select(".missingValuesline").selectAll("line").data([K]),D.enter().append("line"),D.exit().remove(),D.attr("x1",function(a){return a[0]}).attr("y1",function(a){return a[1]}).attr("x2",function(a){return a[2]}).attr("y2",function(a){return a[3]}),E=z.select(".missingValuesline").selectAll("text").data(["undefined values"]),E.append("text").data(["undefined values"]),E.enter().append("text"),E.exit().remove(),E.attr("y",x).attr("x",w-92-I/2).text(function(a){return a});var L=z.select(".background").selectAll("path").data(b);L.enter().append("path"),L.exit().remove(),L.attr("d",p);var M=z.select(".foreground").selectAll("path").data(b);M.enter().append("path"),M.exit().remove(),M.attr("d",p).attr("stroke",j),M.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),o.elementMouseover({label:a.name,data:a.data,index:b,pos:[d3.mouse(this.parentNode)[0],d3.mouse(this.parentNode)[1]]})}),M.on("mouseout",function(a,b){d3.select(this).classed("hover",!1),o.elementMouseout({label:a.name,data:a.data,index:b})});var N=C.selectAll(".dimension").data(h),O=N.enter().append("g").attr("class","nv-parallelCoordinates dimension");O.append("g").attr("class","nv-parallelCoordinates nv-axis"),O.append("g").attr("class","nv-parallelCoordinates-brush"),O.append("text").attr("class","nv-parallelCoordinates nv-label"),N.attr("transform",function(a){return"translate("+f(a)+",0)"}),N.exit().remove(),N.select(".nv-label").style("cursor","move").attr("dy","-1em").attr("text-anchor","middle").text(String).on("mouseover",function(a,b){o.elementMouseover({dim:a,pos:[d3.mouse(this.parentNode.parentNode)[0],d3.mouse(this.parentNode.parentNode)[1]]})}).on("mouseout",function(a,b){o.elementMouseout({dim:a})}).call(H),N.select(".nv-axis").each(function(a,b){d3.select(this).call(G.scale(g[a]).tickFormat(d3.format(i[b])))}),N.select(".nv-parallelCoordinates-brush").each(function(a){d3.select(this).call(g[a].brush)}).selectAll("rect").attr("x",-8).attr("width",16)}),b}var c={top:30,right:0,bottom:10,left:0},d=null,e=null,f=d3.scale.ordinal(),g={},h=[],i=[],j=a.utils.defaultColor(),k=[],l=[],m=[],n=1,o=d3.dispatch("brush","elementMouseover","elementMouseout");return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},dimensionNames:{get:function(){return h},set:function(a){h=a}},dimensionFormats:{get:function(){return i},set:function(a){i=a}},lineTension:{get:function(){return n},set:function(a){n=a}},dimensions:{get:function(){return h},set:function(b){a.deprecated("dimensions","use dimensionNames instead"),h=b}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.pie=function(){"use strict";function b(E){return D.reset(),E.each(function(b){function E(a,b){a.endAngle=isNaN(a.endAngle)?0:a.endAngle,a.startAngle=isNaN(a.startAngle)?0:a.startAngle,p||(a.innerRadius=0);var c=d3.interpolate(this._current,a);return this._current=c(0),function(a){return B[b](c(a))}}var F=d-c.left-c.right,G=e-c.top-c.bottom,H=Math.min(F,G)/2,I=[],J=[];if(i=d3.select(this),0===z.length)for(var K=H-H/5,L=y*H,M=0;M<b[0].length;M++)I.push(K),J.push(L);else I=z.map(function(a){return(a.outer-a.outer/5)*H}),J=z.map(function(a){return(a.inner-a.inner/5)*H}),y=d3.min(z.map(function(a){return a.inner-a.inner/5}));a.utils.initSVG(i);var N=i.selectAll(".nv-wrap.nv-pie").data(b),O=N.enter().append("g").attr("class","nvd3 nv-wrap nv-pie nv-chart-"+h),P=O.append("g"),Q=N.select("g"),R=P.append("g").attr("class","nv-pie");P.append("g").attr("class","nv-pieLabels"),N.attr("transform","translate("+c.left+","+c.top+")"),Q.select(".nv-pie").attr("transform","translate("+F/2+","+G/2+")"),Q.select(".nv-pieLabels").attr("transform","translate("+F/2+","+G/2+")"),i.on("click",function(a,b){A.chartClick({data:a,index:b,pos:d3.event,id:h})}),B=[],C=[];for(var M=0;M<b[0].length;M++){var S=d3.svg.arc().outerRadius(I[M]),T=d3.svg.arc().outerRadius(I[M]+5);u!==!1&&(S.startAngle(u),T.startAngle(u)),w!==!1&&(S.endAngle(w),T.endAngle(w)),p&&(S.innerRadius(J[M]),T.innerRadius(J[M])),S.cornerRadius&&x&&(S.cornerRadius(x),T.cornerRadius(x)),B.push(S),C.push(T)}var U=d3.layout.pie().sort(null).value(function(a){return a.disabled?0:g(a)});U.padAngle&&v&&U.padAngle(v),p&&q&&(R.append("text").attr("class","nv-pie-title"),N.select(".nv-pie-title").style("text-anchor","middle").text(function(a){return q}).style("font-size",Math.min(F,G)*y*2/(q.length+2)+"px").attr("dy","0.35em").attr("transform",function(a,b){return"translate(0, "+s+")"}));var V=N.select(".nv-pie").selectAll(".nv-slice").data(U),W=N.select(".nv-pieLabels").selectAll(".nv-label").data(U);V.exit().remove(),W.exit().remove();var X=V.enter().append("g");X.attr("class","nv-slice"),X.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),r&&d3.select(this).select("path").transition().duration(70).attr("d",C[b]),A.elementMouseover({data:a.data,index:b,color:d3.select(this).style("fill")})}),X.on("mouseout",function(a,b){d3.select(this).classed("hover",!1),r&&d3.select(this).select("path").transition().duration(50).attr("d",B[b]),A.elementMouseout({data:a.data,index:b})}),X.on("mousemove",function(a,b){A.elementMousemove({data:a.data,index:b})}),X.on("click",function(a,b){A.elementClick({data:a.data,index:b,color:d3.select(this).style("fill")})}),X.on("dblclick",function(a,b){A.elementDblClick({data:a.data,index:b,color:d3.select(this).style("fill")})}),V.attr("fill",function(a,b){return j(a.data,b)}),V.attr("stroke",function(a,b){return j(a.data,b)});X.append("path").each(function(a){this._current=a});if(V.select("path").transition().attr("d",function(a,b){return B[b](a)}).attrTween("d",E),l){for(var Y=[],M=0;M<b[0].length;M++)Y.push(B[M]),m?p&&(Y[M]=d3.svg.arc().outerRadius(B[M].outerRadius()),u!==!1&&Y[M].startAngle(u),w!==!1&&Y[M].endAngle(w)):p||Y[M].innerRadius(0);W.enter().append("g").classed("nv-label",!0).each(function(a,b){var c=d3.select(this);c.attr("transform",function(a,b){if(t){a.outerRadius=I[b]+10,a.innerRadius=I[b]+15;var c=(a.startAngle+a.endAngle)/2*(180/Math.PI);return(a.startAngle+a.endAngle)/2<Math.PI?c-=90:c+=90,"translate("+Y[b].centroid(a)+") rotate("+c+")"}return a.outerRadius=H+10,a.innerRadius=H+15,"translate("+Y[b].centroid(a)+")"}),c.append("rect").style("stroke","#fff").style("fill","#fff").attr("rx",3).attr("ry",3),c.append("text").style("text-anchor",t?(a.startAngle+a.endAngle)/2<Math.PI?"start":"end":"middle").style("fill","#000")});var Z={},$=14,_=140,aa=function(a){return Math.floor(a[0]/_)*_+","+Math.floor(a[1]/$)*$};W.watchTransition(D,"pie labels").attr("transform",function(a,b){if(t){a.outerRadius=I[b]+10,a.innerRadius=I[b]+15;var c=(a.startAngle+a.endAngle)/2*(180/Math.PI);return(a.startAngle+a.endAngle)/2<Math.PI?c-=90:c+=90,"translate("+Y[b].centroid(a)+") rotate("+c+")"}a.outerRadius=H+10,a.innerRadius=H+15;var d=Y[b].centroid(a);if(a.value){var e=aa(d);Z[e]&&(d[1]-=$),Z[aa(d)]=!0}return"translate("+d+")"}),W.select(".nv-label text").style("text-anchor",function(a,b){return t?(a.startAngle+a.endAngle)/2<Math.PI?"start":"end":"middle"}).text(function(a,b){var c=(a.endAngle-a.startAngle)/(2*Math.PI),d="";if(!a.value||o>c)return"";if("function"==typeof n)d=n(a,b,{key:f(a.data),value:g(a.data),percent:k(c)});else switch(n){case"key":d=f(a.data);break;case"value":d=k(g(a.data));break;case"percent":d=d3.format("%")(c)}return d})}}),D.renderEnd("pie immediate"),b}var c={top:0,right:0,bottom:0,left:0},d=500,e=500,f=function(a){return a.x},g=function(a){return a.y},h=Math.floor(1e4*Math.random()),i=null,j=a.utils.defaultColor(),k=d3.format(",.2f"),l=!0,m=!1,n="key",o=.02,p=!1,q=!1,r=!0,s=0,t=!1,u=!1,v=!1,w=!1,x=0,y=.5,z=[],A=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),B=[],C=[],D=a.utils.renderWatch(A);return b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{arcsRadius:{get:function(){return z},set:function(a){z=a}},width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},showLabels:{get:function(){return l},set:function(a){l=a}},title:{get:function(){return q},set:function(a){q=a}},titleOffset:{get:function(){return s},set:function(a){s=a}},labelThreshold:{get:function(){return o},set:function(a){o=a}},valueFormat:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return h},set:function(a){h=a}},endAngle:{get:function(){return w},set:function(a){w=a}},startAngle:{get:function(){return u},set:function(a){u=a}},padAngle:{get:function(){return v},set:function(a){v=a}},cornerRadius:{get:function(){return x},set:function(a){x=a}},donutRatio:{get:function(){return y},set:function(a){y=a}},labelsOutside:{get:function(){return m},set:function(a){m=a}},labelSunbeamLayout:{get:function(){return t},set:function(a){t=a}},donut:{get:function(){return p},set:function(a){p=a}},growOnHover:{get:function(){return r},set:function(a){r=a}},pieLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("pieLabelsOutside","use labelsOutside instead")}},donutLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("donutLabelsOutside","use labelsOutside instead")}},labelFormat:{get:function(){return k},set:function(b){k=b,a.deprecated("labelFormat","use valueFormat instead")}},margin:{get:function(){return c},set:function(a){c.top="undefined"!=typeof a.top?a.top:c.top,c.right="undefined"!=typeof a.right?a.right:c.right,c.bottom="undefined"!=typeof a.bottom?a.bottom:c.bottom,c.left="undefined"!=typeof a.left?a.left:c.left}},y:{get:function(){return g},set:function(a){g=d3.functor(a)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},labelType:{get:function(){return n},set:function(a){n=a||"key"}}}),a.utils.initOptions(b),b},a.models.pieChart=function(){"use strict";function b(e){return q.reset(),q.models(c),e.each(function(e){var k=d3.select(this);a.utils.initSVG(k);var n=a.utils.availableWidth(g,k,f),o=a.utils.availableHeight(h,k,f);if(b.update=function(){k.transition().call(b)},b.container=this,l.setter(s(e),b.update).getter(r(e)).update(),l.disabled=e.map(function(a){return!!a.disabled}),!m){var q;m={};for(q in l)l[q]instanceof Array?m[q]=l[q].slice(0):m[q]=l[q]}if(!e||!e.length)return a.utils.noData(b,k),b;k.selectAll(".nv-noData").remove();var t=k.selectAll("g.nv-wrap.nv-pieChart").data([e]),u=t.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),v=t.select("g");if(u.append("g").attr("class","nv-pieWrap"),u.append("g").attr("class","nv-legendWrap"),i)if("top"===j)d.width(n).key(c.x()),t.select(".nv-legendWrap").datum(e).call(d),f.top!=d.height()&&(f.top=d.height(),o=a.utils.availableHeight(h,k,f)),t.select(".nv-legendWrap").attr("transform","translate(0,"+-f.top+")");else if("right"===j){var w=a.models.legend().width();w>n/2&&(w=n/2),d.height(o).key(c.x()),d.width(w),n-=d.width(),t.select(".nv-legendWrap").datum(e).call(d).attr("transform","translate("+n+",0)")}t.attr("transform","translate("+f.left+","+f.top+")"),c.width(n).height(o);var x=v.select(".nv-pieWrap").datum([e]);d3.transition(x).call(c),d.dispatch.on("stateChange",function(a){for(var c in a)l[c]=a[c];p.stateChange(l),b.update()}),p.on("changeState",function(a){"undefined"!=typeof a.disabled&&(e.forEach(function(b,c){b.disabled=a.disabled[c]}),l.disabled=a.disabled),b.update()})}),q.renderEnd("pieChart immediate"),b}var c=a.models.pie(),d=a.models.legend(),e=a.models.tooltip(),f={top:30,right:20,bottom:20,left:20},g=null,h=null,i=!0,j="top",k=a.utils.defaultColor(),l=a.utils.state(),m=null,n=null,o=250,p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd");e.headerEnabled(!1).duration(0).valueFormatter(function(a,b){return c.valueFormat()(a,b)});var q=a.utils.renderWatch(p),r=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},s=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},e.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(a){e.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(a){e.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.legend=d,b.dispatch=p,b.pie=c,b.tooltip=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return i},set:function(a){i=a}},legendPosition:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return e.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),e.enabled(!!b)}},tooltipContent:{get:function(){return e.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),e.contentGenerator(b)}},color:{get:function(){return k},set:function(a){k=a,d.color(k),c.color(k)}},duration:{get:function(){return o},set:function(a){o=a,q.reset(o)}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.scatter=function(){"use strict";function b(N){return P.reset(),N.each(function(b){function N(){if(O=!1,!w)return!1;if(M===!0){var a=d3.merge(b.map(function(a,b){return a.values.map(function(a,c){var d=p(a,c),e=q(a,c);return[m(d)+1e-4*Math.random(),n(e)+1e-4*Math.random(),b,c,a]}).filter(function(a,b){return x(a[4],b)})}));if(0==a.length)return!1;a.length<3&&(a.push([m.range()[0]-20,n.range()[0]-20,null,null]),a.push([m.range()[1]+20,n.range()[1]+20,null,null]),a.push([m.range()[0]-20,n.range()[0]+20,null,null]),a.push([m.range()[1]+20,n.range()[1]-20,null,null]));var c=d3.geom.polygon([[-10,-10],[-10,i+10],[h+10,i+10],[h+10,-10]]),d=d3.geom.voronoi(a).map(function(b,d){return{data:c.clip(b),series:a[d][2],point:a[d][3]}});U.select(".nv-point-paths").selectAll("path").remove();var e=U.select(".nv-point-paths").selectAll("path").data(d),f=e.enter().append("svg:path").attr("d",function(a){return a&&a.data&&0!==a.data.length?"M"+a.data.join(",")+"Z":"M 0 0"}).attr("id",function(a,b){return"nv-path-"+b}).attr("clip-path",function(a,b){return"url(#nv-clip-"+b+")"});C&&f.style("fill",d3.rgb(230,230,230)).style("fill-opacity",.4).style("stroke-opacity",1).style("stroke",d3.rgb(200,200,200)),B&&(U.select(".nv-point-clips").selectAll("clipPath").remove(),U.select(".nv-point-clips").selectAll("clipPath").data(a).enter().append("svg:clipPath").attr("id",function(a,b){return"nv-clip-"+b}).append("svg:circle").attr("cx",function(a){return a[0]}).attr("cy",function(a){return a[1]}).attr("r",D));var k=function(a,c){if(O)return 0;var d=b[a.series];if(void 0!==d){var e=d.values[a.point];e.color=j(d,a.series),e.x=p(e),e.y=q(e);var f=l.node().getBoundingClientRect(),h=window.pageYOffset||document.documentElement.scrollTop,i=window.pageXOffset||document.documentElement.scrollLeft,k={left:m(p(e,a.point))+f.left+i+g.left+10,top:n(q(e,a.point))+f.top+h+g.top+10};c({point:e,series:d,pos:k,seriesIndex:a.series,pointIndex:a.point})}};e.on("click",function(a){k(a,L.elementClick)}).on("dblclick",function(a){k(a,L.elementDblClick)}).on("mouseover",function(a){k(a,L.elementMouseover)}).on("mouseout",function(a,b){k(a,L.elementMouseout)})}else U.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("dblclick",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementDblClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("mouseover",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseover({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c,color:j(a,c)})}).on("mouseout",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseout({point:e,series:d,seriesIndex:a.series,pointIndex:c,color:j(a,c)})})}l=d3.select(this);var R=a.utils.availableWidth(h,l,g),S=a.utils.availableHeight(i,l,g);a.utils.initSVG(l),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var T=E&&F&&I?[]:d3.merge(b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),size:r(a,b)}})}));m.domain(E||d3.extent(T.map(function(a){return a.x}).concat(t))),y&&b[0]?m.range(G||[(R*z+R)/(2*b[0].values.length),R-R*(1+z)/(2*b[0].values.length)]):m.range(G||[0,R]),n.domain(F||d3.extent(T.map(function(a){return a.y}).concat(u))).range(H||[S,0]),o.domain(I||d3.extent(T.map(function(a){return a.size}).concat(v))).range(J||Q),K=m.domain()[0]===m.domain()[1]||n.domain()[0]===n.domain()[1],m.domain()[0]===m.domain()[1]&&(m.domain()[0]?m.domain([m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]):m.domain([-1,1])),n.domain()[0]===n.domain()[1]&&(n.domain()[0]?n.domain([n.domain()[0]-.01*n.domain()[0],n.domain()[1]+.01*n.domain()[1]]):n.domain([-1,1])),isNaN(m.domain()[0])&&m.domain([-1,1]),isNaN(n.domain()[0])&&n.domain([-1,1]),c=c||m,d=d||n,e=e||o;var U=l.selectAll("g.nv-wrap.nv-scatter").data([b]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+k),W=V.append("defs"),X=V.append("g"),Y=U.select("g");U.classed("nv-single-point",K),X.append("g").attr("class","nv-groups"),X.append("g").attr("class","nv-point-paths"),V.append("g").attr("class","nv-point-clips"),U.attr("transform","translate("+g.left+","+g.top+")"),W.append("clipPath").attr("id","nv-edge-clip-"+k).append("rect"),U.select("#nv-edge-clip-"+k+" rect").attr("width",R).attr("height",S>0?S:0),Y.attr("clip-path",A?"url(#nv-edge-clip-"+k+")":""),O=!0;var Z=U.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});Z.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),Z.exit().remove(),Z.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),Z.watchTransition(P,"scatter: groups").style("fill",function(a,b){return j(a,b)}).style("stroke",function(a,b){return j(a,b)}).style("stroke-opacity",1).style("fill-opacity",.5);var $=Z.selectAll("path.nv-point").data(function(a){return a.values.map(function(a,b){return[a,b]}).filter(function(a,b){return x(a[0],b)})});$.enter().append("path").style("fill",function(a){return a.color}).style("stroke",function(a){return a.color}).attr("transform",function(a){return"translate("+c(p(a[0],a[1]))+","+d(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),$.exit().remove(),Z.exit().selectAll("path.nv-point").watchTransition(P,"scatter exit").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).remove(),$.each(function(a){d3.select(this).classed("nv-point",!0).classed("nv-point-"+a[1],!0).classed("nv-noninteractive",!w).classed("hover",!1)}),$.watchTransition(P,"scatter points").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),clearTimeout(f),f=setTimeout(N,300),c=m.copy(),d=n.copy(),e=o.copy()}),P.renderEnd("scatter immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=a.utils.defaultColor(),k=Math.floor(1e5*Math.random()),l=null,m=d3.scale.linear(),n=d3.scale.linear(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=function(a){return a.size||1},s=function(a){return a.shape||"circle"},t=[],u=[],v=[],w=!0,x=function(a){return!a.notActive},y=!1,z=.1,A=!1,B=!0,C=!1,D=function(){return 25},E=null,F=null,G=null,H=null,I=null,J=null,K=!1,L=d3.dispatch("elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),M=!0,N=250,O=!1,P=a.utils.renderWatch(L,N),Q=[16,256];return b.dispatch=L,b.options=a.utils.optionsFunc.bind(b),b._calls=new function(){this.clearHighlights=function(){return a.dom.write(function(){l.selectAll(".nv-point.hover").classed("hover",!1)}),null},this.highlightPoint=function(b,c,d){a.dom.write(function(){l.select(" .nv-series-"+b+" .nv-point-"+c).classed("hover",d)})}},L.on("elementMouseover.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!0)}),L.on("elementMouseout.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!1)}),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},pointScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return E},set:function(a){E=a}},yDomain:{get:function(){return F},set:function(a){F=a}},pointDomain:{get:function(){return I},set:function(a){I=a}},xRange:{get:function(){return G},set:function(a){G=a}},yRange:{get:function(){return H},set:function(a){H=a}},pointRange:{get:function(){return J},set:function(a){J=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},forcePoint:{get:function(){return v},set:function(a){v=a}},interactive:{get:function(){return w},set:function(a){w=a}},pointActive:{get:function(){return x},set:function(a){x=a}},padDataOuter:{get:function(){return z},set:function(a){z=a}},padData:{get:function(){return y},set:function(a){y=a}},clipEdge:{get:function(){return A},set:function(a){A=a}},clipVoronoi:{get:function(){return B},set:function(a){B=a}},clipRadius:{get:function(){return D},set:function(a){D=a}},showVoronoi:{get:function(){return C},set:function(a){C=a}},id:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return p},set:function(a){p=d3.functor(a)}},y:{get:function(){return q},set:function(a){q=d3.functor(a)}},pointSize:{get:function(){return r},set:function(a){r=d3.functor(a)}},pointShape:{get:function(){return s},set:function(a){s=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},duration:{get:function(){return N},set:function(a){N=a,P.reset(N)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},useVoronoi:{get:function(){return M},set:function(a){M=a,M===!1&&(B=!1)}}}),a.utils.initOptions(b),b},a.models.scatterChart=function(){"use strict";function b(z){return D.reset(),D.models(c),t&&D.models(d),u&&D.models(e),q&&D.models(g),r&&D.models(h),z.each(function(z){m=d3.select(this),a.utils.initSVG(m);var G=a.utils.availableWidth(k,m,j),H=a.utils.availableHeight(l,m,j);if(b.update=function(){0===A?m.call(b):m.transition().duration(A).call(b)},b.container=this,w.setter(F(z),b.update).getter(E(z)).update(),w.disabled=z.map(function(a){return!!a.disabled}),!x){var I;x={};for(I in w)w[I]instanceof Array?x[I]=w[I].slice(0):x[I]=w[I]}if(!(z&&z.length&&z.filter(function(a){return a.values.length}).length))return a.utils.noData(b,m),D.renderEnd("scatter immediate"),b;m.selectAll(".nv-noData").remove(),o=c.xScale(),p=c.yScale();var J=m.selectAll("g.nv-wrap.nv-scatterChart").data([z]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+c.id()),L=K.append("g"),M=J.select("g");if(L.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),L.append("g").attr("class","nv-x nv-axis"),L.append("g").attr("class","nv-y nv-axis"),L.append("g").attr("class","nv-scatterWrap"),L.append("g").attr("class","nv-regressionLinesWrap"),L.append("g").attr("class","nv-distWrap"),L.append("g").attr("class","nv-legendWrap"),v&&M.select(".nv-y.nv-axis").attr("transform","translate("+G+",0)"),s){var N=G;f.width(N),J.select(".nv-legendWrap").datum(z).call(f),j.top!=f.height()&&(j.top=f.height(),H=a.utils.availableHeight(l,m,j)),J.select(".nv-legendWrap").attr("transform","translate(0,"+-j.top+")")}J.attr("transform","translate("+j.left+","+j.top+")"),c.width(G).height(H).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),J.select(".nv-scatterWrap").datum(z.filter(function(a){return!a.disabled})).call(c),J.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+c.id()+")");var O=J.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(a){return a});O.enter().append("g").attr("class","nv-regLines");var P=O.selectAll(".nv-regLine").data(function(a){return[a]});P.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0),P.filter(function(a){return a.intercept&&a.slope}).watchTransition(D,"scatterPlusLineChart: regline").attr("x1",o.range()[0]).attr("x2",o.range()[1]).attr("y1",function(a,b){return p(o.domain()[0]*a.slope+a.intercept)}).attr("y2",function(a,b){return p(o.domain()[1]*a.slope+a.intercept)}).style("stroke",function(a,b,c){return n(a,c)}).style("stroke-opacity",function(a,b){return a.disabled||"undefined"==typeof a.slope||"undefined"==typeof a.intercept?0:1}),t&&(d.scale(o)._ticks(a.utils.calcTicksX(G/100,z)).tickSize(-H,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(d)),u&&(e.scale(p)._ticks(a.utils.calcTicksY(H/36,z)).tickSize(-G,0),M.select(".nv-y.nv-axis").call(e)),q&&(g.getData(c.x()).scale(o).width(G).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),M.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(z.filter(function(a){return!a.disabled})).call(g)),r&&(h.getData(c.y()).scale(p).width(H).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),M.select(".nv-distributionY").attr("transform","translate("+(v?G:-h.size())+",0)").datum(z.filter(function(a){return!a.disabled})).call(h)),f.dispatch.on("stateChange",function(a){for(var c in a)w[c]=a[c];y.stateChange(w),b.update()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&(z.forEach(function(b,c){b.disabled=a.disabled[c]}),w.disabled=a.disabled),b.update()}),c.dispatch.on("elementMouseout.tooltip",function(a){i.hidden(!0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",h.size())}),c.dispatch.on("elementMouseover.tooltip",function(a){m.select(".nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",a.pos.top-H-j.top),m.select(".nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.pos.left+g.size()-j.left),i.position(a.pos).data(a).hidden(!1);
-}),B=o.copy(),C=p.copy()}),D.renderEnd("scatter with line immediate"),b}var c=a.models.scatter(),d=a.models.axis(),e=a.models.axis(),f=a.models.legend(),g=a.models.distribution(),h=a.models.distribution(),i=a.models.tooltip(),j={top:30,right:20,bottom:50,left:75},k=null,l=null,m=null,n=a.utils.defaultColor(),o=c.xScale(),p=c.yScale(),q=!1,r=!1,s=!0,t=!0,u=!0,v=!1,w=a.utils.state(),x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=null,A=250;c.xScale(o).yScale(p),d.orient("bottom").tickPadding(10),e.orient(v?"right":"left").tickPadding(10),g.axis("x"),h.axis("y"),i.headerFormatter(function(a,b){return d.tickFormat()(a,b)}).valueFormatter(function(a,b){return e.tickFormat()(a,b)});var B,C,D=a.utils.renderWatch(y,A),E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return b.dispatch=y,b.scatter=c,b.legend=f,b.xAxis=d,b.yAxis=e,b.distX=g,b.distY=h,b.tooltip=i,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},container:{get:function(){return m},set:function(a){m=a}},showDistX:{get:function(){return q},set:function(a){q=a}},showDistY:{get:function(){return r},set:function(a){r=a}},showLegend:{get:function(){return s},set:function(a){s=a}},showXAxis:{get:function(){return t},set:function(a){t=a}},showYAxis:{get:function(){return u},set:function(a){u=a}},defaultState:{get:function(){return x},set:function(a){x=a}},noData:{get:function(){return z},set:function(a){z=a}},duration:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return i.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),i.enabled(!!b)}},tooltipContent:{get:function(){return i.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),i.contentGenerator(b)}},tooltipXContent:{get:function(){return i.contentGenerator()},set:function(b){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},tooltipYContent:{get:function(){return i.contentGenerator()},set:function(b){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},rightAlignYAxis:{get:function(){return v},set:function(a){v=a,e.orient(a?"right":"left")}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),f.color(n),g.color(n),h.color(n)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.sparkline=function(){"use strict";function b(k){return k.each(function(b){var k=h-g.left-g.right,q=i-g.top-g.bottom;j=d3.select(this),a.utils.initSVG(j),l.domain(c||d3.extent(b,n)).range(e||[0,k]),m.domain(d||d3.extent(b,o)).range(f||[q,0]);var r=j.selectAll("g.nv-wrap.nv-sparkline").data([b]),s=r.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline");s.append("g"),r.select("g");r.attr("transform","translate("+g.left+","+g.top+")");var t=r.selectAll("path").data(function(a){return[a]});t.enter().append("path"),t.exit().remove(),t.style("stroke",function(a,b){return a.color||p(a,b)}).attr("d",d3.svg.line().x(function(a,b){return l(n(a,b))}).y(function(a,b){return m(o(a,b))}));var u=r.selectAll("circle.nv-point").data(function(a){function b(b){if(-1!=b){var c=a[b];return c.pointIndex=b,c}return null}var c=a.map(function(a,b){return o(a,b)}),d=b(c.lastIndexOf(m.domain()[1])),e=b(c.indexOf(m.domain()[0])),f=b(c.length-1);return[e,d,f].filter(function(a){return null!=a})});u.enter().append("circle"),u.exit().remove(),u.attr("cx",function(a,b){return l(n(a,a.pointIndex))}).attr("cy",function(a,b){return m(o(a,a.pointIndex))}).attr("r",2).attr("class",function(a,b){return n(a,a.pointIndex)==l.domain()[1]?"nv-point nv-currentValue":o(a,a.pointIndex)==m.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),b}var c,d,e,f,g={top:2,right:0,bottom:2,left:0},h=400,i=32,j=null,k=!0,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=a.utils.getColor(["#000"]);return b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},animate:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return n},set:function(a){n=d3.functor(a)}},y:{get:function(){return o},set:function(a){o=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return p},set:function(b){p=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sparklinePlus=function(){"use strict";function b(p){return p.each(function(q){function r(){if(!j){var a=A.selectAll(".nv-hoverValue").data(i),b=a.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);a.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),a.attr("transform",function(a){return"translate("+c(e.x()(q[a],a))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1),i.length&&(b.append("line").attr("x1",0).attr("y1",-f.top).attr("x2",0).attr("y2",v),b.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-f.top).attr("text-anchor","end").attr("dy",".9em"),A.select(".nv-hoverValue .nv-xValue").text(k(e.x()(q[i[0]],i[0]))),b.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-f.top).attr("text-anchor","start").attr("dy",".9em"),A.select(".nv-hoverValue .nv-yValue").text(l(e.y()(q[i[0]],i[0]))))}}function s(){function a(a,b){for(var c=Math.abs(e.x()(a[0],0)-b),d=0,f=0;f<a.length;f++)Math.abs(e.x()(a[f],f)-b)<c&&(c=Math.abs(e.x()(a[f],f)-b),d=f);return d}if(!j){var b=d3.mouse(this)[0]-f.left;i=[a(q,Math.round(c.invert(b)))],r()}}var t=d3.select(this);a.utils.initSVG(t);var u=a.utils.availableWidth(g,t,f),v=a.utils.availableHeight(h,t,f);if(b.update=function(){b(p)},b.container=this,!q||!q.length)return a.utils.noData(b,t),b;t.selectAll(".nv-noData").remove();var w=e.y()(q[q.length-1],q.length-1);c=e.xScale(),d=e.yScale();var x=t.selectAll("g.nv-wrap.nv-sparklineplus").data([q]),y=x.enter().append("g").attr("class","nvd3 nv-wrap nv-sparklineplus"),z=y.append("g"),A=x.select("g");z.append("g").attr("class","nv-sparklineWrap"),z.append("g").attr("class","nv-valueWrap"),z.append("g").attr("class","nv-hoverArea"),x.attr("transform","translate("+f.left+","+f.top+")");var B=A.select(".nv-sparklineWrap");if(e.width(u).height(v),B.call(e),m){var C=A.select(".nv-valueWrap"),D=C.selectAll(".nv-currentValue").data([w]);D.enter().append("text").attr("class","nv-currentValue").attr("dx",o?-8:8).attr("dy",".9em").style("text-anchor",o?"end":"start"),D.attr("x",u+(o?f.right:0)).attr("y",n?function(a){return d(a)}:0).style("fill",e.color()(q[q.length-1],q.length-1)).text(l(w))}z.select(".nv-hoverArea").append("rect").on("mousemove",s).on("click",function(){j=!j}).on("mouseout",function(){i=[],r()}),A.select(".nv-hoverArea rect").attr("transform",function(a){return"translate("+-f.left+","+-f.top+")"}).attr("width",u+f.left+f.right).attr("height",v+f.top)}),b}var c,d,e=a.models.sparkline(),f={top:15,right:100,bottom:10,left:50},g=null,h=null,i=[],j=!1,k=d3.format(",r"),l=d3.format(",.2f"),m=!0,n=!0,o=!1,p=null;return b.sparkline=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},xTickFormat:{get:function(){return k},set:function(a){k=a}},yTickFormat:{get:function(){return l},set:function(a){l=a}},showLastValue:{get:function(){return m},set:function(a){m=a}},alignValue:{get:function(){return n},set:function(a){n=a}},rightAlignValue:{get:function(){return o},set:function(a){o=a}},noData:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.stackedArea=function(){"use strict";function b(m){return u.reset(),u.models(r),m.each(function(m){var s=f-e.left-e.right,v=g-e.top-e.bottom;j=d3.select(this),a.utils.initSVG(j),c=r.xScale(),d=r.yScale();var w=m;m.forEach(function(a,b){a.seriesIndex=b,a.values=a.values.map(function(a,c){return a.index=c,a.seriesIndex=b,a})});var x=m.filter(function(a){return!a.disabled});m=d3.layout.stack().order(o).offset(n).values(function(a){return a.values}).x(k).y(l).out(function(a,b,c){a.display={y:c,y0:b}})(x);var y=j.selectAll("g.nv-wrap.nv-stackedarea").data([m]),z=y.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedarea"),A=z.append("defs"),B=z.append("g"),C=y.select("g");B.append("g").attr("class","nv-areaWrap"),B.append("g").attr("class","nv-scatterWrap"),y.attr("transform","translate("+e.left+","+e.top+")"),0==r.forceY().length&&r.forceY().push(0),r.width(s).height(v).x(k).y(function(a){return a.display.y+a.display.y0}).forceY([0]).color(m.map(function(a,b){return a.color||h(a,a.seriesIndex)}));var D=C.select(".nv-scatterWrap").datum(m);D.call(r),A.append("clipPath").attr("id","nv-edge-clip-"+i).append("rect"),y.select("#nv-edge-clip-"+i+" rect").attr("width",s).attr("height",v),C.attr("clip-path",q?"url(#nv-edge-clip-"+i+")":"");var E=d3.svg.area().x(function(a,b){return c(k(a,b))}).y0(function(a){return d(a.display.y0)}).y1(function(a){return d(a.display.y+a.display.y0)}).interpolate(p),F=d3.svg.area().x(function(a,b){return c(k(a,b))}).y0(function(a){return d(a.display.y0)}).y1(function(a){return d(a.display.y0)}),G=C.select(".nv-areaWrap").selectAll("path.nv-area").data(function(a){return a});G.enter().append("path").attr("class",function(a,b){return"nv-area nv-area-"+b}).attr("d",function(a,b){return F(a.values,a.seriesIndex)}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),t.areaMouseover({point:a,series:a.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:a.seriesIndex})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),t.areaMouseout({point:a,series:a.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:a.seriesIndex})}).on("click",function(a,b){d3.select(this).classed("hover",!1),t.areaClick({point:a,series:a.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:a.seriesIndex})}),G.exit().remove(),G.style("fill",function(a,b){return a.color||h(a,a.seriesIndex)}).style("stroke",function(a,b){return a.color||h(a,a.seriesIndex)}),G.watchTransition(u,"stackedArea path").attr("d",function(a,b){return E(a.values,b)}),r.dispatch.on("elementMouseover.area",function(a){C.select(".nv-chart-"+i+" .nv-area-"+a.seriesIndex).classed("hover",!0)}),r.dispatch.on("elementMouseout.area",function(a){C.select(".nv-chart-"+i+" .nv-area-"+a.seriesIndex).classed("hover",!1)}),b.d3_stackedOffset_stackPercent=function(a){var b,c,d,e=a.length,f=a[0].length,g=[];for(c=0;f>c;++c){for(b=0,d=0;b<w.length;b++)d+=l(w[b].values[c]);if(d)for(b=0;e>b;b++)a[b][c][1]/=d;else for(b=0;e>b;b++)a[b][c][1]=0}for(c=0;f>c;++c)g[c]=0;return g}}),u.renderEnd("stackedArea immediate"),b}var c,d,e={top:0,right:0,bottom:0,left:0},f=960,g=500,h=a.utils.defaultColor(),i=Math.floor(1e5*Math.random()),j=null,k=function(a){return a.x},l=function(a){return a.y},m="stack",n="zero",o="default",p="linear",q=!1,r=a.models.scatter(),s=250,t=d3.dispatch("areaClick","areaMouseover","areaMouseout","renderEnd","elementClick","elementMouseover","elementMouseout");r.pointSize(2.2).pointDomain([2.2,2.2]);var u=a.utils.renderWatch(t,s);return b.dispatch=t,b.scatter=r,r.dispatch.on("elementClick",function(){t.elementClick.apply(this,arguments)}),r.dispatch.on("elementMouseover",function(){t.elementMouseover.apply(this,arguments)}),r.dispatch.on("elementMouseout",function(){t.elementMouseout.apply(this,arguments)}),b.interpolate=function(a){return arguments.length?(p=a,b):p},b.duration=function(a){return arguments.length?(s=a,u.reset(s),r.duration(s),b):s},b.dispatch=t,b.scatter=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return f},set:function(a){f=a}},height:{get:function(){return g},set:function(a){g=a}},clipEdge:{get:function(){return q},set:function(a){q=a}},offset:{get:function(){return n},set:function(a){n=a}},order:{get:function(){return o},set:function(a){o=a}},interpolate:{get:function(){return p},set:function(a){p=a}},x:{get:function(){return k},set:function(a){k=d3.functor(a)}},y:{get:function(){return l},set:function(a){l=d3.functor(a)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}},style:{get:function(){return m},set:function(a){switch(m=a){case"stack":b.offset("zero"),b.order("default");break;case"stream":b.offset("wiggle"),b.order("inside-out");break;case"stream-center":b.offset("silhouette"),b.order("inside-out");break;case"expand":b.offset("expand"),b.order("default");break;case"stack_percent":b.offset(b.d3_stackedOffset_stackPercent),b.order("default")}}},duration:{get:function(){return s},set:function(a){s=a,u.reset(s),r.duration(s)}}}),a.utils.inheritOptions(b,r),a.utils.initOptions(b),b},a.models.stackedAreaChart=function(){"use strict";function b(k){return F.reset(),F.models(e),r&&F.models(f),s&&F.models(g),k.each(function(k){var x=d3.select(this),F=this;a.utils.initSVG(x);var K=a.utils.availableWidth(m,x,l),L=a.utils.availableHeight(n,x,l);if(b.update=function(){x.transition().duration(C).call(b)},b.container=this,v.setter(I(k),b.update).getter(H(k)).update(),v.disabled=k.map(function(a){return!!a.disabled}),!w){var M;w={};for(M in v)v[M]instanceof Array?w[M]=v[M].slice(0):w[M]=v[M]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(b,x),b;x.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var N=x.selectAll("g.nv-wrap.nv-stackedAreaChart").data([k]),O=N.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),P=N.select("g");if(O.append("rect").style("opacity",0),O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-stackedWrap"),O.append("g").attr("class","nv-legendWrap"),O.append("g").attr("class","nv-controlsWrap"),O.append("g").attr("class","nv-interactive"),P.select("rect").attr("width",K).attr("height",L),q){var Q=p?K-z:K;h.width(Q),P.select(".nv-legendWrap").datum(k).call(h),l.top!=h.height()&&(l.top=h.height(),L=a.utils.availableHeight(n,x,l)),P.select(".nv-legendWrap").attr("transform","translate("+(K-Q)+","+-l.top+")")}if(p){var R=[{key:B.stacked||"Stacked",metaKey:"Stacked",disabled:"stack"!=e.style(),style:"stack"},{key:B.stream||"Stream",metaKey:"Stream",disabled:"stream"!=e.style(),style:"stream"},{key:B.expanded||"Expanded",metaKey:"Expanded",disabled:"expand"!=e.style(),style:"expand"},{key:B.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:"stack_percent"!=e.style(),style:"stack_percent"}];z=A.length/3*260,R=R.filter(function(a){return-1!==A.indexOf(a.metaKey)}),i.width(z).color(["#444","#444","#444"]),P.select(".nv-controlsWrap").datum(R).call(i),l.top!=Math.max(i.height(),h.height())&&(l.top=Math.max(i.height(),h.height()),L=a.utils.availableHeight(n,x,l)),P.select(".nv-controlsWrap").attr("transform","translate(0,"+-l.top+")")}N.attr("transform","translate("+l.left+","+l.top+")"),t&&P.select(".nv-y.nv-axis").attr("transform","translate("+K+",0)"),u&&(j.width(K).height(L).margin({left:l.left,top:l.top}).svgContainer(x).xScale(c),N.select(".nv-interactive").call(j)),e.width(K).height(L);var S=P.select(".nv-stackedWrap").datum(k);if(S.transition().call(e),r&&(f.scale(c)._ticks(a.utils.calcTicksX(K/100,k)).tickSize(-L,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+L+")"),P.select(".nv-x.nv-axis").transition().duration(0).call(f)),s){var T;if(T="wiggle"===e.offset()?0:a.utils.calcTicksY(L/36,k),g.scale(d)._ticks(T).tickSize(-K,0),"expand"===e.style()||"stack_percent"===e.style()){var U=g.tickFormat();D&&U===J||(D=U),g.tickFormat(J)}else D&&(g.tickFormat(D),D=null);P.select(".nv-y.nv-axis").transition().duration(0).call(g)}e.dispatch.on("areaClick.toggle",function(a){1===k.filter(function(a){return!a.disabled}).length?k.forEach(function(a){a.disabled=!1}):k.forEach(function(b,c){b.disabled=c!=a.seriesIndex}),v.disabled=k.map(function(a){return!!a.disabled}),y.stateChange(v),b.update()}),h.dispatch.on("stateChange",function(a){for(var c in a)v[c]=a[c];y.stateChange(v),b.update()}),i.dispatch.on("legendClick",function(a,c){a.disabled&&(R=R.map(function(a){return a.disabled=!0,a}),a.disabled=!1,e.style(a.style),v.style=e.style(),y.stateChange(v),b.update())}),j.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,g,h,i=[];if(k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,j){g=a.interactiveBisect(f.values,c.pointXValue,b.x());var k=f.values[g],l=b.y()(k,g);if(null!=l&&e.highlightPoint(j,g,!0),"undefined"!=typeof k){"undefined"==typeof d&&(d=k),"undefined"==typeof h&&(h=b.xScale()(b.x()(k,g)));var m="expand"==e.style()?k.display.y:b.y()(k,g);i.push({key:f.key,value:m,color:o(f,f.seriesIndex),stackedValue:k.display})}}),i.reverse(),i.length>2){var m=b.yScale().invert(c.mouseY),n=null;i.forEach(function(a,b){m=Math.abs(m);var c=Math.abs(a.stackedValue.y0),d=Math.abs(a.stackedValue.y);return m>=c&&d+c>=m?void(n=b):void 0}),null!=n&&(i[n].highlight=!0)}var p=f.tickFormat()(b.x()(d,g)),q=j.tooltip.valueFormatter();"expand"===e.style()||"stack_percent"===e.style()?(E||(E=q),q=d3.format(".1%")):E&&(q=E,E=null),j.tooltip.position({left:h+l.left,top:c.mouseY+l.top}).chartContainer(F.parentNode).valueFormatter(q).data({value:p,series:i})(),j.renderGuideLine(h)}),j.dispatch.on("elementMouseout",function(a){e.clearHighlights()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&k.length===a.disabled.length&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),v.disabled=a.disabled),"undefined"!=typeof a.style&&(e.style(a.style),G=a.style),b.update()})}),F.renderEnd("stacked Area chart immediate"),b}var c,d,e=a.models.stackedArea(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:25,bottom:50,left:60},m=null,n=null,o=a.utils.defaultColor(),p=!0,q=!0,r=!0,s=!0,t=!1,u=!1,v=a.utils.state(),w=null,x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=250,A=["Stacked","Stream","Expanded"],B={},C=250;v.style=e.style(),f.orient("bottom").tickPadding(7),g.orient(t?"right":"left"),k.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)}),j.tooltip.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)});var D=null,E=null;i.updateState(!1);var F=a.utils.renderWatch(y),G=e.style(),H=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),style:e.style()}}},I=function(a){return function(b){void 0!==b.style&&(G=b.style),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},J=d3.format("%");return e.dispatch.on("elementMouseover.tooltip",function(a){a.point.x=e.x()(a.point),a.point.y=e.y()(a.point),k.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){k.hidden(!0)}),b.dispatch=y,b.stacked=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.interactiveLayer=j,b.tooltip=k,b.dispatch=y,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return w},set:function(a){w=a}},noData:{get:function(){return x},set:function(a){x=a}},showControls:{get:function(){return p},set:function(a){p=a}},controlLabels:{get:function(){return B},set:function(a){B=a}},controlOptions:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return C},set:function(a){C=a,F.reset(C),e.duration(C),f.duration(C),g.duration(C)}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),h.color(o),e.color(o)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},useInteractiveGuideline:{get:function(){return u},set:function(a){u=!!a,b.interactive(!a),b.useVoronoi(!a),e.scatter.interactive(!a)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.sunburst=function(){"use strict";function b(u){return t.reset(),u.each(function(b){function t(a){a.x0=a.x,a.dx0=a.dx}function u(a){var b=d3.interpolate(p.domain(),[a.x,a.x+a.dx]),c=d3.interpolate(q.domain(),[a.y,1]),d=d3.interpolate(q.range(),[a.y?20:0,y]);return function(a,e){return e?function(b){return s(a)}:function(e){return p.domain(b(e)),q.domain(c(e)).range(d(e)),s(a)}}}l=d3.select(this);var v,w=a.utils.availableWidth(g,l,f),x=a.utils.availableHeight(h,l,f),y=Math.min(w,x)/2;a.utils.initSVG(l);var z=l.selectAll(".nv-wrap.nv-sunburst").data(b),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburst nv-chart-"+k),B=A.selectAll("nv-sunburst");z.attr("transform","translate("+w/2+","+x/2+")"),l.on("click",function(a,b){o.chartClick({data:a,index:b,pos:d3.event,id:k})}),q.range([0,y]),c=c||b,e=b[0],r.value(j[i]||j.count),v=B.data(r.nodes).enter().append("path").attr("d",s).style("fill",function(a){return m((a.children?a:a.parent).name)}).style("stroke","#FFF").on("click",function(a){d!==c&&c!==a&&(d=c),c=a,v.transition().duration(n).attrTween("d",u(a))}).each(t).on("dblclick",function(a){d.parent==a&&v.transition().duration(n).attrTween("d",u(e))}).each(t).on("mouseover",function(a,b){d3.select(this).classed("hover",!0).style("opacity",.8),o.elementMouseover({data:a,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1).style("opacity",1),o.elementMouseout({data:a})}).on("mousemove",function(a,b){o.elementMousemove({data:a})})}),t.renderEnd("sunburst immediate"),b}var c,d,e,f={top:0,right:0,bottom:0,left:0},g=null,h=null,i="count",j={count:function(a){return 1},size:function(a){return a.size}},k=Math.floor(1e4*Math.random()),l=null,m=a.utils.defaultColor(),n=500,o=d3.dispatch("chartClick","elementClick","elementDblClick","elementMousemove","elementMouseover","elementMouseout","renderEnd"),p=d3.scale.linear().range([0,2*Math.PI]),q=d3.scale.sqrt(),r=d3.layout.partition().sort(null).value(function(a){return 1}),s=d3.svg.arc().startAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x)))}).endAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x+a.dx)))}).innerRadius(function(a){return Math.max(0,q(a.y))}).outerRadius(function(a){return Math.max(0,q(a.y+a.dy))}),t=a.utils.renderWatch(o);return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},mode:{get:function(){return i},set:function(a){i=a}},id:{get:function(){return k},set:function(a){k=a}},duration:{get:function(){return n},set:function(a){n=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!=a.top?a.top:f.top,f.right=void 0!=a.right?a.right:f.right,f.bottom=void 0!=a.bottom?a.bottom:f.bottom,f.left=void 0!=a.left?a.left:f.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sunburstChart=function(){"use strict";function b(d){return m.reset(),m.models(c),d.each(function(d){var h=d3.select(this);a.utils.initSVG(h);var i=a.utils.availableWidth(f,h,e),j=a.utils.availableHeight(g,h,e);if(b.update=function(){0===k?h.call(b):h.transition().duration(k).call(b)},b.container=this,!d||!d.length)return a.utils.noData(b,h),b;h.selectAll(".nv-noData").remove();var l=h.selectAll("g.nv-wrap.nv-sunburstChart").data(d),m=l.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburstChart").append("g"),n=l.select("g");m.append("g").attr("class","nv-sunburstWrap"),l.attr("transform","translate("+e.left+","+e.top+")"),c.width(i).height(j);var o=n.select(".nv-sunburstWrap").datum(d);d3.transition(o).call(c)}),m.renderEnd("sunburstChart immediate"),b}var c=a.models.sunburst(),d=a.models.tooltip(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=a.utils.defaultColor(),i=(Math.round(1e5*Math.random()),null),j=null,k=250,l=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),m=a.utils.renderWatch(l);return d.headerEnabled(!1).duration(0).valueFormatter(function(a,b){return a}),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.data.name,value:a.data.size,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(a){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(a){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=l,b.sunburst=c,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return i},set:function(a){i=a}},color:{get:function(){return h},set:function(a){h=a,c.color(h)}},duration:{get:function(){return k},set:function(a){k=a,m.reset(k),c.duration(k)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.version="1.8.1"}(); \ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/DT_bootstrap/DT_bootstrap.css b/wqflask/wqflask/static/packages/DT_bootstrap/DT_bootstrap.css
deleted file mode 100644
index 9adaabb1..00000000
--- a/wqflask/wqflask/static/packages/DT_bootstrap/DT_bootstrap.css
+++ /dev/null
@@ -1,179 +0,0 @@
-
-div.dataTables_length label {
- float: left;
- text-align: left;
-}
-
-div.dataTables_length select {
- width: 75px;
-}
-
-div.dataTables_filter label {
- float: right;
-}
-
-div.dataTables_info {
- padding-top: 8px;
-}
-
-div.dataTables_paginate {
- float: right;
- margin: 0;
-}
-
-table.table {
- clear: both;
- margin-bottom: 6px !important;
- max-width: none !important;
-}
-
-table.table thead .sorting,
-table.table thead .sorting_asc,
-table.table thead .sorting_desc,
-table.table thead .sorting_asc_disabled,
-table.table thead .sorting_desc_disabled {
- cursor: pointer;
- *cursor: hand;
-}
-
-table.table thead .sorting { background: url('images/sort_both.png') no-repeat center right; }
-table.table thead .sorting_asc { background: url('images/sort_asc.png') no-repeat center right; }
-table.table thead .sorting_desc { background: url('images/sort_desc.png') no-repeat center right; }
-
-table.table thead .sorting_asc_disabled { background: url('images/sort_asc_disabled.png') no-repeat center right; }
-table.table thead .sorting_desc_disabled { background: url('images/sort_desc_disabled.png') no-repeat center right; }
-
-table.dataTable th:active {
- outline: none;
-}
-
-/* Scrolling */
-div.dataTables_scrollHead table {
- margin-bottom: 0 !important;
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
-}
-
-div.dataTables_scrollHead table thead tr:last-child th:first-child,
-div.dataTables_scrollHead table thead tr:last-child td:first-child {
- border-bottom-left-radius: 0 !important;
- border-bottom-right-radius: 0 !important;
-}
-
-div.dataTables_scrollBody table {
- border-top: none;
- margin-bottom: 0 !important;
-}
-
-div.dataTables_scrollBody tbody tr:first-child th,
-div.dataTables_scrollBody tbody tr:first-child td {
- border-top: none;
-}
-
-div.dataTables_scrollFoot table {
- border-top: none;
-}
-
-
-
-
-/*
- * TableTools styles
- */
-.table tbody tr.active td,
-.table tbody tr.active th {
- background-color: #08C;
- color: white;
-}
-
-.table tbody tr.active:hover td,
-.table tbody tr.active:hover th {
- background-color: #0075b0 !important;
-}
-
-.table-striped tbody tr.active:nth-child(odd) td,
-.table-striped tbody tr.active:nth-child(odd) th {
- background-color: #017ebc;
-}
-
-table.DTTT_selectable tbody tr {
- cursor: pointer;
- *cursor: hand;
-}
-
-div.DTTT .btn {
- color: #333 !important;
- font-size: 12px;
-}
-
-div.DTTT .btn:hover {
- text-decoration: none !important;
-}
-
-
-ul.DTTT_dropdown.dropdown-menu a {
- color: #333 !important; /* needed only when demo_page.css is included */
-}
-
-ul.DTTT_dropdown.dropdown-menu li:hover a {
- background-color: #0088cc;
- color: white !important;
-}
-
-/* TableTools information display */
-div.DTTT_print_info.modal {
- height: 150px;
- margin-top: -75px;
- text-align: center;
-}
-
-div.DTTT_print_info h6 {
- font-weight: normal;
- font-size: 28px;
- line-height: 28px;
- margin: 1em;
-}
-
-div.DTTT_print_info p {
- font-size: 14px;
- line-height: 20px;
-}
-
-
-
-/*
- * FixedColumns styles
- */
-div.DTFC_LeftHeadWrapper table,
-div.DTFC_LeftFootWrapper table,
-table.DTFC_Cloned tr.even {
- background-color: white;
-}
-
-div.DTFC_LeftHeadWrapper table {
- margin-bottom: 0 !important;
- border-top-right-radius: 0 !important;
- border-bottom-left-radius: 0 !important;
- border-bottom-right-radius: 0 !important;
-}
-
-div.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child,
-div.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child {
- border-bottom-left-radius: 0 !important;
- border-bottom-right-radius: 0 !important;
-}
-
-div.DTFC_LeftBodyWrapper table {
- border-top: none;
- margin-bottom: 0 !important;
-}
-
-div.DTFC_LeftBodyWrapper tbody tr:first-child th,
-div.DTFC_LeftBodyWrapper tbody tr:first-child td {
- border-top: none;
-}
-
-div.DTFC_LeftFootWrapper table {
- border-top: none;
-}
-
diff --git a/wqflask/wqflask/static/packages/DT_bootstrap/DT_bootstrap.js b/wqflask/wqflask/static/packages/DT_bootstrap/DT_bootstrap.js
deleted file mode 100644
index cfe3e9d2..00000000
--- a/wqflask/wqflask/static/packages/DT_bootstrap/DT_bootstrap.js
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Set the defaults for DataTables initialisation */
-$.extend( true, $.fn.dataTable.defaults, {
- "sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>",
- "sPaginationType": "bootstrap",
- "oLanguage": {
- "sLengthMenu": "_MENU_ records per page"
- }
-} );
-
-
-/* Default class modification */
-$.extend( $.fn.dataTableExt.oStdClasses, {
- "sWrapper": "dataTables_wrapper form-inline"
-} );
-
-
-/* API method to get paging information */
-$.fn.dataTableExt.oApi.fnPagingInfo = function ( oSettings )
-{
- return {
- "iStart": oSettings._iDisplayStart,
- "iEnd": oSettings.fnDisplayEnd(),
- "iLength": oSettings._iDisplayLength,
- "iTotal": oSettings.fnRecordsTotal(),
- "iFilteredTotal": oSettings.fnRecordsDisplay(),
- "iPage": oSettings._iDisplayLength === -1 ?
- 0 : Math.ceil( oSettings._iDisplayStart / oSettings._iDisplayLength ),
- "iTotalPages": oSettings._iDisplayLength === -1 ?
- 0 : Math.ceil( oSettings.fnRecordsDisplay() / oSettings._iDisplayLength )
- };
-};
-
-
-/* Bootstrap style pagination control */
-$.extend( $.fn.dataTableExt.oPagination, {
- "bootstrap": {
- "fnInit": function( oSettings, nPaging, fnDraw ) {
- var oLang = oSettings.oLanguage.oPaginate;
- var fnClickHandler = function ( e ) {
- e.preventDefault();
- if ( oSettings.oApi._fnPageChange(oSettings, e.data.action) ) {
- fnDraw( oSettings );
- }
- };
-
- $(nPaging).addClass('pagination').append(
- '<ul>'+
- '<li class="prev disabled"><a href="#">&larr; '+oLang.sPrevious+'</a></li>'+
- '<li class="next disabled"><a href="#">'+oLang.sNext+' &rarr; </a></li>'+
- '</ul>'
- );
- var els = $('a', nPaging);
- $(els[0]).bind( 'click.DT', { action: "previous" }, fnClickHandler );
- $(els[1]).bind( 'click.DT', { action: "next" }, fnClickHandler );
- },
-
- "fnUpdate": function ( oSettings, fnDraw ) {
- var iListLength = 5;
- var oPaging = oSettings.oInstance.fnPagingInfo();
- var an = oSettings.aanFeatures.p;
- var i, ien, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2);
-
- if ( oPaging.iTotalPages < iListLength) {
- iStart = 1;
- iEnd = oPaging.iTotalPages;
- }
- else if ( oPaging.iPage <= iHalf ) {
- iStart = 1;
- iEnd = iListLength;
- } else if ( oPaging.iPage >= (oPaging.iTotalPages-iHalf) ) {
- iStart = oPaging.iTotalPages - iListLength + 1;
- iEnd = oPaging.iTotalPages;
- } else {
- iStart = oPaging.iPage - iHalf + 1;
- iEnd = iStart + iListLength - 1;
- }
-
- for ( i=0, ien=an.length ; i<ien ; i++ ) {
- // Remove the middle elements
- $('li:gt(0)', an[i]).filter(':not(:last)').remove();
-
- // Add the new list items and their event handlers
- for ( j=iStart ; j<=iEnd ; j++ ) {
- sClass = (j==oPaging.iPage+1) ? 'class="active"' : '';
- $('<li '+sClass+'><a href="#">'+j+'</a></li>')
- .insertBefore( $('li:last', an[i])[0] )
- .bind('click', function (e) {
- e.preventDefault();
- oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength;
- fnDraw( oSettings );
- } );
- }
-
- // Add / remove disabled classes from the static elements
- if ( oPaging.iPage === 0 ) {
- $('li:first', an[i]).addClass('disabled');
- } else {
- $('li:first', an[i]).removeClass('disabled');
- }
-
- if ( oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0 ) {
- $('li:last', an[i]).addClass('disabled');
- } else {
- $('li:last', an[i]).removeClass('disabled');
- }
- }
- }
- }
-} );
-
-
-/*
- * TableTools Bootstrap compatibility
- * Required TableTools 2.1+
- */
-if ( $.fn.DataTable.TableTools ) {
- // Set the classes that TableTools uses to something suitable for Bootstrap
- $.extend( true, $.fn.DataTable.TableTools.classes, {
- "container": "DTTT btn-group",
- "buttons": {
- "normal": "btn",
- "disabled": "disabled"
- },
- "collection": {
- "container": "DTTT_dropdown dropdown-menu",
- "buttons": {
- "normal": "",
- "disabled": "disabled"
- }
- },
- "print": {
- "info": "DTTT_print_info modal"
- },
- "select": {
- "row": "active"
- }
- } );
-
- // Have the collection use a bootstrap compatible dropdown
- $.extend( true, $.fn.DataTable.TableTools.DEFAULTS.oTags, {
- "collection": {
- "container": "ul",
- "button": "li",
- "liner": "a"
- }
- } );
-}
-
-
-/* Table initialisation */
-//$(document).ready(function() {
-// $('#example').dataTable( {
-// "sDom": "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i><'span6'p>>",
-// "sPaginationType": "bootstrap",
-// "oLanguage": {
-// "sLengthMenu": "_MENU_ records per page"
-// }
-// } );
-//} ); \ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/DT_bootstrap/images b/wqflask/wqflask/static/packages/DT_bootstrap/images
deleted file mode 120000
index f5f1b7d0..00000000
--- a/wqflask/wqflask/static/packages/DT_bootstrap/images
+++ /dev/null
@@ -1 +0,0 @@
-../../new/packages/DataTables/images/ \ No newline at end of file
diff --git a/wqflask/wqflask/templates/index_page_orig.html b/wqflask/wqflask/templates/index_page_orig.html
index 48ed0ec5..92392b39 100755
--- a/wqflask/wqflask/templates/index_page_orig.html
+++ b/wqflask/wqflask/templates/index_page_orig.html
@@ -202,7 +202,9 @@
<div align="right">
<a href="https://twitter.com/GeneNetwork2">more news items...</a>
</div>
+ <script type="text/javascript" src="//rf.revolvermaps.com/0/0/8.js?i=526mdlpknyd&amp;m=0&amp;c=ff0000&amp;cr1=ffffff&amp;f=arial&amp;l=33" async="async"></script>
</div>
+ </section>
<section id="websites">
<div class="page-header">
<h1>Github</h1>
diff --git a/wqflask/wqflask/templates/show_trait.html b/wqflask/wqflask/templates/show_trait.html
index ff000ced..3e4a6d7c 100644
--- a/wqflask/wqflask/templates/show_trait.html
+++ b/wqflask/wqflask/templates/show_trait.html
@@ -6,7 +6,6 @@
<link rel="stylesheet" type="text/css" href="/static/new/css/prob_plot.css" />
<link rel="stylesheet" type="text/css" href="/static/new/css/scatter-matrix.css" />
<link rel="stylesheet" type="text/css" href="/static/new/css/d3-tip.min.css" />
- <link rel="stylesheet" type="text/css" href="/static/new/packages/nvd3/nv.d3.css" />
<link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/css/jquery.dataTables.css" />
<link rel="stylesheet" type="text/css" href="/static/new/packages/noUiSlider/nouislider.css" />
<link rel="stylesheet" type="text/css" href="/static/new/packages/noUiSlider/nouislider.pips.css" />
@@ -131,7 +130,6 @@
</script>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
- <script type="text/javascript" src="/static/new/packages/nvd3/nv.d3.js"></script>
<script type="text/javascript" src="/static/new/js_external/underscore-min.js"></script>
<script type="text/javascript" src="/static/new/js_external/underscore.string.min.js"></script>
<script type="text/javascript" src="/static/new/js_external/d3-tip.min.js"></script>
diff --git a/wqflask/wqflask/user_manager.py b/wqflask/wqflask/user_manager.py
index 7ab7583f..b2c7a914 100644
--- a/wqflask/wqflask/user_manager.py
+++ b/wqflask/wqflask/user_manager.py
@@ -789,7 +789,7 @@ class LoginUser(object):
user_details = get_user_by_unique_column(es, "user_id", user_id)
if user_details:
user = model.User()
- user.id = user_details["user_id"]
+ user.id = user_details["user_id"] if user_details["user_id"] == None else "N/A"
user.full_name = user_details["name"]
user.login_type = user_details["login_type"]
return self.actual_login(user)
@@ -887,6 +887,9 @@ class LoginUser(object):
session_id_signed = login_rec.session_id + ":" + session_id_signature
logger.debug("session_id_signed:", session_id_signed)
+ if not user.id:
+ user.id = ''
+
session = dict(login_time = time.time(),
user_id = user.id,
user_name = user.full_name,