From a91dd73b908bf5c4629c90d4e71e2136c7d864ba Mon Sep 17 00:00:00 2001 From: ayyoob Date: Sun, 12 Jul 2015 04:10:59 +0530 Subject: [PATCH 01/12] bam and analytics corrections --- modules/distribution/pom.xml | 8 +++++++- modules/distribution/src/assembly/bin.xml | 9 +++++++++ .../repository/jaggeryapps/iot/api/stats-api.jag | 2 +- .../jaggeryapps/iotserver/api/stats-api.jag | 2 +- .../src/statistics/IOT_Analytics.tbox | Bin 0 -> 5405 bytes 5 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 modules/distribution/src/statistics/IOT_Analytics.tbox diff --git a/modules/distribution/pom.xml b/modules/distribution/pom.xml index 625a7f70..9b6cb6fc 100644 --- a/modules/distribution/pom.xml +++ b/modules/distribution/pom.xml @@ -404,13 +404,19 @@ - + + + + + + + + + + + + + diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/layouts/fluid.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/layouts/fluid.hbs old mode 100644 new mode 100755 index 3065855a..6cedfaad --- a/modules/distribution/src/repository/jaggeryapps/iotserver/layouts/fluid.hbs +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/layouts/fluid.hbs @@ -1,14 +1,15 @@ - - - - - - - {{ defineZone "title"}} - {{ defineZone "topLibCss"}} - {{ defineZone "topCss"}} - {{ defineZone "topJs"}} + + + + + + {{defineZone "favicon"}} + + {{ defineZone "title"}} + + {{ defineZone "topLibCss"}} + {{ defineZone "topCss"}}
@@ -32,6 +33,7 @@ {{ defineZone "body"}} {{ defineZone "footer"}}
+ {{ defineZone "bottomjquery" }} {{ defineZone "bottomLibJs" }} {{ defineZone "bottomJs" }} diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/layouts/nav-fluid.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/layouts/nav-fluid.hbs old mode 100644 new mode 100755 diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/acs.jag b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/acs.jag old mode 100644 new mode 100755 index 147c20a2..8aae7961 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/acs.jag +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/acs.jag @@ -22,6 +22,8 @@ var sso = require('/modules/sso.js').sso; var constants = require('/modules/constants.js'); var carbonModule = require("carbon"); var log = new Log(); +var apiWrapperUtil = require("/modules/api-wrapper-util.js").apiWrapperUtil; +var userModule = require("/modules/user.js").userModule; var keyStoreParams = { keyStoreName: dataConfig.ssoConfiguration.keyStoreName, keyStorePassword: dataConfig.ssoConfiguration.keyStorePassword, @@ -31,14 +33,18 @@ sso.configure(dataConfig.ssoConfiguration.issuer, dataConfig.ssoConfiguration.appName, keyStoreParams, dataConfig.ssoConfiguration.identityProviderURL); sso.acs( - function(loggedInUser) { + function(loggedInUser, samlResponse) { var carbonUser = carbonModule.server.tenantUser(loggedInUser); session.put(constants.USER_SESSION_KEY, carbonUser); var username = carbonUser.username; if(log.isDebugEnabled()){ log.debug("User logged in: "+username); } - response.sendRedirect(dataConfig.appContext); + var permissions = userModule.getUIPermissions(); + if (permissions.DASHBOARD_VIEW){ + apiWrapperUtil.setupAccessTokenPair("saml", samlResponse); + response.sendRedirect(dataConfig.appContext + "/device-mgt"); + } }, function() { if(log.isDebugEnabled()){ log.debug("User logged out"); diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/fuse-router.js b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/fuse-router.js old mode 100644 new mode 100755 index 6ab63dc1..7aab77d7 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/fuse-router.js +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/fuse-router.js @@ -82,41 +82,8 @@ var route; }; var renderStatic = function (unit, path) { - var unitModel = null; - var unitName = ""; - var parts = (unit + path).split("/"); - - //'unitName' name can be "unitA" or "categoryA/unitA" or "categoryA/categoryAb/unitB"...etc - //incrementally trying to resolve a unit using url path parts. - for (var i = 0; i < parts.length; i++) { - - if (unitName == "") { - unitName = parts[i]; - } else { - unitName += "/" + parts[i]; - } - - try { - var model = fuse.getUnitDefinition(unitName); - if (model) { - unitModel = { - name: model.name, - path: parts.splice(i + 1).join("/") - }; - break; - } - } catch (err) { - //unit not found, ignore error - } - } - - if (unitModel == null) { - log.error("unit `"+unit+"` not found!"); - return false; - } - - var staticFile = fuse.getFile(unitModel.name, 'public' + "/" + unitModel.path); - + log.debug('[' + requestId + '] for unit "' + unit + '" a request received for a static file "' + path + '"'); + var staticFile = fuse.getFile(unit, 'public' + path); if (staticFile.isExists() && !staticFile.isDirectory()) { response.addHeader('Content-type', getMime(path)); response.addHeader('Cache-Control', 'public,max-age=12960000'); @@ -139,7 +106,7 @@ var route; if (jagFile.isExists()) { include(jagFile.getPath()); return true; - } else { + }else{ return false; } }; diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/fuse.jag b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/fuse.jag old mode 100644 new mode 100755 index a16cebfb..748d82ed --- a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/fuse.jag +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/fuse.jag @@ -1,17 +1,10 @@ <% -var getPath = File.prototype.getPath; -File.prototype.getPath = function() { - var path = getPath.call(this); - path = path.replace(/\\/g, '/'); - return path; -}; - //global object to pass request stat among fuse framework files. var fuseState = { zones: {}, appName: '', - zoneStack: [], + currentZone: [], //TODO: rename to zone Stack currentUnit: null }; diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/fuse.js b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/fuse.js old mode 100644 new mode 100755 index fcc26c74..3dd87fc2 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/fuse.js +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/fuse.js @@ -15,7 +15,6 @@ var getHbsFile, getFile, toRelativePath, cleanupAncestors, for (var i = 0; i < definitions.length; i++) { var definition = definitions[i]; lookUpTable[definition.name] = i; - //log.info("initLookUp()"+definition.name+"<-"+i); } } }; @@ -46,7 +45,6 @@ var getHbsFile, getFile, toRelativePath, cleanupAncestors, }; var getAncestorModels = function (unit) { - //log.info('[' + requestId + '] getAncestorModels()'+unit); var unitModel = getUnitDefinition(unit); var ancestors = [unitModel]; var parentName; @@ -150,12 +148,11 @@ var getHbsFile, getFile, toRelativePath, cleanupAncestors, }; getUnitDefinition = function (unit) { - //log.info('[' + requestId + '] getUnitDefinition()'+unit); var definitions = getUnitDefinitions(); initLookUp(definitions); - //log.info('[' + requestId + '] lookUpTable[unit]:'+unit); var model = definitions[lookUpTable[unit]]; if (!model) { + log.warn('[' + requestId + '] unit "' + unit + '" does not exits'); throw '[' + requestId + '] unit "' + unit + '" does not exits'; } return model; @@ -208,7 +205,7 @@ var getHbsFile, getFile, toRelativePath, cleanupAncestors, var unitDir = unitDirs[i]; if (unitDir.isDirectory()) { var unitName = unitDir.getName(); - //log.info("reading: "+unitName + " basePath:'" + basePath + "'"); + //log.info("reading: "+unitName + " basePath:"+basePath); var definitionFile = new File(fuse.getUnitPath(basePath+unitName) + '/' + unitName + '.json'); if(definitionFile.isExists()) { @@ -384,7 +381,6 @@ var getHbsFile, getFile, toRelativePath, cleanupAncestors, * @returns {File} */ getFile = function (unitName, path, opt_suffix) { - //log.info("getFile() unitName:"+unitName+", path:"+path+", opt_suffix:"+opt_suffix); var slashPath = ((path[0] === '/') ? '' : '/') + path; var selfFileName = ''; var fileName = ''; @@ -403,10 +399,8 @@ var getHbsFile, getFile, toRelativePath, cleanupAncestors, var unitDef = getUnitDefinition(unitName); if (unitDef.path.indexOf('.hbs', unitDef.path.length - 4) !== -1) { if (opt_suffix.indexOf('.hbs', opt_suffix.length - 4) !== -1) { - //log.info("1:"+unitDef.path); return new File(unitDef.path); } else { - //log.info("2:"+unitDef.path.replace(/.hbs$/, opt_suffix)); return new File(unitDef.path.replace(/.hbs$/, opt_suffix)); } } @@ -417,7 +411,7 @@ var getHbsFile, getFile, toRelativePath, cleanupAncestors, '[' + requestId + '] for unit "' + unitName + '" file resolved : "' + slashPath + selfFileName + '" -> "' + selfFile.getPath() + '"' ); - //log.info("3:"+getUnitPath(unitName) + slashPath + selfFileName); + return selfFile; } @@ -437,7 +431,6 @@ var getHbsFile, getFile, toRelativePath, cleanupAncestors, '[' + requestId + '] for unit "' + unitName + '" file resolved : "' + slashPath + selfFileName + '" -> "' + file.getPath() + '"' ); - //log.info("4:"+getUnitPath(ancestorName) + slashPath + fileName); return file; } } @@ -445,7 +438,6 @@ var getHbsFile, getFile, toRelativePath, cleanupAncestors, '[' + requestId + '] for unit "' + unitName + '" (non-excising) file resolved : "' + slashPath + selfFileName + '" -> "' + selfFile.getPath() + '"' ); - //log.info("5:"+getUnitPath(unitName) + slashPath + selfFileName); return selfFile; }; diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/handlebars-helpers.js b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/handlebars-helpers.js old mode 100644 new mode 100755 index 9ea058b2..8c915700 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/handlebars-helpers.js +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/handlebars-helpers.js @@ -56,7 +56,7 @@ Handlebars.innerZonesFromUnit = null; Handlebars.registerHelper('defineZone', function (zoneName, zoneContent) { var result = ''; var zone = Handlebars.Utils.escapeExpression(zoneName); - fuseState.zoneStack.push(zone); + fuseState.currentZone.push(zone); var unitsToRender = fuseState.zones[zone] || []; if (Handlebars.innerZones.length > 0) { @@ -92,12 +92,12 @@ Handlebars.registerHelper('defineZone', function (zoneName, zoneContent) { return result; } - fuseState.zoneStack.pop(); + fuseState.currentZone.pop(); return new Handlebars.SafeString(result); }); Handlebars.registerHelper('zone', function (zoneName, zoneContent) { - var currentZone = fuseState.zoneStack[fuseState.zoneStack.length - 1]; + var currentZone = fuseState.currentZone[fuseState.currentZone.length - 1]; if (currentZone == null) { return 'zone_' + zoneName + ' '; } @@ -113,7 +113,7 @@ Handlebars.registerHelper('zone', function (zoneName, zoneContent) { }); Handlebars.registerHelper('layout', function (layoutName) { - var currentZone = fuseState.zoneStack[fuseState.zoneStack.length - 1]; + var currentZone = fuseState.currentZone[fuseState.currentZone.length - 1]; if (currentZone == null) { return 'layout_' + layoutName; } else { @@ -122,7 +122,7 @@ Handlebars.registerHelper('layout', function (layoutName) { }); Handlebars.registerHelper('authorized', function () { - var currentZone = fuseState.zoneStack[fuseState.zoneStack.length - 1]; + var currentZone = fuseState.currentZone[fuseState.currentZone.length - 1]; if (currentZone == null) { return ''; } else { @@ -155,11 +155,11 @@ Handlebars.registerHelper('unit', function (unitName,options) { log.error('unit does not have a main zone'); } //TODO warn when unspecified decencies are included. - fuseState.zoneStack.push('main'); + fuseState.currentZone.push('main'); var template = fuse.getFile(baseUnit, '', '.hbs'); log.debug('[' + requestId + '] including "' + baseUnit + '"'+" with configs "+stringify(templateConfigs)); var result = new Handlebars.SafeString(Handlebars.compileFile(template)(getScope(baseUnit,templateConfigs))); - fuseState.zoneStack.pop(); + fuseState.currentZone.pop(); return result; }); @@ -192,7 +192,6 @@ Handlebars.registerHelper('equal', function(lvalue, rvalue, options) { return options.fn(this); } }); - Handlebars.registerHelper('unequal', function(lvalue, rvalue, options) { if (arguments.length < 3) throw new Error("Handlebars Helper equal needs 2 parameters"); diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/handlebars-v2.0.0.js b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/handlebars-v2.0.0.js old mode 100644 new mode 100755 diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/less-rhino-1.7.5.js b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/less-rhino-1.7.5.js old mode 100644 new mode 100755 index 798c8563..4a191ca4 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/less-rhino-1.7.5.js +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/less-rhino-1.7.5.js @@ -10190,7 +10190,7 @@ var compile = function (args) { var parser = new less.Parser(options); parser.parse(input, function (e, root) { if (e) { - log.info(e); + log.error(e); writeError(e, options); quit(1); } else { diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/login.jag b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/login.jag old mode 100644 new mode 100755 diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/lib/logout.jag b/modules/distribution/src/repository/jaggeryapps/iotserver/lib/logout.jag old mode 100644 new mode 100755 diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/modules/api-wrapper-util.js b/modules/distribution/src/repository/jaggeryapps/iotserver/modules/api-wrapper-util.js new file mode 100755 index 00000000..2de3c4fa --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/modules/api-wrapper-util.js @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var apiWrapperUtil = function () { + var module = {}; + var tokenUtil = require("/modules/util.js").util; + module.refreshToken = function () { + var tokenPair = session.get("accessTokenPair"); + tokenPair = tokenUtil.refreshToken(tokenPair); + session.put("accessTokenPair", tokenPair); + response.addCookie({'name': 'accessToken', 'value': tokenPair.accessToken}); + }; + module.setupAccessTokenPair = function (type, properties) { + var tokenPair; + var clientId = "pY0FbBUC_GI7mfHVS1FvhWAifEwa"; + var clientSecret = "Tu5Za1R3fHtGc5yH4KK8TNiLVSca"; + if (type == "password") { + //tokenPair = tokenUtil.getTokenWithPasswordGrantType(properties.username, properties.password, clientId, clientSecret); + } else if (type == "saml") { + + } + //session.put("accessTokenPair", tokenPair); + //response.addCookie({'name': 'accessToken', 'value': tokenPair.accessToken}); + }; + return module; +}(); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/modules/constants.js b/modules/distribution/src/repository/jaggeryapps/iotserver/modules/constants.js index bd03967a..048a5d24 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/modules/constants.js +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/modules/constants.js @@ -20,7 +20,7 @@ var WEB_APP_TITLE = "WSO2 DC - Device Cloud"; var WEB_APP_CONTEXT = "/iotserver"; var USER_SESSION_KEY = "USER"; var UNSPECIFIED = "Unspecified"; -var DEVICES_UNIT_PATH="/units/devices/"; +var DEVICES_UNIT_PATH="/units/"; var DEVICE_IDENTIFIER = "deviceIdentifier"; var DEVICE_NAME = "name"; diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/modules/device.js b/modules/distribution/src/repository/jaggeryapps/iotserver/modules/device.js index 8dfd6fcd..5b1b6b52 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/modules/device.js +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/modules/device.js @@ -167,7 +167,7 @@ deviceModule = function () { var data = {}; //XMLHTTPRequest's GET - log.info(removeDeviceEndpoint); + //log.info(removeDeviceEndpoint); return del(removeDeviceEndpoint, data, "text"); }; @@ -178,8 +178,8 @@ deviceModule = function () { var data = {}; //XMLHTTPRequest's POST - log.info(updateDeviceEndpoint+ "?name="+device.name); - return post(updateDeviceEndpoint+ "?name="+device.name, data, "text"); + //log.info(updateDeviceEndpoint+ "?name="+device.name); + return post(updateDeviceEndpoint+ "?name="+encodeURIComponent(device.name), data, "text"); }; /* @@ -273,4 +273,4 @@ deviceModule = function () { return publicMethods; -}(); \ No newline at end of file +}(); diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/modules/util.js b/modules/distribution/src/repository/jaggeryapps/iotserver/modules/util.js new file mode 100755 index 00000000..f6d413b2 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/modules/util.js @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var util = function () { + var module = {}; + var Base64 = Packages.org.apache.commons.codec.binary.Base64; + var String = Packages.java.lang.String; + var log = new Log(); + + /** + * Encode the payload in Base64 + * @param payload + * @returns {Packages.java.lang.String} + */ + function encode(payload){ + return new String(Base64.encodeBase64(new String(payload).getBytes())); + } + + /** + * Get an AccessToken pair based on username and password + * @param username + * @param password + * @param clientId + * @param clientSecret + * @param scope + * @returns {{accessToken: "", refreshToken: ""}} + */ + module.getTokenWithPasswordGrantType = function (username, password, clientId, clientSecret, scope) { + var xhr = new XMLHttpRequest(); + var tokenEndpoint = "https://localhost:9443/oauth2/token"; + var encodedClientKeys = encode(clientId + ":" + clientSecret); + xhr.open("POST", tokenEndpoint, false); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + xhr.setRequestHeader("Authorization", "Basic " + encodedClientKeys); + xhr.send("grant_type=password&username=" + username + "&password=" + password + "&scope=" + scope); + delete password, delete clientSecret, delete encodedClientKeys; + var tokenPair = {}; + if (xhr.status == 200) { + var data = parse(xhr.responseText); + tokenPair.refreshToken = data.refresh_token; + tokenPair.accessToken = data.access_token; + } else if (xhr.status == 403) { + throw "Error in obtaining token with Password Grant Type"; + } else { + throw "Error in obtaining token with Password Grant Type"; + } + return tokenPair; + }; + module.getTokenWithSAMLGrantType = function () { + + }; + module.refreshToken = function(tokenPair){ + var xhr = new XMLHttpRequest(); + var tokenEndpoint = "https://localhost:9443/oauth2/token"; + var encodedClientKeys = encode(clientId + ":" + clientSecret); + xhr.open("POST", tokenEndpoint, false); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + xhr.setRequestHeader("Authorization", "Basic " + encodedClientKeys); + xhr.send("grant_type=refresh_token&refresh_token=" + tokenPair.refreshToken + "&scope=" + scope); + delete password, delete clientSecret, delete encodedClientKeys; + var tokenPair = {}; + if (xhr.status == 200) { + var data = parse(xhr.responseText); + tokenPair.refreshToken = data.refresh_token; + tokenPair.accessToken = data.access_token; + } else if (xhr.status == 403) { + throw "Error in obtaining token with Password Grant Type"; + } else { + throw "Error in obtaining token with Password Grant Type"; + } + return tokenPair; + }; + return module; +}(); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/modules/utility.js b/modules/distribution/src/repository/jaggeryapps/iotserver/modules/utility.js index f4b02c14..1bff6d8e 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/modules/utility.js +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/modules/utility.js @@ -41,22 +41,52 @@ utility = function () { publicMethods.insertAppPermissions = function (userModule, type) { userModule.addPermissions([{key: "device-mgt", name: "Device Management"}], "", type); - userModule.addPermissions([{key: "admin", name: "Device Management Admin"}], "device-mgt", type); - userModule.addPermissions([{key: "user", name: "Device Management User"}], "device-mgt", type); + userModule.addPermissions([{ + key: "admin", + name: "Device Management Admin" + }], "device-mgt", type); + userModule.addPermissions([{ + key: "user", + name: "Device Management User" + }], "device-mgt", type); userModule.addPermissions([{key: "devices", name: "Devices"}], "device-mgt/admin", type); - userModule.addPermissions([{key: "devices/list", name: "List Devices"}], "device-mgt/admin", type); - userModule.addPermissions([{key: "devices/operation", name: "Perform Operation"}], "device-mgt/admin", type); + userModule.addPermissions([{ + key: "devices/list", + name: "List Devices" + }], "device-mgt/admin", type); + userModule.addPermissions([{ + key: "devices/operation", + name: "Perform Operation" + }], "device-mgt/admin", type); userModule.addPermissions([{key: "users", name: "Users"}], "device-mgt/admin", type); - userModule.addPermissions([{key: "users/add", name: "Add New Users"}], "device-mgt/admin", type); - userModule.addPermissions([{key: "users/invite", name: "Invite Users"}], "device-mgt/admin", type); - userModule.addPermissions([{key: "users/list", name: "List Users"}], "device-mgt/admin", type); - userModule.addPermissions([{key: "users/remove", name: "Remove Users"}], "device-mgt/admin", type); + userModule.addPermissions([{ + key: "users/add", + name: "Add New Users" + }], "device-mgt/admin", type); + userModule.addPermissions([{ + key: "users/invite", + name: "Invite Users" + }], "device-mgt/admin", type); + userModule.addPermissions([{ + key: "users/list", + name: "List Users" + }], "device-mgt/admin", type); + userModule.addPermissions([{ + key: "users/remove", + name: "Remove Users" + }], "device-mgt/admin", type); userModule.addPermissions([{key: "devices", name: "Devices"}], "device-mgt/user", type); - userModule.addPermissions([{key: "devices/list", name: "List Devices"}], "device-mgt/user", type); - userModule.addPermissions([{key: "devices/operation", name: "Perform Operation"}], "device-mgt/user", "init"); + userModule.addPermissions([{ + key: "devices/list", + name: "List Devices" + }], "device-mgt/user", type); + userModule.addPermissions([{ + key: "devices/operation", + name: "Perform Operation" + }], "device-mgt/user", "init"); }; return publicMethods; diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/dashboard.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/dashboard.hbs index 6500d10a..d11adeca 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/dashboard.hbs +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/dashboard.hbs @@ -1,3 +1,4 @@ +{{authorized}} {{layout "fluid"}} {{#zone "title"}} WSO2 DC | Device Cloud diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/android.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/android.hbs index 8e4b528b..0a7b07f9 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/android.hbs +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/android.hbs @@ -4,5 +4,5 @@ {{/zone}} {{#zone "body"}} {{unit "appbar" link="store" title="STORE"}} - {{unit "devices/android"}} + {{unit "android"}} {{/zone}} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/android_sense.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/android_sense.hbs index 0dd30cc5..b8b0b319 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/android_sense.hbs +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/android_sense.hbs @@ -4,5 +4,5 @@ {{/zone}} {{#zone "body"}} {{unit "appbar" link="store" title="STORE"}} - {{unit "devices/android_sense"}} + {{unit "android_sense"}} {{/zone}} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/arduino.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/arduino.hbs index c957abd3..afbe5b13 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/arduino.hbs +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/arduino.hbs @@ -4,5 +4,5 @@ {{/zone}} {{#zone "body"}} {{unit "appbar" link="store" title="STORE"}} - {{unit "devices/arduino"}} + {{unit "arduino"}} {{/zone}} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/digital_display.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/digital_display.hbs index 4b79991c..89d1b6d6 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/digital_display.hbs +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/digital_display.hbs @@ -4,5 +4,5 @@ {{/zone}} {{#zone "body"}} {{unit "appbar" link="store" title="STORE"}} - {{unit "devices/digital_display"}} + {{unit "digital_display"}} {{/zone}} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/firealarm.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/firealarm.hbs index 89676768..8330160f 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/firealarm.hbs +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/firealarm.hbs @@ -4,5 +4,5 @@ {{/zone}} {{#zone "body"}} {{unit "appbar" link="store" title="STORE"}} - {{unit "devices/firealarm"}} + {{unit "firealarm"}} {{/zone}} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/index.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/index.hbs index 68142bbe..ea9cd1a3 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/index.hbs +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/index.hbs @@ -4,7 +4,7 @@ Devices {{/zone}} {{#zone "body"}} - {{unit "appbar" link="device-mgt" title="Device Management"}} + {{unit "appbar" link="device-mgt" title="My Devices"}} {{unit "extended-search-box"}} {{unit "operation-mod"}}
diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/raspberrypi.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/raspberrypi.hbs index 9025c456..11e7f64b 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/raspberrypi.hbs +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/raspberrypi.hbs @@ -4,5 +4,5 @@ {{/zone}} {{#zone "body"}} {{unit "appbar" link="store" title="STORE"}} - {{unit "devices/raspberrypi"}} + {{unit "raspberrypi"}} {{/zone}} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/sensebot.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/sensebot.hbs index 4a4b58c1..a1b5049d 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/sensebot.hbs +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/sensebot.hbs @@ -4,5 +4,5 @@ {{/zone}} {{#zone "body"}} {{unit "appbar" link="store" title="STORE"}} - {{unit "devices/sensebot"}} + {{unit "sensebot"}} {{/zone}} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/windows.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/windows.hbs index cdfa94ba..8b87456d 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/windows.hbs +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/pages/devices/windows.hbs @@ -4,5 +4,5 @@ {{/zone}} {{#zone "body"}} {{unit "appbar" link="store" title="STORE"}} - {{unit "devices/windows"}} + {{unit "windows"}} {{/zone}} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/test.jag b/modules/distribution/src/repository/jaggeryapps/iotserver/test.jag new file mode 100755 index 00000000..c0097b63 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/test.jag @@ -0,0 +1,12 @@ +<% +var userModule = require("/modules/user.js").userModule; +userModule.addPermissions([{key: "device-mgt/", name: "Device Management"}], ""); +userModule.addPermissions([{key: "device-mgt/admin", name: "Device Management Admin"}], ""); +userModule.addPermissions([{key: "device-mgt/user", name: "Device Management User"}], ""); + +userModule.addPermissions([{key: "devices", name: "Device"}], "device-mgt/admin"); +userModule.addPermissions([{key: "devices", name: "Device"}], "device-mgt/user"); +userModule.addPermissions([{key: "devices/list", name: "List all Devices"}], "device-mgt/admin"); +userModule.addPermissions([{key: "devices/list", name: "List own Devices"}], "device-mgt/user"); +new Log().info(userModule.isAuthorized("/permission/device-mgt/admin/devices/list")); +%> \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/test/device-spec.js b/modules/distribution/src/repository/jaggeryapps/iotserver/test/device-spec.js new file mode 100755 index 00000000..f8ce2f3e --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/test/device-spec.js @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +describe('Device Module', function () { + var log = new Log(); + var mobileDB; + var cdmDB; + var deviceModule = require("/modules/device.js").deviceModule; + + function tearUp() { + mobileDB = new Database("MobileDM_DS"); + cdmDB = new Database("DM_DS"); + cdmDB.query("insert into dm_device(description, name, date_of_enrollment, date_of_last_update, " + + "ownership,status, device_type_id, device_identification, owner, tenant_id ) " + + "values ('Galaxy Tab','Admin Samsung', 1425467382, 1425467382, 'BYOD', 'ACTIVE'," + + " 1,'4892813d-0b18-4a02-b7b1-61775257488e', 'admin@wso2.com', '-1234');"); + cdmDB.query("insert into dm_device(description, name, date_of_enrollment, date_of_last_update, " + + "ownership,status, device_type_id, device_identification, owner, tenant_id ) " + + "values ('Galaxy Tab','Admin Samsung', 1425467382, 1425467382, 'BYOD', 'ACTIVE'," + + " 1,'4892813d-0b18-4a02-b7b1-61775257488F', 'mdm@wso2.com', '-1234');"); + + mobileDB.query("insert into mbl_device (mobile_device_id, push_token, imei ,imsi, os_version, " + + "device_model , vendor ,latitude ,longitude , challenge ,token, unlock_token ,serial ) " + + "values ('4892813d-0b18-4a02-b7b1-61775257488e', 'sdfsdf', 'cxv', 'vbcb', '4.1', " + + "'Galaxy Tab', 'Samsung', '234234234', '4345345234234', 'dfjsdlfk', 'wuweir234', " + + "'ksdfjlskfjwer', '234234');"); + mobileDB.query("insert into mbl_device (mobile_device_id, push_token, imei ,imsi, os_version, " + + "device_model , vendor ,latitude ,longitude , challenge ,token, unlock_token ,serial ) " + + "values ('4892813d-0b18-4a02-b7b1-61775257488F', 'sdfsdf', 'cxv', 'vbcb', '4.1', " + + "'Galaxy Tab', 'Samsung', '234234234', '4345345234234', 'dfjsdlfk', 'wuweir234', " + + "'ksdfjlskfjwer', '234234');"); + } + + function tearDown() { + deleteData(); + mobileDB.close(); + cdmDB.close(); + } + + function deleteData(){ + cdmDB.query("delete from dm_device where device_identification='4892813d-0b18-4a02-b7b1-61775257488e'"); + cdmDB.query("delete from dm_device where device_identification='4892813d-0b18-4a02-b7b1-61775257488F'"); + mobileDB.query("delete from mbl_device where mobile_device_id='4892813d-0b18-4a02-b7b1-61775257488e'"); + mobileDB.query("delete from mbl_device where mobile_device_id='4892813d-0b18-4a02-b7b1-61775257488F'"); + } + + it('List all Devices - Device Module', function () { + try { + tearUp(); + var results = deviceModule.listDevices(); + expect(results.length).not.toBe(0); + } catch (e) { + log.error(e); + throw e; + } finally { + tearDown(); + } + }); + it('List Devices for User - Device Module', function () { + try { + tearUp(); + var results = deviceModule.listDevicesForUser("mdm@wso2.com"); + expect(results.length).toBe(1); + } catch (e) { + log.error(e); + throw e; + } finally { + tearDown(); + } + }); + it('Perform operation on the device', function(){ + try { + tearUp(); + var devices = [{"id": "4892813d-0b18-4a02-b7b1-61775257488e", "type": "android"}]; + var operation = {"featureName": "DEVICE_LOCK", "type": "COMMAND", "properties": {"enabled": true}} + var results = deviceModule.performOperation(devices, operation); + expect(results.length).toBe(1); + } catch (e) { + log.error(e); + throw e; + } finally { + tearDown(); + } + }); +}); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/test/testExecutor.jag b/modules/distribution/src/repository/jaggeryapps/iotserver/test/testExecutor.jag old mode 100644 new mode 100755 diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/test/user-spec.js b/modules/distribution/src/repository/jaggeryapps/iotserver/test/user-spec.js new file mode 100755 index 00000000..5bbf7444 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/test/user-spec.js @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +describe('Device Module', function () { + var log = new Log(); + var mobileDB; + var cdmDB; + var deviceModule = require("/modules/device.js").deviceModule; + var userModule = require("/modules/user.js").userModule; + var constants = require("/modules/constants.js"); + function tearUp() { + mobileDB = new Database("MobileDM_DS"); + cdmDB = new Database("DM_DS"); + cdmDB.query("insert into dm_device(description, name, date_of_enrollment, date_of_last_update, " + + "ownership,status, device_type_id, device_identification, owner, tenant_id ) " + + "values ('Galaxy Tab','Admin Samsung', 1425467382, 1425467382, 'BYOD', 'ACTIVE'," + + " 1,'4892813d-0b18-4a02-b7b1-61775257488e', 'admin@wso2.com', '-1234');"); + cdmDB.query("insert into dm_device(description, name, date_of_enrollment, date_of_last_update, " + + "ownership,status, device_type_id, device_identification, owner, tenant_id ) " + + "values ('Galaxy Tab','Admin Samsung', 1425467382, 1425467382, 'BYOD', 'ACTIVE'," + + " 1,'4892813d-0b18-4a02-b7b1-61775257488F', 'mdm@wso2.com', '-1234');"); + + mobileDB.query("insert into mbl_device (mobile_device_id, push_token, imei ,imsi, os_version, " + + "device_model , vendor ,latitude ,longitude , challenge ,token, unlock_token ,serial ) " + + "values ('4892813d-0b18-4a02-b7b1-61775257488e', 'sdfsdf', 'cxv', 'vbcb', '4.1', " + + "'Galaxy Tab', 'Samsung', '234234234', '4345345234234', 'dfjsdlfk', 'wuweir234', " + + "'ksdfjlskfjwer', '234234');"); + mobileDB.query("insert into mbl_device (mobile_device_id, push_token, imei ,imsi, os_version, " + + "device_model , vendor ,latitude ,longitude , challenge ,token, unlock_token ,serial ) " + + "values ('4892813d-0b18-4a02-b7b1-61775257488F', 'sdfsdf', 'cxv', 'vbcb', '4.1', " + + "'Galaxy Tab', 'Samsung', '234234234', '4345345234234', 'dfjsdlfk', 'wuweir234', " + + "'ksdfjlskfjwer', '234234');"); + session.put(constants.USER_SESSION_KEY, {"username" : "admin", "domain": "carbon.super", "tenantId": "-1234"}); + } + + function tearDown() { + deleteData(); + mobileDB.close(); + cdmDB.close(); + session.put(constants.USER_SESSION_KEY, null); + } + + function deleteData(){ + cdmDB.query("delete from dm_device where device_identification='4892813d-0b18-4a02-b7b1-61775257488e'"); + cdmDB.query("delete from dm_device where device_identification='4892813d-0b18-4a02-b7b1-61775257488F'"); + mobileDB.query("delete from mbl_device where mobile_device_id='4892813d-0b18-4a02-b7b1-61775257488e'"); + mobileDB.query("delete from mbl_device where mobile_device_id='4892813d-0b18-4a02-b7b1-61775257488F'"); + } + + it('List all users', function () { + try { + tearUp(); + var results = userModule.getUsers(); + expect(results.length).not.toBe(0); + } catch (e) { + log.error(e); + throw e; + } finally { + tearDown(); + } + }); + it('Check permission for user', function () { + try { + tearUp(); + expect(userModule.isAuthorized("/permission/device-mgt/user/devices/list")).toBe(true); + } catch (e) { + log.error(e); + throw e; + } finally { + tearDown(); + } + }); +}); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/tmp/.gitignore b/modules/distribution/src/repository/jaggeryapps/iotserver/tmp/.gitignore new file mode 100755 index 00000000..50e166d6 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/tmp/.gitignore @@ -0,0 +1,5 @@ +# Ignore everything in this directory. +# they are auto generated, should not be committed. +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/token.jag b/modules/distribution/src/repository/jaggeryapps/iotserver/token.jag new file mode 100755 index 00000000..77778307 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/token.jag @@ -0,0 +1,4 @@ +<% +var apiWrapperUtil = require("/modules/api-wrapper-util.js").apiWrapperUtil; +apiWrapperUtil.refreshToken(); +%> \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android/android.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android/android.hbs similarity index 100% rename from modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android/android.hbs rename to modules/distribution/src/repository/jaggeryapps/iotserver/units/android/android.hbs diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/android/android.js b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android/android.js new file mode 100644 index 00000000..dae1a137 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android/android.js @@ -0,0 +1,4 @@ +function onRequest(context){ + context.sketchPath = "api/device/sketch/download"; + return context; +} diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android/android.json b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android/android.json similarity index 100% rename from modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android/android.json rename to modules/distribution/src/repository/jaggeryapps/iotserver/units/android/android.json diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android/public/images/android-thumb.png b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android/public/images/android-thumb.png similarity index 100% rename from modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android/public/images/android-thumb.png rename to modules/distribution/src/repository/jaggeryapps/iotserver/units/android/public/images/android-thumb.png diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android/public/images/android.png b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android/public/images/android.png similarity index 100% rename from modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android/public/images/android.png rename to modules/distribution/src/repository/jaggeryapps/iotserver/units/android/public/images/android.png diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android/public/store.json b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android/public/store.json similarity index 100% rename from modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android/public/store.json rename to modules/distribution/src/repository/jaggeryapps/iotserver/units/android/public/store.json diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android_sense/android_sense.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/android_sense.hbs similarity index 100% rename from modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android_sense/android_sense.hbs rename to modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/android_sense.hbs diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/android_sense.js b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/android_sense.js new file mode 100644 index 00000000..dae1a137 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/android_sense.js @@ -0,0 +1,4 @@ +function onRequest(context){ + context.sketchPath = "api/device/sketch/download"; + return context; +} diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android_sense/android_sense.json b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/android_sense.json similarity index 100% rename from modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android_sense/android_sense.json rename to modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/android_sense.json diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android_sense/public/images/android_sense-thumb.png b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/public/images/android_sense-thumb.png similarity index 100% rename from modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android_sense/public/images/android_sense-thumb.png rename to modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/public/images/android_sense-thumb.png diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android_sense/public/images/android_sense.png b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/public/images/android_sense.png similarity index 100% rename from modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android_sense/public/images/android_sense.png rename to modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/public/images/android_sense.png diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android_sense/public/store.json b/modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/public/store.json similarity index 100% rename from modules/distribution/src/repository/jaggeryapps/iotserver/units/devices/android_sense/public/store.json rename to modules/distribution/src/repository/jaggeryapps/iotserver/units/android_sense/public/store.json diff --git a/modules/distribution/src/repository/jaggeryapps/iotserver/units/appbar/appbar.hbs b/modules/distribution/src/repository/jaggeryapps/iotserver/units/appbar/appbar.hbs index e82f3989..4067deba 100644 --- a/modules/distribution/src/repository/jaggeryapps/iotserver/units/appbar/appbar.hbs +++ b/modules/distribution/src/repository/jaggeryapps/iotserver/units/appbar/appbar.hbs @@ -41,7 +41,7 @@
'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)0&&ithis.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.ythis.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'
    <% for (var i=0; i
  • <%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>
'};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/bulb.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/bulb.js deleted file mode 100644 index 72c40fd7..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/bulb.js +++ /dev/null @@ -1,10 +0,0 @@ -function changeImage() { - var image = document.getElementById('myImage'); - if (image.src.match("bulb-on")) { - - image.src = "/iot/public/mydevice/images/bulb-off.png"; - } else { - - image.src = "/iot/public/mydevice/images/bulb-on.png"; - } -} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/d3.min.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/d3.min.js deleted file mode 100644 index 43a29e23..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/d3.min.js +++ /dev/null @@ -1,9470 +0,0 @@ -!function() { - var d3 = { - version: "3.5.2" - }; - if (!Date.now) Date.now = function() { - return +new Date(); - }; - var d3_arraySlice = [].slice, d3_array = function(list) { - return d3_arraySlice.call(list); - }; - var d3_document = document, d3_documentElement = d3_document.documentElement, d3_window = window; - try { - d3_array(d3_documentElement.childNodes)[0].nodeType; - } catch (e) { - d3_array = function(list) { - var i = list.length, array = new Array(i); - while (i--) array[i] = list[i]; - return array; - }; - } - try { - d3_document.createElement("div").style.setProperty("opacity", 0, ""); - } catch (error) { - var d3_element_prototype = d3_window.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = d3_window.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; - d3_element_prototype.setAttribute = function(name, value) { - d3_element_setAttribute.call(this, name, value + ""); - }; - d3_element_prototype.setAttributeNS = function(space, local, value) { - d3_element_setAttributeNS.call(this, space, local, value + ""); - }; - d3_style_prototype.setProperty = function(name, value, priority) { - d3_style_setProperty.call(this, name, value + "", priority); - }; - } - d3.ascending = d3_ascending; - function d3_ascending(a, b) { - return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; - } - d3.descending = function(a, b) { - return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; - }; - d3.min = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = array[i]) != null && a > b) a = b; - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; - } - return a; - }; - d3.max = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = array[i]) != null && b > a) a = b; - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; - } - return a; - }; - d3.extent = function(array, f) { - var i = -1, n = array.length, a, b, c; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = c = b; - break; - } - while (++i < n) if ((b = array[i]) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = c = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } - return [ a, c ]; - }; - function d3_number(x) { - return x === null ? NaN : +x; - } - function d3_numeric(x) { - return !isNaN(x); - } - d3.sum = function(array, f) { - var s = 0, n = array.length, a, i = -1; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = +array[i])) s += a; - } else { - while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a; - } - return s; - }; - d3.mean = function(array, f) { - var s = 0, n = array.length, a, i = -1, j = n; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j; - } else { - while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j; - } - if (j) return s / j; - }; - d3.quantile = function(values, p) { - var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; - return e ? v + e * (values[h] - v) : v; - }; - d3.median = function(array, f) { - var numbers = [], n = array.length, a, i = -1; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a); - } else { - while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a); - } - if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5); - }; - d3.variance = function(array, f) { - var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0; - if (arguments.length === 1) { - while (++i < n) { - if (d3_numeric(a = d3_number(array[i]))) { - d = a - m; - m += d / ++j; - s += d * (a - m); - } - } - } else { - while (++i < n) { - if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) { - d = a - m; - m += d / ++j; - s += d * (a - m); - } - } - } - if (j > 1) return s / (j - 1); - }; - d3.deviation = function() { - var v = d3.variance.apply(this, arguments); - return v ? Math.sqrt(v) : v; - }; - function d3_bisector(compare) { - return { - left: function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid; - } - return lo; - }, - right: function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1; - } - return lo; - } - }; - } - var d3_bisect = d3_bisector(d3_ascending); - d3.bisectLeft = d3_bisect.left; - d3.bisect = d3.bisectRight = d3_bisect.right; - d3.bisector = function(f) { - return d3_bisector(f.length === 1 ? function(d, x) { - return d3_ascending(f(d), x); - } : f); - }; - d3.shuffle = function(array, i0, i1) { - if ((m = arguments.length) < 3) { - i1 = array.length; - if (m < 2) i0 = 0; - } - var m = i1 - i0, t, i; - while (m) { - i = Math.random() * m-- | 0; - t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t; - } - return array; - }; - d3.permute = function(array, indexes) { - var i = indexes.length, permutes = new Array(i); - while (i--) permutes[i] = array[indexes[i]]; - return permutes; - }; - d3.pairs = function(array) { - var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); - while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; - return pairs; - }; - d3.zip = function() { - if (!(n = arguments.length)) return []; - for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) { - for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) { - zip[j] = arguments[j][i]; - } - } - return zips; - }; - function d3_zipLength(d) { - return d.length; - } - d3.transpose = function(matrix) { - return d3.zip.apply(d3, matrix); - }; - d3.keys = function(map) { - var keys = []; - for (var key in map) keys.push(key); - return keys; - }; - d3.values = function(map) { - var values = []; - for (var key in map) values.push(map[key]); - return values; - }; - d3.entries = function(map) { - var entries = []; - for (var key in map) entries.push({ - key: key, - value: map[key] - }); - return entries; - }; - d3.merge = function(arrays) { - var n = arrays.length, m, i = -1, j = 0, merged, array; - while (++i < n) j += arrays[i].length; - merged = new Array(j); - while (--n >= 0) { - array = arrays[n]; - m = array.length; - while (--m >= 0) { - merged[--j] = array[m]; - } - } - return merged; - }; - var abs = Math.abs; - d3.range = function(start, stop, step) { - if (arguments.length < 3) { - step = 1; - if (arguments.length < 2) { - stop = start; - start = 0; - } - } - if ((stop - start) / step === Infinity) throw new Error("infinite range"); - var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; - start *= k, stop *= k, step *= k; - if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); - return range; - }; - function d3_range_integerScale(x) { - var k = 1; - while (x * k % 1) k *= 10; - return k; - } - function d3_class(ctor, properties) { - for (var key in properties) { - Object.defineProperty(ctor.prototype, key, { - value: properties[key], - enumerable: false - }); - } - } - d3.map = function(object, f) { - var map = new d3_Map(); - if (object instanceof d3_Map) { - object.forEach(function(key, value) { - map.set(key, value); - }); - } else if (Array.isArray(object)) { - var i = -1, n = object.length, o; - if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o); - } else { - for (var key in object) map.set(key, object[key]); - } - return map; - }; - function d3_Map() { - this._ = Object.create(null); - } - var d3_map_proto = "__proto__", d3_map_zero = "\x00"; - d3_class(d3_Map, { - has: d3_map_has, - get: function(key) { - return this._[d3_map_escape(key)]; - }, - set: function(key, value) { - return this._[d3_map_escape(key)] = value; - }, - remove: d3_map_remove, - keys: d3_map_keys, - values: function() { - var values = []; - for (var key in this._) values.push(this._[key]); - return values; - }, - entries: function() { - var entries = []; - for (var key in this._) entries.push({ - key: d3_map_unescape(key), - value: this._[key] - }); - return entries; - }, - size: d3_map_size, - empty: d3_map_empty, - forEach: function(f) { - for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]); - } - }); - function d3_map_escape(key) { - return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key; - } - function d3_map_unescape(key) { - return (key += "")[0] === d3_map_zero ? key.slice(1) : key; - } - function d3_map_has(key) { - return d3_map_escape(key) in this._; - } - function d3_map_remove(key) { - return (key = d3_map_escape(key)) in this._ && delete this._[key]; - } - function d3_map_keys() { - var keys = []; - for (var key in this._) keys.push(d3_map_unescape(key)); - return keys; - } - function d3_map_size() { - var size = 0; - for (var key in this._) ++size; - return size; - } - function d3_map_empty() { - for (var key in this._) return false; - return true; - } - d3.nest = function() { - var nest = {}, keys = [], sortKeys = [], sortValues, rollup; - function map(mapType, array, depth) { - if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; - var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; - while (++i < n) { - if (values = valuesByKey.get(keyValue = key(object = array[i]))) { - values.push(object); - } else { - valuesByKey.set(keyValue, [ object ]); - } - } - if (mapType) { - object = mapType(); - setter = function(keyValue, values) { - object.set(keyValue, map(mapType, values, depth)); - }; - } else { - object = {}; - setter = function(keyValue, values) { - object[keyValue] = map(mapType, values, depth); - }; - } - valuesByKey.forEach(setter); - return object; - } - function entries(map, depth) { - if (depth >= keys.length) return map; - var array = [], sortKey = sortKeys[depth++]; - map.forEach(function(key, keyMap) { - array.push({ - key: key, - values: entries(keyMap, depth) - }); - }); - return sortKey ? array.sort(function(a, b) { - return sortKey(a.key, b.key); - }) : array; - } - nest.map = function(array, mapType) { - return map(mapType, array, 0); - }; - nest.entries = function(array) { - return entries(map(d3.map, array, 0), 0); - }; - nest.key = function(d) { - keys.push(d); - return nest; - }; - nest.sortKeys = function(order) { - sortKeys[keys.length - 1] = order; - return nest; - }; - nest.sortValues = function(order) { - sortValues = order; - return nest; - }; - nest.rollup = function(f) { - rollup = f; - return nest; - }; - return nest; - }; - d3.set = function(array) { - var set = new d3_Set(); - if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); - return set; - }; - function d3_Set() { - this._ = Object.create(null); - } - d3_class(d3_Set, { - has: d3_map_has, - add: function(key) { - this._[d3_map_escape(key += "")] = true; - return key; - }, - remove: d3_map_remove, - values: d3_map_keys, - size: d3_map_size, - empty: d3_map_empty, - forEach: function(f) { - for (var key in this._) f.call(this, d3_map_unescape(key)); - } - }); - d3.behavior = {}; - d3.rebind = function(target, source) { - var i = 1, n = arguments.length, method; - while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); - return target; - }; - function d3_rebind(target, source, method) { - return function() { - var value = method.apply(source, arguments); - return value === source ? target : value; - }; - } - function d3_vendorSymbol(object, name) { - if (name in object) return name; - name = name.charAt(0).toUpperCase() + name.slice(1); - for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { - var prefixName = d3_vendorPrefixes[i] + name; - if (prefixName in object) return prefixName; - } - } - var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; - function d3_noop() {} - d3.dispatch = function() { - var dispatch = new d3_dispatch(), i = -1, n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); - return dispatch; - }; - function d3_dispatch() {} - d3_dispatch.prototype.on = function(type, listener) { - var i = type.indexOf("."), name = ""; - if (i >= 0) { - name = type.slice(i + 1); - type = type.slice(0, i); - } - if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); - if (arguments.length === 2) { - if (listener == null) for (type in this) { - if (this.hasOwnProperty(type)) this[type].on(name, null); - } - return this; - } - }; - function d3_dispatch_event(dispatch) { - var listeners = [], listenerByName = new d3_Map(); - function event() { - var z = listeners, i = -1, n = z.length, l; - while (++i < n) if (l = z[i].on) l.apply(this, arguments); - return dispatch; - } - event.on = function(name, listener) { - var l = listenerByName.get(name), i; - if (arguments.length < 2) return l && l.on; - if (l) { - l.on = null; - listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); - listenerByName.remove(name); - } - if (listener) listeners.push(listenerByName.set(name, { - on: listener - })); - return dispatch; - }; - return event; - } - d3.event = null; - function d3_eventPreventDefault() { - d3.event.preventDefault(); - } - function d3_eventSource() { - var e = d3.event, s; - while (s = e.sourceEvent) e = s; - return e; - } - function d3_eventDispatch(target) { - var dispatch = new d3_dispatch(), i = 0, n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); - dispatch.of = function(thiz, argumentz) { - return function(e1) { - try { - var e0 = e1.sourceEvent = d3.event; - e1.target = target; - d3.event = e1; - dispatch[e1.type].apply(thiz, argumentz); - } finally { - d3.event = e0; - } - }; - }; - return dispatch; - } - d3.requote = function(s) { - return s.replace(d3_requote_re, "\\$&"); - }; - var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; - var d3_subclass = {}.__proto__ ? function(object, prototype) { - object.__proto__ = prototype; - } : function(object, prototype) { - for (var property in prototype) object[property] = prototype[property]; - }; - function d3_selection(groups) { - d3_subclass(groups, d3_selectionPrototype); - return groups; - } - var d3_select = function(s, n) { - return n.querySelector(s); - }, d3_selectAll = function(s, n) { - return n.querySelectorAll(s); - }, d3_selectMatcher = d3_documentElement.matches || d3_documentElement[d3_vendorSymbol(d3_documentElement, "matchesSelector")], d3_selectMatches = function(n, s) { - return d3_selectMatcher.call(n, s); - }; - if (typeof Sizzle === "function") { - d3_select = function(s, n) { - return Sizzle(s, n)[0] || null; - }; - d3_selectAll = Sizzle; - d3_selectMatches = Sizzle.matchesSelector; - } - d3.selection = function() { - return d3_selectionRoot; - }; - var d3_selectionPrototype = d3.selection.prototype = []; - d3_selectionPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, group, node; - selector = d3_selection_selector(selector); - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroup.push(subnode = selector.call(node, node.__data__, i, j)); - if (subnode && "__data__" in node) subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selector(selector) { - return typeof selector === "function" ? selector : function() { - return d3_select(selector, this); - }; - } - d3_selectionPrototype.selectAll = function(selector) { - var subgroups = [], subgroup, node; - selector = d3_selection_selectorAll(selector); - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); - subgroup.parentNode = node; - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selectorAll(selector) { - return typeof selector === "function" ? selector : function() { - return d3_selectAll(selector, this); - }; - } - var d3_nsPrefix = { - svg: "http://www.w3.org/2000/svg", - xhtml: "http://www.w3.org/1999/xhtml", - xlink: "http://www.w3.org/1999/xlink", - xml: "http://www.w3.org/XML/1998/namespace", - xmlns: "http://www.w3.org/2000/xmlns/" - }; - d3.ns = { - prefix: d3_nsPrefix, - qualify: function(name) { - var i = name.indexOf(":"), prefix = name; - if (i >= 0) { - prefix = name.slice(0, i); - name = name.slice(i + 1); - } - return d3_nsPrefix.hasOwnProperty(prefix) ? { - space: d3_nsPrefix[prefix], - local: name - } : name; - } - }; - d3_selectionPrototype.attr = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(); - name = d3.ns.qualify(name); - return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); - } - for (value in name) this.each(d3_selection_attr(value, name[value])); - return this; - } - return this.each(d3_selection_attr(name, value)); - }; - function d3_selection_attr(name, value) { - name = d3.ns.qualify(name); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - function attrConstant() { - this.setAttribute(name, value); - } - function attrConstantNS() { - this.setAttributeNS(name.space, name.local, value); - } - function attrFunction() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); - } - function attrFunctionNS() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); - } - return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; - } - function d3_collapse(s) { - return s.trim().replace(/\s+/g, " "); - } - d3_selectionPrototype.classed = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; - if (value = node.classList) { - while (++i < n) if (!value.contains(name[i])) return false; - } else { - value = node.getAttribute("class"); - while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; - } - return true; - } - for (value in name) this.each(d3_selection_classed(value, name[value])); - return this; - } - return this.each(d3_selection_classed(name, value)); - }; - function d3_selection_classedRe(name) { - return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); - } - function d3_selection_classes(name) { - return (name + "").trim().split(/^|\s+/); - } - function d3_selection_classed(name, value) { - name = d3_selection_classes(name).map(d3_selection_classedName); - var n = name.length; - function classedConstant() { - var i = -1; - while (++i < n) name[i](this, value); - } - function classedFunction() { - var i = -1, x = value.apply(this, arguments); - while (++i < n) name[i](this, x); - } - return typeof value === "function" ? classedFunction : classedConstant; - } - function d3_selection_classedName(name) { - var re = d3_selection_classedRe(name); - return function(node, value) { - if (c = node.classList) return value ? c.add(name) : c.remove(name); - var c = node.getAttribute("class") || ""; - if (value) { - re.lastIndex = 0; - if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); - } else { - node.setAttribute("class", d3_collapse(c.replace(re, " "))); - } - }; - } - d3_selectionPrototype.style = function(name, value, priority) { - var n = arguments.length; - if (n < 3) { - if (typeof name !== "string") { - if (n < 2) value = ""; - for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); - return this; - } - if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name); - priority = ""; - } - return this.each(d3_selection_style(name, value, priority)); - }; - function d3_selection_style(name, value, priority) { - function styleNull() { - this.style.removeProperty(name); - } - function styleConstant() { - this.style.setProperty(name, value, priority); - } - function styleFunction() { - var x = value.apply(this, arguments); - if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); - } - return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; - } - d3_selectionPrototype.property = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") return this.node()[name]; - for (value in name) this.each(d3_selection_property(value, name[value])); - return this; - } - return this.each(d3_selection_property(name, value)); - }; - function d3_selection_property(name, value) { - function propertyNull() { - delete this[name]; - } - function propertyConstant() { - this[name] = value; - } - function propertyFunction() { - var x = value.apply(this, arguments); - if (x == null) delete this[name]; else this[name] = x; - } - return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; - } - d3_selectionPrototype.text = function(value) { - return arguments.length ? this.each(typeof value === "function" ? function() { - var v = value.apply(this, arguments); - this.textContent = v == null ? "" : v; - } : value == null ? function() { - this.textContent = ""; - } : function() { - this.textContent = value; - }) : this.node().textContent; - }; - d3_selectionPrototype.html = function(value) { - return arguments.length ? this.each(typeof value === "function" ? function() { - var v = value.apply(this, arguments); - this.innerHTML = v == null ? "" : v; - } : value == null ? function() { - this.innerHTML = ""; - } : function() { - this.innerHTML = value; - }) : this.node().innerHTML; - }; - d3_selectionPrototype.append = function(name) { - name = d3_selection_creator(name); - return this.select(function() { - return this.appendChild(name.apply(this, arguments)); - }); - }; - function d3_selection_creator(name) { - return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? function() { - return this.ownerDocument.createElementNS(name.space, name.local); - } : function() { - return this.ownerDocument.createElementNS(this.namespaceURI, name); - }; - } - d3_selectionPrototype.insert = function(name, before) { - name = d3_selection_creator(name); - before = d3_selection_selector(before); - return this.select(function() { - return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); - }); - }; - d3_selectionPrototype.remove = function() { - return this.each(d3_selectionRemove); - }; - function d3_selectionRemove() { - var parent = this.parentNode; - if (parent) parent.removeChild(this); - } - d3_selectionPrototype.data = function(value, key) { - var i = -1, n = this.length, group, node; - if (!arguments.length) { - value = new Array(n = (group = this[0]).length); - while (++i < n) { - if (node = group[i]) { - value[i] = node.__data__; - } - } - return value; - } - function bind(group, groupData) { - var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; - if (key) { - var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue; - for (i = -1; ++i < n; ) { - if (nodeByKeyValue.has(keyValue = key.call(node = group[i], node.__data__, i))) { - exitNodes[i] = node; - } else { - nodeByKeyValue.set(keyValue, node); - } - keyValues[i] = keyValue; - } - for (i = -1; ++i < m; ) { - if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) { - enterNodes[i] = d3_selection_dataNode(nodeData); - } else if (node !== true) { - updateNodes[i] = node; - node.__data__ = nodeData; - } - nodeByKeyValue.set(keyValue, true); - } - for (i = -1; ++i < n; ) { - if (nodeByKeyValue.get(keyValues[i]) !== true) { - exitNodes[i] = group[i]; - } - } - } else { - for (i = -1; ++i < n0; ) { - node = group[i]; - nodeData = groupData[i]; - if (node) { - node.__data__ = nodeData; - updateNodes[i] = node; - } else { - enterNodes[i] = d3_selection_dataNode(nodeData); - } - } - for (;i < m; ++i) { - enterNodes[i] = d3_selection_dataNode(groupData[i]); - } - for (;i < n; ++i) { - exitNodes[i] = group[i]; - } - } - enterNodes.update = updateNodes; - enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; - enter.push(enterNodes); - update.push(updateNodes); - exit.push(exitNodes); - } - var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); - if (typeof value === "function") { - while (++i < n) { - bind(group = this[i], value.call(group, group.parentNode.__data__, i)); - } - } else { - while (++i < n) { - bind(group = this[i], value); - } - } - update.enter = function() { - return enter; - }; - update.exit = function() { - return exit; - }; - return update; - }; - function d3_selection_dataNode(data) { - return { - __data__: data - }; - } - d3_selectionPrototype.datum = function(value) { - return arguments.length ? this.property("__data__", value) : this.property("__data__"); - }; - d3_selectionPrototype.filter = function(filter) { - var subgroups = [], subgroup, group, node; - if (typeof filter !== "function") filter = d3_selection_filter(filter); - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { - subgroup.push(node); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_filter(selector) { - return function() { - return d3_selectMatches(this, selector); - }; - } - d3_selectionPrototype.order = function() { - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { - if (node = group[i]) { - if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); - next = node; - } - } - } - return this; - }; - d3_selectionPrototype.sort = function(comparator) { - comparator = d3_selection_sortComparator.apply(this, arguments); - for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); - return this.order(); - }; - function d3_selection_sortComparator(comparator) { - if (!arguments.length) comparator = d3_ascending; - return function(a, b) { - return a && b ? comparator(a.__data__, b.__data__) : !a - !b; - }; - } - d3_selectionPrototype.each = function(callback) { - return d3_selection_each(this, function(node, i, j) { - callback.call(node, node.__data__, i, j); - }); - }; - function d3_selection_each(groups, callback) { - for (var j = 0, m = groups.length; j < m; j++) { - for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { - if (node = group[i]) callback(node, i, j); - } - } - return groups; - } - d3_selectionPrototype.call = function(callback) { - var args = d3_array(arguments); - callback.apply(args[0] = this, args); - return this; - }; - d3_selectionPrototype.empty = function() { - return !this.node(); - }; - d3_selectionPrototype.node = function() { - for (var j = 0, m = this.length; j < m; j++) { - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - var node = group[i]; - if (node) return node; - } - } - return null; - }; - d3_selectionPrototype.size = function() { - var n = 0; - d3_selection_each(this, function() { - ++n; - }); - return n; - }; - function d3_selection_enter(selection) { - d3_subclass(selection, d3_selection_enterPrototype); - return selection; - } - var d3_selection_enterPrototype = []; - d3.selection.enter = d3_selection_enter; - d3.selection.enter.prototype = d3_selection_enterPrototype; - d3_selection_enterPrototype.append = d3_selectionPrototype.append; - d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; - d3_selection_enterPrototype.node = d3_selectionPrototype.node; - d3_selection_enterPrototype.call = d3_selectionPrototype.call; - d3_selection_enterPrototype.size = d3_selectionPrototype.size; - d3_selection_enterPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, upgroup, group, node; - for (var j = -1, m = this.length; ++j < m; ) { - upgroup = (group = this[j]).update; - subgroups.push(subgroup = []); - subgroup.parentNode = group.parentNode; - for (var i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); - subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - d3_selection_enterPrototype.insert = function(name, before) { - if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); - return d3_selectionPrototype.insert.call(this, name, before); - }; - function d3_selection_enterInsertBefore(enter) { - var i0, j0; - return function(d, i, j) { - var group = enter[j].update, n = group.length, node; - if (j != j0) j0 = j, i0 = 0; - if (i >= i0) i0 = i + 1; - while (!(node = group[i0]) && ++i0 < n) ; - return node; - }; - } - d3.select = function(node) { - var group = [ typeof node === "string" ? d3_select(node, d3_document) : node ]; - group.parentNode = d3_documentElement; - return d3_selection([ group ]); - }; - d3.selectAll = function(nodes) { - var group = d3_array(typeof nodes === "string" ? d3_selectAll(nodes, d3_document) : nodes); - group.parentNode = d3_documentElement; - return d3_selection([ group ]); - }; - var d3_selectionRoot = d3.select(d3_documentElement); - d3_selectionPrototype.on = function(type, listener, capture) { - var n = arguments.length; - if (n < 3) { - if (typeof type !== "string") { - if (n < 2) listener = false; - for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); - return this; - } - if (n < 2) return (n = this.node()["__on" + type]) && n._; - capture = false; - } - return this.each(d3_selection_on(type, listener, capture)); - }; - function d3_selection_on(type, listener, capture) { - var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; - if (i > 0) type = type.slice(0, i); - var filter = d3_selection_onFilters.get(type); - if (filter) type = filter, wrap = d3_selection_onFilter; - function onRemove() { - var l = this[name]; - if (l) { - this.removeEventListener(type, l, l.$); - delete this[name]; - } - } - function onAdd() { - var l = wrap(listener, d3_array(arguments)); - onRemove.call(this); - this.addEventListener(type, this[name] = l, l.$ = capture); - l._ = listener; - } - function removeAll() { - var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; - for (var name in this) { - if (match = name.match(re)) { - var l = this[name]; - this.removeEventListener(match[1], l, l.$); - delete this[name]; - } - } - } - return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; - } - var d3_selection_onFilters = d3.map({ - mouseenter: "mouseover", - mouseleave: "mouseout" - }); - d3_selection_onFilters.forEach(function(k) { - if ("on" + k in d3_document) d3_selection_onFilters.remove(k); - }); - function d3_selection_onListener(listener, argumentz) { - return function(e) { - var o = d3.event; - d3.event = e; - argumentz[0] = this.__data__; - try { - listener.apply(this, argumentz); - } finally { - d3.event = o; - } - }; - } - function d3_selection_onFilter(listener, argumentz) { - var l = d3_selection_onListener(listener, argumentz); - return function(e) { - var target = this, related = e.relatedTarget; - if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { - l.call(target, e); - } - }; - } - var d3_event_dragSelect = "onselectstart" in d3_document ? null : d3_vendorSymbol(d3_documentElement.style, "userSelect"), d3_event_dragId = 0; - function d3_event_dragSuppress() { - var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); - if (d3_event_dragSelect) { - var style = d3_documentElement.style, select = style[d3_event_dragSelect]; - style[d3_event_dragSelect] = "none"; - } - return function(suppressClick) { - w.on(name, null); - if (d3_event_dragSelect) style[d3_event_dragSelect] = select; - if (suppressClick) { - var off = function() { - w.on(click, null); - }; - w.on(click, function() { - d3_eventPreventDefault(); - off(); - }, true); - setTimeout(off, 0); - } - }; - } - d3.mouse = function(container) { - return d3_mousePoint(container, d3_eventSource()); - }; - var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0; - function d3_mousePoint(container, e) { - if (e.changedTouches) e = e.changedTouches[0]; - var svg = container.ownerSVGElement || container; - if (svg.createSVGPoint) { - var point = svg.createSVGPoint(); - if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) { - svg = d3.select("body").append("svg").style({ - position: "absolute", - top: 0, - left: 0, - margin: 0, - padding: 0, - border: "none" - }, "important"); - var ctm = svg[0][0].getScreenCTM(); - d3_mouse_bug44083 = !(ctm.f || ctm.e); - svg.remove(); - } - if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, - point.y = e.clientY; - point = point.matrixTransform(container.getScreenCTM().inverse()); - return [ point.x, point.y ]; - } - var rect = container.getBoundingClientRect(); - return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; - } - d3.touch = function(container, touches, identifier) { - if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches; - if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) { - if ((touch = touches[i]).identifier === identifier) { - return d3_mousePoint(container, touch); - } - } - }; - d3.behavior.drag = function() { - var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_behavior_dragMouseSubject, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_behavior_dragTouchSubject, "touchmove", "touchend"); - function drag() { - this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); - } - function dragstart(id, position, subject, move, end) { - return function() { - var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject()).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(), position0 = position(parent, dragId); - if (origin) { - dragOffset = origin.apply(that, arguments); - dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ]; - } else { - dragOffset = [ 0, 0 ]; - } - dispatch({ - type: "dragstart" - }); - function moved() { - var position1 = position(parent, dragId), dx, dy; - if (!position1) return; - dx = position1[0] - position0[0]; - dy = position1[1] - position0[1]; - dragged |= dx | dy; - position0 = position1; - dispatch({ - type: "drag", - x: position1[0] + dragOffset[0], - y: position1[1] + dragOffset[1], - dx: dx, - dy: dy - }); - } - function ended() { - if (!position(parent, dragId)) return; - dragSubject.on(move + dragName, null).on(end + dragName, null); - dragRestore(dragged && d3.event.target === target); - dispatch({ - type: "dragend" - }); - } - }; - } - drag.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return drag; - }; - return d3.rebind(drag, event, "on"); - }; - function d3_behavior_dragTouchId() { - return d3.event.changedTouches[0].identifier; - } - function d3_behavior_dragTouchSubject() { - return d3.event.target; - } - function d3_behavior_dragMouseSubject() { - return d3_window; - } - d3.touches = function(container, touches) { - if (arguments.length < 2) touches = d3_eventSource().touches; - return touches ? d3_array(touches).map(function(touch) { - var point = d3_mousePoint(container, touch); - point.identifier = touch.identifier; - return point; - }) : []; - }; - var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π; - function d3_sgn(x) { - return x > 0 ? 1 : x < 0 ? -1 : 0; - } - function d3_cross2d(a, b, c) { - return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); - } - function d3_acos(x) { - return x > 1 ? 0 : x < -1 ? π : Math.acos(x); - } - function d3_asin(x) { - return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); - } - function d3_sinh(x) { - return ((x = Math.exp(x)) - 1 / x) / 2; - } - function d3_cosh(x) { - return ((x = Math.exp(x)) + 1 / x) / 2; - } - function d3_tanh(x) { - return ((x = Math.exp(2 * x)) - 1) / (x + 1); - } - function d3_haversin(x) { - return (x = Math.sin(x / 2)) * x; - } - var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4; - d3.interpolateZoom = function(p0, p1) { - var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2]; - var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / ρ; - function interpolate(t) { - var s = t * S; - if (dr) { - var coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0)); - return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ]; - } - return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * s) ]; - } - interpolate.duration = S * 1e3; - return interpolate; - }; - d3.behavior.zoom = function() { - var view = { - x: 0, - y: 0, - k: 1 - }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; - function zoom(g) { - g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); - } - zoom.event = function(g) { - g.each(function() { - var dispatch = event.of(this, arguments), view1 = view; - if (d3_transitionInheritId) { - d3.select(this).transition().each("start.zoom", function() { - view = this.__chart__ || { - x: 0, - y: 0, - k: 1 - }; - zoomstarted(dispatch); - }).tween("zoom:zoom", function() { - var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); - return function(t) { - var l = i(t), k = dx / l[2]; - this.__chart__ = view = { - x: cx - l[0] * k, - y: cy - l[1] * k, - k: k - }; - zoomed(dispatch); - }; - }).each("interrupt.zoom", function() { - zoomended(dispatch); - }).each("end.zoom", function() { - zoomended(dispatch); - }); - } else { - this.__chart__ = view; - zoomstarted(dispatch); - zoomed(dispatch); - zoomended(dispatch); - } - }); - }; - zoom.translate = function(_) { - if (!arguments.length) return [ view.x, view.y ]; - view = { - x: +_[0], - y: +_[1], - k: view.k - }; - rescale(); - return zoom; - }; - zoom.scale = function(_) { - if (!arguments.length) return view.k; - view = { - x: view.x, - y: view.y, - k: +_ - }; - rescale(); - return zoom; - }; - zoom.scaleExtent = function(_) { - if (!arguments.length) return scaleExtent; - scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; - return zoom; - }; - zoom.center = function(_) { - if (!arguments.length) return center; - center = _ && [ +_[0], +_[1] ]; - return zoom; - }; - zoom.size = function(_) { - if (!arguments.length) return size; - size = _ && [ +_[0], +_[1] ]; - return zoom; - }; - zoom.duration = function(_) { - if (!arguments.length) return duration; - duration = +_; - return zoom; - }; - zoom.x = function(z) { - if (!arguments.length) return x1; - x1 = z; - x0 = z.copy(); - view = { - x: 0, - y: 0, - k: 1 - }; - return zoom; - }; - zoom.y = function(z) { - if (!arguments.length) return y1; - y1 = z; - y0 = z.copy(); - view = { - x: 0, - y: 0, - k: 1 - }; - return zoom; - }; - function location(p) { - return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; - } - function point(l) { - return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; - } - function scaleTo(s) { - view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); - } - function translateTo(p, l) { - l = point(l); - view.x += p[0] - l[0]; - view.y += p[1] - l[1]; - } - function zoomTo(that, p, l, k) { - that.__chart__ = { - x: view.x, - y: view.y, - k: view.k - }; - scaleTo(Math.pow(2, k)); - translateTo(center0 = p, l); - that = d3.select(that); - if (duration > 0) that = that.transition().duration(duration); - that.call(zoom.event); - } - function rescale() { - if (x1) x1.domain(x0.range().map(function(x) { - return (x - view.x) / view.k; - }).map(x0.invert)); - if (y1) y1.domain(y0.range().map(function(y) { - return (y - view.y) / view.k; - }).map(y0.invert)); - } - function zoomstarted(dispatch) { - if (!zooming++) dispatch({ - type: "zoomstart" - }); - } - function zoomed(dispatch) { - rescale(); - dispatch({ - type: "zoom", - scale: view.k, - translate: [ view.x, view.y ] - }); - } - function zoomended(dispatch) { - if (!--zooming) dispatch({ - type: "zoomend" - }); - center0 = null; - } - function mousedowned() { - var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(); - d3_selection_interrupt.call(that); - zoomstarted(dispatch); - function moved() { - dragged = 1; - translateTo(d3.mouse(that), location0); - zoomed(dispatch); - } - function ended() { - subject.on(mousemove, null).on(mouseup, null); - dragRestore(dragged && d3.event.target === target); - zoomended(dispatch); - } - } - function touchstarted() { - var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(); - started(); - zoomstarted(dispatch); - subject.on(mousedown, null).on(touchstart, started); - function relocate() { - var touches = d3.touches(that); - scale0 = view.k; - touches.forEach(function(t) { - if (t.identifier in locations0) locations0[t.identifier] = location(t); - }); - return touches; - } - function started() { - var target = d3.event.target; - d3.select(target).on(touchmove, moved).on(touchend, ended); - targets.push(target); - var changed = d3.event.changedTouches; - for (var i = 0, n = changed.length; i < n; ++i) { - locations0[changed[i].identifier] = null; - } - var touches = relocate(), now = Date.now(); - if (touches.length === 1) { - if (now - touchtime < 500) { - var p = touches[0]; - zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1); - d3_eventPreventDefault(); - } - touchtime = now; - } else if (touches.length > 1) { - var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; - distance0 = dx * dx + dy * dy; - } - } - function moved() { - var touches = d3.touches(that), p0, l0, p1, l1; - d3_selection_interrupt.call(that); - for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { - p1 = touches[i]; - if (l1 = locations0[p1.identifier]) { - if (l0) break; - p0 = p1, l0 = l1; - } - } - if (l1) { - var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); - p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; - l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; - scaleTo(scale1 * scale0); - } - touchtime = null; - translateTo(p0, l0); - zoomed(dispatch); - } - function ended() { - if (d3.event.touches.length) { - var changed = d3.event.changedTouches; - for (var i = 0, n = changed.length; i < n; ++i) { - delete locations0[changed[i].identifier]; - } - for (var identifier in locations0) { - return void relocate(); - } - } - d3.selectAll(targets).on(zoomName, null); - subject.on(mousedown, mousedowned).on(touchstart, touchstarted); - dragRestore(); - zoomended(dispatch); - } - } - function mousewheeled() { - var dispatch = event.of(this, arguments); - if (mousewheelTimer) clearTimeout(mousewheelTimer); else translate0 = location(center0 = center || d3.mouse(this)), - d3_selection_interrupt.call(this), zoomstarted(dispatch); - mousewheelTimer = setTimeout(function() { - mousewheelTimer = null; - zoomended(dispatch); - }, 50); - d3_eventPreventDefault(); - scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); - translateTo(center0, translate0); - zoomed(dispatch); - } - function dblclicked() { - var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2; - zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1); - } - return d3.rebind(zoom, event, "on"); - }; - var d3_behavior_zoomInfinity = [ 0, Infinity ]; - var d3_behavior_zoomDelta, d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { - return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); - }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { - return d3.event.wheelDelta; - }, "mousewheel") : (d3_behavior_zoomDelta = function() { - return -d3.event.detail; - }, "MozMousePixelScroll"); - d3.color = d3_color; - function d3_color() {} - d3_color.prototype.toString = function() { - return this.rgb() + ""; - }; - d3.hsl = d3_hsl; - function d3_hsl(h, s, l) { - return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l); - } - var d3_hslPrototype = d3_hsl.prototype = new d3_color(); - d3_hslPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_hsl(this.h, this.s, this.l / k); - }; - d3_hslPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_hsl(this.h, this.s, k * this.l); - }; - d3_hslPrototype.rgb = function() { - return d3_hsl_rgb(this.h, this.s, this.l); - }; - function d3_hsl_rgb(h, s, l) { - var m1, m2; - h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; - s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; - l = l < 0 ? 0 : l > 1 ? 1 : l; - m2 = l <= .5 ? l * (1 + s) : l + s - l * s; - m1 = 2 * l - m2; - function v(h) { - if (h > 360) h -= 360; else if (h < 0) h += 360; - if (h < 60) return m1 + (m2 - m1) * h / 60; - if (h < 180) return m2; - if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; - return m1; - } - function vv(h) { - return Math.round(v(h) * 255); - } - return new d3_rgb(vv(h + 120), vv(h), vv(h - 120)); - } - d3.hcl = d3_hcl; - function d3_hcl(h, c, l) { - return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l); - } - var d3_hclPrototype = d3_hcl.prototype = new d3_color(); - d3_hclPrototype.brighter = function(k) { - return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.darker = function(k) { - return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.rgb = function() { - return d3_hcl_lab(this.h, this.c, this.l).rgb(); - }; - function d3_hcl_lab(h, c, l) { - if (isNaN(h)) h = 0; - if (isNaN(c)) c = 0; - return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); - } - d3.lab = d3_lab; - function d3_lab(l, a, b) { - return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b); - } - var d3_lab_K = 18; - var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; - var d3_labPrototype = d3_lab.prototype = new d3_color(); - d3_labPrototype.brighter = function(k) { - return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); - }; - d3_labPrototype.darker = function(k) { - return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); - }; - d3_labPrototype.rgb = function() { - return d3_lab_rgb(this.l, this.a, this.b); - }; - function d3_lab_rgb(l, a, b) { - var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; - x = d3_lab_xyz(x) * d3_lab_X; - y = d3_lab_xyz(y) * d3_lab_Y; - z = d3_lab_xyz(z) * d3_lab_Z; - return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); - } - function d3_lab_hcl(l, a, b) { - return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l); - } - function d3_lab_xyz(x) { - return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; - } - function d3_xyz_lab(x) { - return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; - } - function d3_xyz_rgb(r) { - return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); - } - d3.rgb = d3_rgb; - function d3_rgb(r, g, b) { - return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b); - } - function d3_rgbNumber(value) { - return new d3_rgb(value >> 16, value >> 8 & 255, value & 255); - } - function d3_rgbString(value) { - return d3_rgbNumber(value) + ""; - } - var d3_rgbPrototype = d3_rgb.prototype = new d3_color(); - d3_rgbPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - var r = this.r, g = this.g, b = this.b, i = 30; - if (!r && !g && !b) return new d3_rgb(i, i, i); - if (r && r < i) r = i; - if (g && g < i) g = i; - if (b && b < i) b = i; - return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k)); - }; - d3_rgbPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_rgb(k * this.r, k * this.g, k * this.b); - }; - d3_rgbPrototype.hsl = function() { - return d3_rgb_hsl(this.r, this.g, this.b); - }; - d3_rgbPrototype.toString = function() { - return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); - }; - function d3_rgb_hex(v) { - return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); - } - function d3_rgb_parse(format, rgb, hsl) { - var r = 0, g = 0, b = 0, m1, m2, color; - m1 = /([a-z]+)\((.*)\)/i.exec(format); - if (m1) { - m2 = m1[2].split(","); - switch (m1[1]) { - case "hsl": - { - return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); - } - - case "rgb": - { - return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); - } - } - } - if (color = d3_rgb_names.get(format)) return rgb(color.r, color.g, color.b); - if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) { - if (format.length === 4) { - r = (color & 3840) >> 4; - r = r >> 4 | r; - g = color & 240; - g = g >> 4 | g; - b = color & 15; - b = b << 4 | b; - } else if (format.length === 7) { - r = (color & 16711680) >> 16; - g = (color & 65280) >> 8; - b = color & 255; - } - } - return rgb(r, g, b); - } - function d3_rgb_hsl(r, g, b) { - var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; - if (d) { - s = l < .5 ? d / (max + min) : d / (2 - max - min); - if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; - h *= 60; - } else { - h = NaN; - s = l > 0 && l < 1 ? 0 : h; - } - return new d3_hsl(h, s, l); - } - function d3_rgb_lab(r, g, b) { - r = d3_rgb_xyz(r); - g = d3_rgb_xyz(g); - b = d3_rgb_xyz(b); - var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); - return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); - } - function d3_rgb_xyz(r) { - return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); - } - function d3_rgb_parseNumber(c) { - var f = parseFloat(c); - return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; - } - var d3_rgb_names = d3.map({ - aliceblue: 15792383, - antiquewhite: 16444375, - aqua: 65535, - aquamarine: 8388564, - azure: 15794175, - beige: 16119260, - bisque: 16770244, - black: 0, - blanchedalmond: 16772045, - blue: 255, - blueviolet: 9055202, - brown: 10824234, - burlywood: 14596231, - cadetblue: 6266528, - chartreuse: 8388352, - chocolate: 13789470, - coral: 16744272, - cornflowerblue: 6591981, - cornsilk: 16775388, - crimson: 14423100, - cyan: 65535, - darkblue: 139, - darkcyan: 35723, - darkgoldenrod: 12092939, - darkgray: 11119017, - darkgreen: 25600, - darkgrey: 11119017, - darkkhaki: 12433259, - darkmagenta: 9109643, - darkolivegreen: 5597999, - darkorange: 16747520, - darkorchid: 10040012, - darkred: 9109504, - darksalmon: 15308410, - darkseagreen: 9419919, - darkslateblue: 4734347, - darkslategray: 3100495, - darkslategrey: 3100495, - darkturquoise: 52945, - darkviolet: 9699539, - deeppink: 16716947, - deepskyblue: 49151, - dimgray: 6908265, - dimgrey: 6908265, - dodgerblue: 2003199, - firebrick: 11674146, - floralwhite: 16775920, - forestgreen: 2263842, - fuchsia: 16711935, - gainsboro: 14474460, - ghostwhite: 16316671, - gold: 16766720, - goldenrod: 14329120, - gray: 8421504, - green: 32768, - greenyellow: 11403055, - grey: 8421504, - honeydew: 15794160, - hotpink: 16738740, - indianred: 13458524, - indigo: 4915330, - ivory: 16777200, - khaki: 15787660, - lavender: 15132410, - lavenderblush: 16773365, - lawngreen: 8190976, - lemonchiffon: 16775885, - lightblue: 11393254, - lightcoral: 15761536, - lightcyan: 14745599, - lightgoldenrodyellow: 16448210, - lightgray: 13882323, - lightgreen: 9498256, - lightgrey: 13882323, - lightpink: 16758465, - lightsalmon: 16752762, - lightseagreen: 2142890, - lightskyblue: 8900346, - lightslategray: 7833753, - lightslategrey: 7833753, - lightsteelblue: 11584734, - lightyellow: 16777184, - lime: 65280, - limegreen: 3329330, - linen: 16445670, - magenta: 16711935, - maroon: 8388608, - mediumaquamarine: 6737322, - mediumblue: 205, - mediumorchid: 12211667, - mediumpurple: 9662683, - mediumseagreen: 3978097, - mediumslateblue: 8087790, - mediumspringgreen: 64154, - mediumturquoise: 4772300, - mediumvioletred: 13047173, - midnightblue: 1644912, - mintcream: 16121850, - mistyrose: 16770273, - moccasin: 16770229, - navajowhite: 16768685, - navy: 128, - oldlace: 16643558, - olive: 8421376, - olivedrab: 7048739, - orange: 16753920, - orangered: 16729344, - orchid: 14315734, - palegoldenrod: 15657130, - palegreen: 10025880, - paleturquoise: 11529966, - palevioletred: 14381203, - papayawhip: 16773077, - peachpuff: 16767673, - peru: 13468991, - pink: 16761035, - plum: 14524637, - powderblue: 11591910, - purple: 8388736, - red: 16711680, - rosybrown: 12357519, - royalblue: 4286945, - saddlebrown: 9127187, - salmon: 16416882, - sandybrown: 16032864, - seagreen: 3050327, - seashell: 16774638, - sienna: 10506797, - silver: 12632256, - skyblue: 8900331, - slateblue: 6970061, - slategray: 7372944, - slategrey: 7372944, - snow: 16775930, - springgreen: 65407, - steelblue: 4620980, - tan: 13808780, - teal: 32896, - thistle: 14204888, - tomato: 16737095, - turquoise: 4251856, - violet: 15631086, - wheat: 16113331, - white: 16777215, - whitesmoke: 16119285, - yellow: 16776960, - yellowgreen: 10145074 - }); - d3_rgb_names.forEach(function(key, value) { - d3_rgb_names.set(key, d3_rgbNumber(value)); - }); - function d3_functor(v) { - return typeof v === "function" ? v : function() { - return v; - }; - } - d3.functor = d3_functor; - function d3_identity(d) { - return d; - } - d3.xhr = d3_xhrType(d3_identity); - function d3_xhrType(response) { - return function(url, mimeType, callback) { - if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, - mimeType = null; - return d3_xhr(url, mimeType, response, callback); - }; - } - function d3_xhr(url, mimeType, response, callback) { - var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; - if (d3_window.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); - "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { - request.readyState > 3 && respond(); - }; - function respond() { - var status = request.status, result; - if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { - try { - result = response.call(xhr, request); - } catch (e) { - dispatch.error.call(xhr, e); - return; - } - dispatch.load.call(xhr, result); - } else { - dispatch.error.call(xhr, request); - } - } - request.onprogress = function(event) { - var o = d3.event; - d3.event = event; - try { - dispatch.progress.call(xhr, request); - } finally { - d3.event = o; - } - }; - xhr.header = function(name, value) { - name = (name + "").toLowerCase(); - if (arguments.length < 2) return headers[name]; - if (value == null) delete headers[name]; else headers[name] = value + ""; - return xhr; - }; - xhr.mimeType = function(value) { - if (!arguments.length) return mimeType; - mimeType = value == null ? null : value + ""; - return xhr; - }; - xhr.responseType = function(value) { - if (!arguments.length) return responseType; - responseType = value; - return xhr; - }; - xhr.response = function(value) { - response = value; - return xhr; - }; - [ "get", "post" ].forEach(function(method) { - xhr[method] = function() { - return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); - }; - }); - xhr.send = function(method, data, callback) { - if (arguments.length === 2 && typeof data === "function") callback = data, data = null; - request.open(method, url, true); - if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; - if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); - if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); - if (responseType != null) request.responseType = responseType; - if (callback != null) xhr.on("error", callback).on("load", function(request) { - callback(null, request); - }); - dispatch.beforesend.call(xhr, request); - request.send(data == null ? null : data); - return xhr; - }; - xhr.abort = function() { - request.abort(); - return xhr; - }; - d3.rebind(xhr, dispatch, "on"); - return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); - } - function d3_xhr_fixCallback(callback) { - return callback.length === 1 ? function(error, request) { - callback(error == null ? request : null); - } : callback; - } - function d3_xhrHasResponse(request) { - var type = request.responseType; - return type && type !== "text" ? request.response : request.responseText; - } - d3.dsv = function(delimiter, mimeType) { - var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); - function dsv(url, row, callback) { - if (arguments.length < 3) callback = row, row = null; - var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); - xhr.row = function(_) { - return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; - }; - return xhr; - } - function response(request) { - return dsv.parse(request.responseText); - } - function typedResponse(f) { - return function(request) { - return dsv.parse(request.responseText, f); - }; - } - dsv.parse = function(text, f) { - var o; - return dsv.parseRows(text, function(row, i) { - if (o) return o(row, i - 1); - var a = new Function("d", "return {" + row.map(function(name, i) { - return JSON.stringify(name) + ": d[" + i + "]"; - }).join(",") + "}"); - o = f ? function(row, i) { - return f(a(row), i); - } : a; - }); - }; - dsv.parseRows = function(text, f) { - var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; - function token() { - if (I >= N) return EOF; - if (eol) return eol = false, EOL; - var j = I; - if (text.charCodeAt(j) === 34) { - var i = j; - while (i++ < N) { - if (text.charCodeAt(i) === 34) { - if (text.charCodeAt(i + 1) !== 34) break; - ++i; - } - } - I = i + 2; - var c = text.charCodeAt(i + 1); - if (c === 13) { - eol = true; - if (text.charCodeAt(i + 2) === 10) ++I; - } else if (c === 10) { - eol = true; - } - return text.slice(j + 1, i).replace(/""/g, '"'); - } - while (I < N) { - var c = text.charCodeAt(I++), k = 1; - if (c === 10) eol = true; else if (c === 13) { - eol = true; - if (text.charCodeAt(I) === 10) ++I, ++k; - } else if (c !== delimiterCode) continue; - return text.slice(j, I - k); - } - return text.slice(j); - } - while ((t = token()) !== EOF) { - var a = []; - while (t !== EOL && t !== EOF) { - a.push(t); - t = token(); - } - if (f && (a = f(a, n++)) == null) continue; - rows.push(a); - } - return rows; - }; - dsv.format = function(rows) { - if (Array.isArray(rows[0])) return dsv.formatRows(rows); - var fieldSet = new d3_Set(), fields = []; - rows.forEach(function(row) { - for (var field in row) { - if (!fieldSet.has(field)) { - fields.push(fieldSet.add(field)); - } - } - }); - return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { - return fields.map(function(field) { - return formatValue(row[field]); - }).join(delimiter); - })).join("\n"); - }; - dsv.formatRows = function(rows) { - return rows.map(formatRow).join("\n"); - }; - function formatRow(row) { - return row.map(formatValue).join(delimiter); - } - function formatValue(text) { - return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; - } - return dsv; - }; - d3.csv = d3.dsv(",", "text/csv"); - d3.tsv = d3.dsv(" ", "text/tab-separated-values"); - var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = d3_window[d3_vendorSymbol(d3_window, "requestAnimationFrame")] || function(callback) { - setTimeout(callback, 17); - }; - d3.timer = function(callback, delay, then) { - var n = arguments.length; - if (n < 2) delay = 0; - if (n < 3) then = Date.now(); - var time = then + delay, timer = { - c: callback, - t: time, - f: false, - n: null - }; - if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; - d3_timer_queueTail = timer; - if (!d3_timer_interval) { - d3_timer_timeout = clearTimeout(d3_timer_timeout); - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } - }; - function d3_timer_step() { - var now = d3_timer_mark(), delay = d3_timer_sweep() - now; - if (delay > 24) { - if (isFinite(delay)) { - clearTimeout(d3_timer_timeout); - d3_timer_timeout = setTimeout(d3_timer_step, delay); - } - d3_timer_interval = 0; - } else { - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } - } - d3.timer.flush = function() { - d3_timer_mark(); - d3_timer_sweep(); - }; - function d3_timer_mark() { - var now = Date.now(); - d3_timer_active = d3_timer_queueHead; - while (d3_timer_active) { - if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t); - d3_timer_active = d3_timer_active.n; - } - return now; - } - function d3_timer_sweep() { - var t0, t1 = d3_timer_queueHead, time = Infinity; - while (t1) { - if (t1.f) { - t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; - } else { - if (t1.t < time) time = t1.t; - t1 = (t0 = t1).n; - } - } - d3_timer_queueTail = t0; - return time; - } - function d3_format_precision(x, p) { - return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); - } - d3.round = function(x, n) { - return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); - }; - var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); - d3.formatPrefix = function(value, precision) { - var i = 0; - if (value) { - if (value < 0) value *= -1; - if (precision) value = d3.round(value, d3_format_precision(value, precision)); - i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); - i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); - } - return d3_formatPrefixes[8 + i / 3]; - }; - function d3_formatPrefix(d, i) { - var k = Math.pow(10, abs(8 - i) * 3); - return { - scale: i > 8 ? function(d) { - return d / k; - } : function(d) { - return d * k; - }, - symbol: d - }; - } - function d3_locale_numberFormat(locale) { - var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) { - var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0; - while (i > 0 && g > 0) { - if (length + g + 1 > width) g = Math.max(1, width - length); - t.push(value.substring(i -= g, i + g)); - if ((length += g + 1) > width) break; - g = locale_grouping[j = (j + 1) % locale_grouping.length]; - } - return t.reverse().join(locale_thousands); - } : d3_identity; - return function(specifier) { - var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true; - if (precision) precision = +precision.substring(1); - if (zfill || fill === "0" && align === "=") { - zfill = fill = "0"; - align = "="; - } - switch (type) { - case "n": - comma = true; - type = "g"; - break; - - case "%": - scale = 100; - suffix = "%"; - type = "f"; - break; - - case "p": - scale = 100; - suffix = "%"; - type = "r"; - break; - - case "b": - case "o": - case "x": - case "X": - if (symbol === "#") prefix = "0" + type.toLowerCase(); - - case "c": - exponent = false; - - case "d": - integer = true; - precision = 0; - break; - - case "s": - scale = -1; - type = "r"; - break; - } - if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; - if (type == "r" && !precision) type = "g"; - if (precision != null) { - if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); - } - type = d3_format_types.get(type) || d3_format_typeDefault; - var zcomma = zfill && comma; - return function(value) { - var fullSuffix = suffix; - if (integer && value % 1) return ""; - var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign; - if (scale < 0) { - var unit = d3.formatPrefix(value, precision); - value = unit.scale(value); - fullSuffix = unit.symbol + suffix; - } else { - value *= scale; - } - value = type(value, precision); - var i = value.lastIndexOf("."), before, after; - if (i < 0) { - var j = exponent ? value.lastIndexOf("e") : -1; - if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j); - } else { - before = value.substring(0, i); - after = locale_decimal + value.substring(i + 1); - } - if (!zfill && comma) before = formatGroup(before, Infinity); - var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; - if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity); - negative += prefix; - value = before + after; - return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix; - }; - }; - } - var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; - var d3_format_types = d3.map({ - b: function(x) { - return x.toString(2); - }, - c: function(x) { - return String.fromCharCode(x); - }, - o: function(x) { - return x.toString(8); - }, - x: function(x) { - return x.toString(16); - }, - X: function(x) { - return x.toString(16).toUpperCase(); - }, - g: function(x, p) { - return x.toPrecision(p); - }, - e: function(x, p) { - return x.toExponential(p); - }, - f: function(x, p) { - return x.toFixed(p); - }, - r: function(x, p) { - return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); - } - }); - function d3_format_typeDefault(x) { - return x + ""; - } - var d3_time = d3.time = {}, d3_date = Date; - function d3_date_utc() { - this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); - } - d3_date_utc.prototype = { - getDate: function() { - return this._.getUTCDate(); - }, - getDay: function() { - return this._.getUTCDay(); - }, - getFullYear: function() { - return this._.getUTCFullYear(); - }, - getHours: function() { - return this._.getUTCHours(); - }, - getMilliseconds: function() { - return this._.getUTCMilliseconds(); - }, - getMinutes: function() { - return this._.getUTCMinutes(); - }, - getMonth: function() { - return this._.getUTCMonth(); - }, - getSeconds: function() { - return this._.getUTCSeconds(); - }, - getTime: function() { - return this._.getTime(); - }, - getTimezoneOffset: function() { - return 0; - }, - valueOf: function() { - return this._.valueOf(); - }, - setDate: function() { - d3_time_prototype.setUTCDate.apply(this._, arguments); - }, - setDay: function() { - d3_time_prototype.setUTCDay.apply(this._, arguments); - }, - setFullYear: function() { - d3_time_prototype.setUTCFullYear.apply(this._, arguments); - }, - setHours: function() { - d3_time_prototype.setUTCHours.apply(this._, arguments); - }, - setMilliseconds: function() { - d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); - }, - setMinutes: function() { - d3_time_prototype.setUTCMinutes.apply(this._, arguments); - }, - setMonth: function() { - d3_time_prototype.setUTCMonth.apply(this._, arguments); - }, - setSeconds: function() { - d3_time_prototype.setUTCSeconds.apply(this._, arguments); - }, - setTime: function() { - d3_time_prototype.setTime.apply(this._, arguments); - } - }; - var d3_time_prototype = Date.prototype; - function d3_time_interval(local, step, number) { - function round(date) { - var d0 = local(date), d1 = offset(d0, 1); - return date - d0 < d1 - date ? d0 : d1; - } - function ceil(date) { - step(date = local(new d3_date(date - 1)), 1); - return date; - } - function offset(date, k) { - step(date = new d3_date(+date), k); - return date; - } - function range(t0, t1, dt) { - var time = ceil(t0), times = []; - if (dt > 1) { - while (time < t1) { - if (!(number(time) % dt)) times.push(new Date(+time)); - step(time, 1); - } - } else { - while (time < t1) times.push(new Date(+time)), step(time, 1); - } - return times; - } - function range_utc(t0, t1, dt) { - try { - d3_date = d3_date_utc; - var utc = new d3_date_utc(); - utc._ = t0; - return range(utc, t1, dt); - } finally { - d3_date = Date; - } - } - local.floor = local; - local.round = round; - local.ceil = ceil; - local.offset = offset; - local.range = range; - var utc = local.utc = d3_time_interval_utc(local); - utc.floor = utc; - utc.round = d3_time_interval_utc(round); - utc.ceil = d3_time_interval_utc(ceil); - utc.offset = d3_time_interval_utc(offset); - utc.range = range_utc; - return local; - } - function d3_time_interval_utc(method) { - return function(date, k) { - try { - d3_date = d3_date_utc; - var utc = new d3_date_utc(); - utc._ = date; - return method(utc, k)._; - } finally { - d3_date = Date; - } - }; - } - d3_time.year = d3_time_interval(function(date) { - date = d3_time.day(date); - date.setMonth(0, 1); - return date; - }, function(date, offset) { - date.setFullYear(date.getFullYear() + offset); - }, function(date) { - return date.getFullYear(); - }); - d3_time.years = d3_time.year.range; - d3_time.years.utc = d3_time.year.utc.range; - d3_time.day = d3_time_interval(function(date) { - var day = new d3_date(2e3, 0); - day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); - return day; - }, function(date, offset) { - date.setDate(date.getDate() + offset); - }, function(date) { - return date.getDate() - 1; - }); - d3_time.days = d3_time.day.range; - d3_time.days.utc = d3_time.day.utc.range; - d3_time.dayOfYear = function(date) { - var year = d3_time.year(date); - return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); - }; - [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { - i = 7 - i; - var interval = d3_time[day] = d3_time_interval(function(date) { - (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); - return date; - }, function(date, offset) { - date.setDate(date.getDate() + Math.floor(offset) * 7); - }, function(date) { - var day = d3_time.year(date).getDay(); - return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); - }); - d3_time[day + "s"] = interval.range; - d3_time[day + "s"].utc = interval.utc.range; - d3_time[day + "OfYear"] = function(date) { - var day = d3_time.year(date).getDay(); - return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); - }; - }); - d3_time.week = d3_time.sunday; - d3_time.weeks = d3_time.sunday.range; - d3_time.weeks.utc = d3_time.sunday.utc.range; - d3_time.weekOfYear = d3_time.sundayOfYear; - function d3_locale_timeFormat(locale) { - var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; - function d3_time_format(template) { - var n = template.length; - function format(date) { - var string = [], i = -1, j = 0, c, p, f; - while (++i < n) { - if (template.charCodeAt(i) === 37) { - string.push(template.slice(j, i)); - if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); - if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); - string.push(c); - j = i + 1; - } - } - string.push(template.slice(j, i)); - return string.join(""); - } - format.parse = function(string) { - var d = { - y: 1900, - m: 0, - d: 1, - H: 0, - M: 0, - S: 0, - L: 0, - Z: null - }, i = d3_time_parse(d, template, string, 0); - if (i != string.length) return null; - if ("p" in d) d.H = d.H % 12 + d.p * 12; - var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); - if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("w" in d && ("W" in d || "U" in d)) { - date.setFullYear(d.y, 0, 1); - date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); - } else date.setFullYear(d.y, d.m, d.d); - date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L); - return localZ ? date._ : date; - }; - format.toString = function() { - return template; - }; - return format; - } - function d3_time_parse(date, template, string, j) { - var c, p, t, i = 0, n = template.length, m = string.length; - while (i < n) { - if (j >= m) return -1; - c = template.charCodeAt(i++); - if (c === 37) { - t = template.charAt(i++); - p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; - if (!p || (j = p(date, string, j)) < 0) return -1; - } else if (c != string.charCodeAt(j++)) { - return -1; - } - } - return j; - } - d3_time_format.utc = function(template) { - var local = d3_time_format(template); - function format(date) { - try { - d3_date = d3_date_utc; - var utc = new d3_date(); - utc._ = date; - return local(utc); - } finally { - d3_date = Date; - } - } - format.parse = function(string) { - try { - d3_date = d3_date_utc; - var date = local.parse(string); - return date && date._; - } finally { - d3_date = Date; - } - }; - format.toString = local.toString; - return format; - }; - d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; - var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); - locale_periods.forEach(function(p, i) { - d3_time_periodLookup.set(p.toLowerCase(), i); - }); - var d3_time_formats = { - a: function(d) { - return locale_shortDays[d.getDay()]; - }, - A: function(d) { - return locale_days[d.getDay()]; - }, - b: function(d) { - return locale_shortMonths[d.getMonth()]; - }, - B: function(d) { - return locale_months[d.getMonth()]; - }, - c: d3_time_format(locale_dateTime), - d: function(d, p) { - return d3_time_formatPad(d.getDate(), p, 2); - }, - e: function(d, p) { - return d3_time_formatPad(d.getDate(), p, 2); - }, - H: function(d, p) { - return d3_time_formatPad(d.getHours(), p, 2); - }, - I: function(d, p) { - return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); - }, - j: function(d, p) { - return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); - }, - L: function(d, p) { - return d3_time_formatPad(d.getMilliseconds(), p, 3); - }, - m: function(d, p) { - return d3_time_formatPad(d.getMonth() + 1, p, 2); - }, - M: function(d, p) { - return d3_time_formatPad(d.getMinutes(), p, 2); - }, - p: function(d) { - return locale_periods[+(d.getHours() >= 12)]; - }, - S: function(d, p) { - return d3_time_formatPad(d.getSeconds(), p, 2); - }, - U: function(d, p) { - return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); - }, - w: function(d) { - return d.getDay(); - }, - W: function(d, p) { - return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); - }, - x: d3_time_format(locale_date), - X: d3_time_format(locale_time), - y: function(d, p) { - return d3_time_formatPad(d.getFullYear() % 100, p, 2); - }, - Y: function(d, p) { - return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); - }, - Z: d3_time_zone, - "%": function() { - return "%"; - } - }; - var d3_time_parsers = { - a: d3_time_parseWeekdayAbbrev, - A: d3_time_parseWeekday, - b: d3_time_parseMonthAbbrev, - B: d3_time_parseMonth, - c: d3_time_parseLocaleFull, - d: d3_time_parseDay, - e: d3_time_parseDay, - H: d3_time_parseHour24, - I: d3_time_parseHour24, - j: d3_time_parseDayOfYear, - L: d3_time_parseMilliseconds, - m: d3_time_parseMonthNumber, - M: d3_time_parseMinutes, - p: d3_time_parseAmPm, - S: d3_time_parseSeconds, - U: d3_time_parseWeekNumberSunday, - w: d3_time_parseWeekdayNumber, - W: d3_time_parseWeekNumberMonday, - x: d3_time_parseLocaleDate, - X: d3_time_parseLocaleTime, - y: d3_time_parseYear, - Y: d3_time_parseFullYear, - Z: d3_time_parseZone, - "%": d3_time_parseLiteralPercent - }; - function d3_time_parseWeekdayAbbrev(date, string, i) { - d3_time_dayAbbrevRe.lastIndex = 0; - var n = d3_time_dayAbbrevRe.exec(string.slice(i)); - return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseWeekday(date, string, i) { - d3_time_dayRe.lastIndex = 0; - var n = d3_time_dayRe.exec(string.slice(i)); - return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseMonthAbbrev(date, string, i) { - d3_time_monthAbbrevRe.lastIndex = 0; - var n = d3_time_monthAbbrevRe.exec(string.slice(i)); - return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseMonth(date, string, i) { - d3_time_monthRe.lastIndex = 0; - var n = d3_time_monthRe.exec(string.slice(i)); - return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseLocaleFull(date, string, i) { - return d3_time_parse(date, d3_time_formats.c.toString(), string, i); - } - function d3_time_parseLocaleDate(date, string, i) { - return d3_time_parse(date, d3_time_formats.x.toString(), string, i); - } - function d3_time_parseLocaleTime(date, string, i) { - return d3_time_parse(date, d3_time_formats.X.toString(), string, i); - } - function d3_time_parseAmPm(date, string, i) { - var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase()); - return n == null ? -1 : (date.p = n, i); - } - return d3_time_format; - } - var d3_time_formatPads = { - "-": "", - _: " ", - "0": "0" - }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; - function d3_time_formatPad(value, fill, width) { - var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; - return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); - } - function d3_time_formatRe(names) { - return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); - } - function d3_time_formatLookup(names) { - var map = new d3_Map(), i = -1, n = names.length; - while (++i < n) map.set(names[i].toLowerCase(), i); - return map; - } - function d3_time_parseWeekdayNumber(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 1)); - return n ? (date.w = +n[0], i + n[0].length) : -1; - } - function d3_time_parseWeekNumberSunday(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i)); - return n ? (date.U = +n[0], i + n[0].length) : -1; - } - function d3_time_parseWeekNumberMonday(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i)); - return n ? (date.W = +n[0], i + n[0].length) : -1; - } - function d3_time_parseFullYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 4)); - return n ? (date.y = +n[0], i + n[0].length) : -1; - } - function d3_time_parseYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; - } - function d3_time_parseZone(date, string, i) { - return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, - i + 5) : -1; - } - function d3_time_expandYear(d) { - return d + (d > 68 ? 1900 : 2e3); - } - function d3_time_parseMonthNumber(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.m = n[0] - 1, i + n[0].length) : -1; - } - function d3_time_parseDay(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.d = +n[0], i + n[0].length) : -1; - } - function d3_time_parseDayOfYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 3)); - return n ? (date.j = +n[0], i + n[0].length) : -1; - } - function d3_time_parseHour24(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.H = +n[0], i + n[0].length) : -1; - } - function d3_time_parseMinutes(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.M = +n[0], i + n[0].length) : -1; - } - function d3_time_parseSeconds(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.S = +n[0], i + n[0].length) : -1; - } - function d3_time_parseMilliseconds(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 3)); - return n ? (date.L = +n[0], i + n[0].length) : -1; - } - function d3_time_zone(d) { - var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60; - return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); - } - function d3_time_parseLiteralPercent(date, string, i) { - d3_time_percentRe.lastIndex = 0; - var n = d3_time_percentRe.exec(string.slice(i, i + 1)); - return n ? i + n[0].length : -1; - } - function d3_time_formatMulti(formats) { - var n = formats.length, i = -1; - while (++i < n) formats[i][0] = this(formats[i][0]); - return function(date) { - var i = 0, f = formats[i]; - while (!f[1](date)) f = formats[++i]; - return f[0](date); - }; - } - d3.locale = function(locale) { - return { - numberFormat: d3_locale_numberFormat(locale), - timeFormat: d3_locale_timeFormat(locale) - }; - }; - var d3_locale_enUS = d3.locale({ - decimal: ".", - thousands: ",", - grouping: [ 3 ], - currency: [ "$", "" ], - dateTime: "%a %b %e %X %Y", - date: "%m/%d/%Y", - time: "%H:%M:%S", - periods: [ "AM", "PM" ], - days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], - shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], - months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], - shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] - }); - d3.format = d3_locale_enUS.numberFormat; - d3.geo = {}; - function d3_adder() {} - d3_adder.prototype = { - s: 0, - t: 0, - add: function(y) { - d3_adderSum(y, this.t, d3_adderTemp); - d3_adderSum(d3_adderTemp.s, this.s, this); - if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; - }, - reset: function() { - this.s = this.t = 0; - }, - valueOf: function() { - return this.s; - } - }; - var d3_adderTemp = new d3_adder(); - function d3_adderSum(a, b, o) { - var x = o.s = a + b, bv = x - a, av = x - bv; - o.t = a - av + (b - bv); - } - d3.geo.stream = function(object, listener) { - if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { - d3_geo_streamObjectType[object.type](object, listener); - } else { - d3_geo_streamGeometry(object, listener); - } - }; - function d3_geo_streamGeometry(geometry, listener) { - if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { - d3_geo_streamGeometryType[geometry.type](geometry, listener); - } - } - var d3_geo_streamObjectType = { - Feature: function(feature, listener) { - d3_geo_streamGeometry(feature.geometry, listener); - }, - FeatureCollection: function(object, listener) { - var features = object.features, i = -1, n = features.length; - while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); - } - }; - var d3_geo_streamGeometryType = { - Sphere: function(object, listener) { - listener.sphere(); - }, - Point: function(object, listener) { - object = object.coordinates; - listener.point(object[0], object[1], object[2]); - }, - MultiPoint: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); - }, - LineString: function(object, listener) { - d3_geo_streamLine(object.coordinates, listener, 0); - }, - MultiLineString: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); - }, - Polygon: function(object, listener) { - d3_geo_streamPolygon(object.coordinates, listener); - }, - MultiPolygon: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); - }, - GeometryCollection: function(object, listener) { - var geometries = object.geometries, i = -1, n = geometries.length; - while (++i < n) d3_geo_streamGeometry(geometries[i], listener); - } - }; - function d3_geo_streamLine(coordinates, listener, closed) { - var i = -1, n = coordinates.length - closed, coordinate; - listener.lineStart(); - while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); - listener.lineEnd(); - } - function d3_geo_streamPolygon(coordinates, listener) { - var i = -1, n = coordinates.length; - listener.polygonStart(); - while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); - listener.polygonEnd(); - } - d3.geo.area = function(object) { - d3_geo_areaSum = 0; - d3.geo.stream(object, d3_geo_area); - return d3_geo_areaSum; - }; - var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); - var d3_geo_area = { - sphere: function() { - d3_geo_areaSum += 4 * π; - }, - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_areaRingSum.reset(); - d3_geo_area.lineStart = d3_geo_areaRingStart; - }, - polygonEnd: function() { - var area = 2 * d3_geo_areaRingSum; - d3_geo_areaSum += area < 0 ? 4 * π + area : area; - d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; - } - }; - function d3_geo_areaRingStart() { - var λ00, φ00, λ0, cosφ0, sinφ0; - d3_geo_area.point = function(λ, φ) { - d3_geo_area.point = nextPoint; - λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), - sinφ0 = Math.sin(φ); - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - φ = φ * d3_radians / 2 + π / 4; - var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ); - d3_geo_areaRingSum.add(Math.atan2(v, u)); - λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; - } - d3_geo_area.lineEnd = function() { - nextPoint(λ00, φ00); - }; - } - function d3_geo_cartesian(spherical) { - var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); - return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; - } - function d3_geo_cartesianDot(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; - } - function d3_geo_cartesianCross(a, b) { - return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; - } - function d3_geo_cartesianAdd(a, b) { - a[0] += b[0]; - a[1] += b[1]; - a[2] += b[2]; - } - function d3_geo_cartesianScale(vector, k) { - return [ vector[0] * k, vector[1] * k, vector[2] * k ]; - } - function d3_geo_cartesianNormalize(d) { - var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); - d[0] /= l; - d[1] /= l; - d[2] /= l; - } - function d3_geo_spherical(cartesian) { - return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; - } - function d3_geo_sphericalEqual(a, b) { - return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; - } - d3.geo.bounds = function() { - var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; - var bound = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - bound.point = ringPoint; - bound.lineStart = ringStart; - bound.lineEnd = ringEnd; - dλSum = 0; - d3_geo_area.polygonStart(); - }, - polygonEnd: function() { - d3_geo_area.polygonEnd(); - bound.point = point; - bound.lineStart = lineStart; - bound.lineEnd = lineEnd; - if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; - range[0] = λ0, range[1] = λ1; - } - }; - function point(λ, φ) { - ranges.push(range = [ λ0 = λ, λ1 = λ ]); - if (φ < φ0) φ0 = φ; - if (φ > φ1) φ1 = φ; - } - function linePoint(λ, φ) { - var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); - if (p0) { - var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); - d3_geo_cartesianNormalize(inflection); - inflection = d3_geo_spherical(inflection); - var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; - if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { - var φi = inflection[1] * d3_degrees; - if (φi > φ1) φ1 = φi; - } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { - var φi = -inflection[1] * d3_degrees; - if (φi < φ0) φ0 = φi; - } else { - if (φ < φ0) φ0 = φ; - if (φ > φ1) φ1 = φ; - } - if (antimeridian) { - if (λ < λ_) { - if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; - } else { - if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; - } - } else { - if (λ1 >= λ0) { - if (λ < λ0) λ0 = λ; - if (λ > λ1) λ1 = λ; - } else { - if (λ > λ_) { - if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; - } else { - if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; - } - } - } - } else { - point(λ, φ); - } - p0 = p, λ_ = λ; - } - function lineStart() { - bound.point = linePoint; - } - function lineEnd() { - range[0] = λ0, range[1] = λ1; - bound.point = point; - p0 = null; - } - function ringPoint(λ, φ) { - if (p0) { - var dλ = λ - λ_; - dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; - } else λ__ = λ, φ__ = φ; - d3_geo_area.point(λ, φ); - linePoint(λ, φ); - } - function ringStart() { - d3_geo_area.lineStart(); - } - function ringEnd() { - ringPoint(λ__, φ__); - d3_geo_area.lineEnd(); - if (abs(dλSum) > ε) λ0 = -(λ1 = 180); - range[0] = λ0, range[1] = λ1; - p0 = null; - } - function angle(λ0, λ1) { - return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; - } - function compareRanges(a, b) { - return a[0] - b[0]; - } - function withinRange(x, range) { - return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; - } - return function(feature) { - φ1 = λ1 = -(λ0 = φ0 = Infinity); - ranges = []; - d3.geo.stream(feature, bound); - var n = ranges.length; - if (n) { - ranges.sort(compareRanges); - for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { - b = ranges[i]; - if (withinRange(b[0], a) || withinRange(b[1], a)) { - if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; - if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; - } else { - merged.push(a = b); - } - } - var best = -Infinity, dλ; - for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { - b = merged[i]; - if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; - } - } - ranges = range = null; - return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ]; - }; - }(); - d3.geo.centroid = function(object) { - d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; - d3.geo.stream(object, d3_geo_centroid); - var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; - if (m < ε2) { - x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; - if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; - m = x * x + y * y + z * z; - if (m < ε2) return [ NaN, NaN ]; - } - return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; - }; - var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; - var d3_geo_centroid = { - sphere: d3_noop, - point: d3_geo_centroidPoint, - lineStart: d3_geo_centroidLineStart, - lineEnd: d3_geo_centroidLineEnd, - polygonStart: function() { - d3_geo_centroid.lineStart = d3_geo_centroidRingStart; - }, - polygonEnd: function() { - d3_geo_centroid.lineStart = d3_geo_centroidLineStart; - } - }; - function d3_geo_centroidPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ)); - } - function d3_geo_centroidPointXYZ(x, y, z) { - ++d3_geo_centroidW0; - d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; - d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; - d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; - } - function d3_geo_centroidLineStart() { - var x0, y0, z0; - d3_geo_centroid.point = function(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - x0 = cosφ * Math.cos(λ); - y0 = cosφ * Math.sin(λ); - z0 = Math.sin(φ); - d3_geo_centroid.point = nextPoint; - d3_geo_centroidPointXYZ(x0, y0, z0); - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); - d3_geo_centroidW1 += w; - d3_geo_centroidX1 += w * (x0 + (x0 = x)); - d3_geo_centroidY1 += w * (y0 + (y0 = y)); - d3_geo_centroidZ1 += w * (z0 + (z0 = z)); - d3_geo_centroidPointXYZ(x0, y0, z0); - } - } - function d3_geo_centroidLineEnd() { - d3_geo_centroid.point = d3_geo_centroidPoint; - } - function d3_geo_centroidRingStart() { - var λ00, φ00, x0, y0, z0; - d3_geo_centroid.point = function(λ, φ) { - λ00 = λ, φ00 = φ; - d3_geo_centroid.point = nextPoint; - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - x0 = cosφ * Math.cos(λ); - y0 = cosφ * Math.sin(λ); - z0 = Math.sin(φ); - d3_geo_centroidPointXYZ(x0, y0, z0); - }; - d3_geo_centroid.lineEnd = function() { - nextPoint(λ00, φ00); - d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; - d3_geo_centroid.point = d3_geo_centroidPoint; - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); - d3_geo_centroidX2 += v * cx; - d3_geo_centroidY2 += v * cy; - d3_geo_centroidZ2 += v * cz; - d3_geo_centroidW1 += w; - d3_geo_centroidX1 += w * (x0 + (x0 = x)); - d3_geo_centroidY1 += w * (y0 + (y0 = y)); - d3_geo_centroidZ1 += w * (z0 + (z0 = z)); - d3_geo_centroidPointXYZ(x0, y0, z0); - } - } - function d3_geo_compose(a, b) { - function compose(x, y) { - return x = a(x, y), b(x[0], x[1]); - } - if (a.invert && b.invert) compose.invert = function(x, y) { - return x = b.invert(x, y), x && a.invert(x[0], x[1]); - }; - return compose; - } - function d3_true() { - return true; - } - function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { - var subject = [], clip = []; - segments.forEach(function(segment) { - if ((n = segment.length - 1) <= 0) return; - var n, p0 = segment[0], p1 = segment[n]; - if (d3_geo_sphericalEqual(p0, p1)) { - listener.lineStart(); - for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); - listener.lineEnd(); - return; - } - var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); - a.o = b; - subject.push(a); - clip.push(b); - a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); - b = new d3_geo_clipPolygonIntersection(p1, null, a, true); - a.o = b; - subject.push(a); - clip.push(b); - }); - clip.sort(compare); - d3_geo_clipPolygonLinkCircular(subject); - d3_geo_clipPolygonLinkCircular(clip); - if (!subject.length) return; - for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { - clip[i].e = entry = !entry; - } - var start = subject[0], points, point; - while (1) { - var current = start, isSubject = true; - while (current.v) if ((current = current.n) === start) return; - points = current.z; - listener.lineStart(); - do { - current.v = current.o.v = true; - if (current.e) { - if (isSubject) { - for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.n.x, 1, listener); - } - current = current.n; - } else { - if (isSubject) { - points = current.p.z; - for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.p.x, -1, listener); - } - current = current.p; - } - current = current.o; - points = current.z; - isSubject = !isSubject; - } while (!current.v); - listener.lineEnd(); - } - } - function d3_geo_clipPolygonLinkCircular(array) { - if (!(n = array.length)) return; - var n, i = 0, a = array[0], b; - while (++i < n) { - a.n = b = array[i]; - b.p = a; - a = b; - } - a.n = b = array[0]; - b.p = a; - } - function d3_geo_clipPolygonIntersection(point, points, other, entry) { - this.x = point; - this.z = points; - this.o = other; - this.e = entry; - this.v = false; - this.n = this.p = null; - } - function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { - return function(rotate, listener) { - var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - clip.point = pointRing; - clip.lineStart = ringStart; - clip.lineEnd = ringEnd; - segments = []; - polygon = []; - }, - polygonEnd: function() { - clip.point = point; - clip.lineStart = lineStart; - clip.lineEnd = lineEnd; - segments = d3.merge(segments); - var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); - if (segments.length) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); - } else if (clipStartInside) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - if (polygonStarted) listener.polygonEnd(), polygonStarted = false; - segments = polygon = null; - }, - sphere: function() { - listener.polygonStart(); - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - listener.polygonEnd(); - } - }; - function point(λ, φ) { - var point = rotate(λ, φ); - if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ); - } - function pointLine(λ, φ) { - var point = rotate(λ, φ); - line.point(point[0], point[1]); - } - function lineStart() { - clip.point = pointLine; - line.lineStart(); - } - function lineEnd() { - clip.point = point; - line.lineEnd(); - } - var segments; - var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring; - function pointRing(λ, φ) { - ring.push([ λ, φ ]); - var point = rotate(λ, φ); - ringListener.point(point[0], point[1]); - } - function ringStart() { - ringListener.lineStart(); - ring = []; - } - function ringEnd() { - pointRing(ring[0][0], ring[0][1]); - ringListener.lineEnd(); - var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; - ring.pop(); - polygon.push(ring); - ring = null; - if (!n) return; - if (clean & 1) { - segment = ringSegments[0]; - var n = segment.length - 1, i = -1, point; - if (n > 0) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - listener.lineStart(); - while (++i < n) listener.point((point = segment[i])[0], point[1]); - listener.lineEnd(); - } - return; - } - if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); - segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); - } - return clip; - }; - } - function d3_geo_clipSegmentLength1(segment) { - return segment.length > 1; - } - function d3_geo_clipBufferListener() { - var lines = [], line; - return { - lineStart: function() { - lines.push(line = []); - }, - point: function(λ, φ) { - line.push([ λ, φ ]); - }, - lineEnd: d3_noop, - buffer: function() { - var buffer = lines; - lines = []; - line = null; - return buffer; - }, - rejoin: function() { - if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); - } - }; - } - function d3_geo_clipSort(a, b) { - return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]); - } - var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]); - function d3_geo_clipAntimeridianLine(listener) { - var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; - return { - lineStart: function() { - listener.lineStart(); - clean = 1; - }, - point: function(λ1, φ1) { - var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0); - if (abs(dλ - π) < ε) { - listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ); - listener.point(sλ0, φ0); - listener.lineEnd(); - listener.lineStart(); - listener.point(sλ1, φ0); - listener.point(λ1, φ0); - clean = 0; - } else if (sλ0 !== sλ1 && dλ >= π) { - if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; - if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; - φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); - listener.point(sλ0, φ0); - listener.lineEnd(); - listener.lineStart(); - listener.point(sλ1, φ0); - clean = 0; - } - listener.point(λ0 = λ1, φ0 = φ1); - sλ0 = sλ1; - }, - lineEnd: function() { - listener.lineEnd(); - λ0 = φ0 = NaN; - }, - clean: function() { - return 2 - clean; - } - }; - } - function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { - var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); - return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; - } - function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { - var φ; - if (from == null) { - φ = direction * halfπ; - listener.point(-π, φ); - listener.point(0, φ); - listener.point(π, φ); - listener.point(π, 0); - listener.point(π, -φ); - listener.point(0, -φ); - listener.point(-π, -φ); - listener.point(-π, 0); - listener.point(-π, φ); - } else if (abs(from[0] - to[0]) > ε) { - var s = from[0] < to[0] ? π : -π; - φ = direction * s / 2; - listener.point(-s, φ); - listener.point(0, φ); - listener.point(s, φ); - } else { - listener.point(to[0], to[1]); - } - } - function d3_geo_pointInPolygon(point, polygon) { - var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; - d3_geo_areaRingSum.reset(); - for (var i = 0, n = polygon.length; i < n; ++i) { - var ring = polygon[i], m = ring.length; - if (!m) continue; - var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1; - while (true) { - if (j === m) j = 0; - point = ring[j]; - var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ; - d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ))); - polarAngle += antimeridian ? dλ + sdλ * τ : dλ; - if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { - var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); - d3_geo_cartesianNormalize(arc); - var intersection = d3_geo_cartesianCross(meridianNormal, arc); - d3_geo_cartesianNormalize(intersection); - var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); - if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) { - winding += antimeridian ^ dλ >= 0 ? 1 : -1; - } - } - if (!j++) break; - λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point; - } - } - return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1; - } - function d3_geo_clipCircle(radius) { - var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); - return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]); - function visible(λ, φ) { - return Math.cos(λ) * Math.cos(φ) > cr; - } - function clipLine(listener) { - var point0, c0, v0, v00, clean; - return { - lineStart: function() { - v00 = v0 = false; - clean = 1; - }, - point: function(λ, φ) { - var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0; - if (!point0 && (v00 = v0 = v)) listener.lineStart(); - if (v !== v0) { - point2 = intersect(point0, point1); - if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { - point1[0] += ε; - point1[1] += ε; - v = visible(point1[0], point1[1]); - } - } - if (v !== v0) { - clean = 0; - if (v) { - listener.lineStart(); - point2 = intersect(point1, point0); - listener.point(point2[0], point2[1]); - } else { - point2 = intersect(point0, point1); - listener.point(point2[0], point2[1]); - listener.lineEnd(); - } - point0 = point2; - } else if (notHemisphere && point0 && smallRadius ^ v) { - var t; - if (!(c & c0) && (t = intersect(point1, point0, true))) { - clean = 0; - if (smallRadius) { - listener.lineStart(); - listener.point(t[0][0], t[0][1]); - listener.point(t[1][0], t[1][1]); - listener.lineEnd(); - } else { - listener.point(t[1][0], t[1][1]); - listener.lineEnd(); - listener.lineStart(); - listener.point(t[0][0], t[0][1]); - } - } - } - if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { - listener.point(point1[0], point1[1]); - } - point0 = point1, v0 = v, c0 = c; - }, - lineEnd: function() { - if (v0) listener.lineEnd(); - point0 = null; - }, - clean: function() { - return clean | (v00 && v0) << 1; - } - }; - } - function intersect(a, b, two) { - var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); - var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; - if (!determinant) return !two && a; - var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); - d3_geo_cartesianAdd(A, B); - var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); - if (t2 < 0) return; - var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); - d3_geo_cartesianAdd(q, A); - q = d3_geo_spherical(q); - if (!two) return q; - var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; - if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; - var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε; - if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; - if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) { - var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); - d3_geo_cartesianAdd(q1, A); - return [ q, d3_geo_spherical(q1) ]; - } - } - function code(λ, φ) { - var r = smallRadius ? radius : π - radius, code = 0; - if (λ < -r) code |= 1; else if (λ > r) code |= 2; - if (φ < -r) code |= 4; else if (φ > r) code |= 8; - return code; - } - } - function d3_geom_clipLine(x0, y0, x1, y1) { - return function(line) { - var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; - r = x0 - ax; - if (!dx && r > 0) return; - r /= dx; - if (dx < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dx > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - r = x1 - ax; - if (!dx && r < 0) return; - r /= dx; - if (dx < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dx > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - r = y0 - ay; - if (!dy && r > 0) return; - r /= dy; - if (dy < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dy > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - r = y1 - ay; - if (!dy && r < 0) return; - r /= dy; - if (dy < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dy > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - if (t0 > 0) line.a = { - x: ax + t0 * dx, - y: ay + t0 * dy - }; - if (t1 < 1) line.b = { - x: ax + t1 * dx, - y: ay + t1 * dy - }; - return line; - }; - } - var d3_geo_clipExtentMAX = 1e9; - d3.geo.clipExtent = function() { - var x0, y0, x1, y1, stream, clip, clipExtent = { - stream: function(output) { - if (stream) stream.valid = false; - stream = clip(output); - stream.valid = true; - return stream; - }, - extent: function(_) { - if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; - clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); - if (stream) stream.valid = false, stream = null; - return clipExtent; - } - }; - return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); - }; - function d3_geo_clipExtent(x0, y0, x1, y1) { - return function(listener) { - var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - listener = bufferListener; - segments = []; - polygon = []; - clean = true; - }, - polygonEnd: function() { - listener = listener_; - segments = d3.merge(segments); - var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; - if (inside || visible) { - listener.polygonStart(); - if (inside) { - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - if (visible) { - d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); - } - listener.polygonEnd(); - } - segments = polygon = ring = null; - } - }; - function insidePolygon(p) { - var wn = 0, n = polygon.length, y = p[1]; - for (var i = 0; i < n; ++i) { - for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { - b = v[j]; - if (a[1] <= y) { - if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; - } else { - if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; - } - a = b; - } - } - return wn !== 0; - } - function interpolate(from, to, direction, listener) { - var a = 0, a1 = 0; - if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { - do { - listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); - } while ((a = (a + direction + 4) % 4) !== a1); - } else { - listener.point(to[0], to[1]); - } - } - function pointVisible(x, y) { - return x0 <= x && x <= x1 && y0 <= y && y <= y1; - } - function point(x, y) { - if (pointVisible(x, y)) listener.point(x, y); - } - var x__, y__, v__, x_, y_, v_, first, clean; - function lineStart() { - clip.point = linePoint; - if (polygon) polygon.push(ring = []); - first = true; - v_ = false; - x_ = y_ = NaN; - } - function lineEnd() { - if (segments) { - linePoint(x__, y__); - if (v__ && v_) bufferListener.rejoin(); - segments.push(bufferListener.buffer()); - } - clip.point = point; - if (v_) listener.lineEnd(); - } - function linePoint(x, y) { - x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); - y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); - var v = pointVisible(x, y); - if (polygon) ring.push([ x, y ]); - if (first) { - x__ = x, y__ = y, v__ = v; - first = false; - if (v) { - listener.lineStart(); - listener.point(x, y); - } - } else { - if (v && v_) listener.point(x, y); else { - var l = { - a: { - x: x_, - y: y_ - }, - b: { - x: x, - y: y - } - }; - if (clipLine(l)) { - if (!v_) { - listener.lineStart(); - listener.point(l.a.x, l.a.y); - } - listener.point(l.b.x, l.b.y); - if (!v) listener.lineEnd(); - clean = false; - } else if (v) { - listener.lineStart(); - listener.point(x, y); - clean = false; - } - } - } - x_ = x, y_ = y, v_ = v; - } - return clip; - }; - function corner(p, direction) { - return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; - } - function compare(a, b) { - return comparePoints(a.x, b.x); - } - function comparePoints(a, b) { - var ca = corner(a, 1), cb = corner(b, 1); - return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; - } - } - function d3_geo_conic(projectAt) { - var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1); - p.parallels = function(_) { - if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ]; - return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180); - }; - return p; - } - function d3_geo_conicEqualArea(φ0, φ1) { - var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n; - function forward(λ, φ) { - var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; - return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = ρ0 - y; - return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; - }; - return forward; - } - (d3.geo.conicEqualArea = function() { - return d3_geo_conic(d3_geo_conicEqualArea); - }).raw = d3_geo_conicEqualArea; - d3.geo.albers = function() { - return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); - }; - d3.geo.albersUsa = function() { - var lower48 = d3.geo.albers(); - var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); - var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); - var point, pointStream = { - point: function(x, y) { - point = [ x, y ]; - } - }, lower48Point, alaskaPoint, hawaiiPoint; - function albersUsa(coordinates) { - var x = coordinates[0], y = coordinates[1]; - point = null; - (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); - return point; - } - albersUsa.invert = function(coordinates) { - var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; - return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); - }; - albersUsa.stream = function(stream) { - var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); - return { - point: function(x, y) { - lower48Stream.point(x, y); - alaskaStream.point(x, y); - hawaiiStream.point(x, y); - }, - sphere: function() { - lower48Stream.sphere(); - alaskaStream.sphere(); - hawaiiStream.sphere(); - }, - lineStart: function() { - lower48Stream.lineStart(); - alaskaStream.lineStart(); - hawaiiStream.lineStart(); - }, - lineEnd: function() { - lower48Stream.lineEnd(); - alaskaStream.lineEnd(); - hawaiiStream.lineEnd(); - }, - polygonStart: function() { - lower48Stream.polygonStart(); - alaskaStream.polygonStart(); - hawaiiStream.polygonStart(); - }, - polygonEnd: function() { - lower48Stream.polygonEnd(); - alaskaStream.polygonEnd(); - hawaiiStream.polygonEnd(); - } - }; - }; - albersUsa.precision = function(_) { - if (!arguments.length) return lower48.precision(); - lower48.precision(_); - alaska.precision(_); - hawaii.precision(_); - return albersUsa; - }; - albersUsa.scale = function(_) { - if (!arguments.length) return lower48.scale(); - lower48.scale(_); - alaska.scale(_ * .35); - hawaii.scale(_); - return albersUsa.translate(lower48.translate()); - }; - albersUsa.translate = function(_) { - if (!arguments.length) return lower48.translate(); - var k = lower48.scale(), x = +_[0], y = +_[1]; - lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; - alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; - hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; - return albersUsa; - }; - return albersUsa.scale(1070); - }; - var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_pathAreaPolygon = 0; - d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; - }, - polygonEnd: function() { - d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; - d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); - } - }; - function d3_geo_pathAreaRingStart() { - var x00, y00, x0, y0; - d3_geo_pathArea.point = function(x, y) { - d3_geo_pathArea.point = nextPoint; - x00 = x0 = x, y00 = y0 = y; - }; - function nextPoint(x, y) { - d3_geo_pathAreaPolygon += y0 * x - x0 * y; - x0 = x, y0 = y; - } - d3_geo_pathArea.lineEnd = function() { - nextPoint(x00, y00); - }; - } - var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; - var d3_geo_pathBounds = { - point: d3_geo_pathBoundsPoint, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: d3_noop, - polygonEnd: d3_noop - }; - function d3_geo_pathBoundsPoint(x, y) { - if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; - if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; - if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; - if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; - } - function d3_geo_pathBuffer() { - var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; - var stream = { - point: point, - lineStart: function() { - stream.point = pointLineStart; - }, - lineEnd: lineEnd, - polygonStart: function() { - stream.lineEnd = lineEndPolygon; - }, - polygonEnd: function() { - stream.lineEnd = lineEnd; - stream.point = point; - }, - pointRadius: function(_) { - pointCircle = d3_geo_pathBufferCircle(_); - return stream; - }, - result: function() { - if (buffer.length) { - var result = buffer.join(""); - buffer = []; - return result; - } - } - }; - function point(x, y) { - buffer.push("M", x, ",", y, pointCircle); - } - function pointLineStart(x, y) { - buffer.push("M", x, ",", y); - stream.point = pointLine; - } - function pointLine(x, y) { - buffer.push("L", x, ",", y); - } - function lineEnd() { - stream.point = point; - } - function lineEndPolygon() { - buffer.push("Z"); - } - return stream; - } - function d3_geo_pathBufferCircle(radius) { - return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; - } - var d3_geo_pathCentroid = { - point: d3_geo_pathCentroidPoint, - lineStart: d3_geo_pathCentroidLineStart, - lineEnd: d3_geo_pathCentroidLineEnd, - polygonStart: function() { - d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; - }, - polygonEnd: function() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; - d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; - } - }; - function d3_geo_pathCentroidPoint(x, y) { - d3_geo_centroidX0 += x; - d3_geo_centroidY0 += y; - ++d3_geo_centroidZ0; - } - function d3_geo_pathCentroidLineStart() { - var x0, y0; - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX1 += z * (x0 + x) / 2; - d3_geo_centroidY1 += z * (y0 + y) / 2; - d3_geo_centroidZ1 += z; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - } - } - function d3_geo_pathCentroidLineEnd() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - } - function d3_geo_pathCentroidRingStart() { - var x00, y00, x0, y0; - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX1 += z * (x0 + x) / 2; - d3_geo_centroidY1 += z * (y0 + y) / 2; - d3_geo_centroidZ1 += z; - z = y0 * x - x0 * y; - d3_geo_centroidX2 += z * (x0 + x); - d3_geo_centroidY2 += z * (y0 + y); - d3_geo_centroidZ2 += z * 3; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - } - d3_geo_pathCentroid.lineEnd = function() { - nextPoint(x00, y00); - }; - } - function d3_geo_pathContext(context) { - var pointRadius = 4.5; - var stream = { - point: point, - lineStart: function() { - stream.point = pointLineStart; - }, - lineEnd: lineEnd, - polygonStart: function() { - stream.lineEnd = lineEndPolygon; - }, - polygonEnd: function() { - stream.lineEnd = lineEnd; - stream.point = point; - }, - pointRadius: function(_) { - pointRadius = _; - return stream; - }, - result: d3_noop - }; - function point(x, y) { - context.moveTo(x + pointRadius, y); - context.arc(x, y, pointRadius, 0, τ); - } - function pointLineStart(x, y) { - context.moveTo(x, y); - stream.point = pointLine; - } - function pointLine(x, y) { - context.lineTo(x, y); - } - function lineEnd() { - stream.point = point; - } - function lineEndPolygon() { - context.closePath(); - } - return stream; - } - function d3_geo_resample(project) { - var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; - function resample(stream) { - return (maxDepth ? resampleRecursive : resampleNone)(stream); - } - function resampleNone(stream) { - return d3_geo_transformPoint(stream, function(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - }); - } - function resampleRecursive(stream) { - var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; - var resample = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - stream.polygonStart(); - resample.lineStart = ringStart; - }, - polygonEnd: function() { - stream.polygonEnd(); - resample.lineStart = lineStart; - } - }; - function point(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - } - function lineStart() { - x0 = NaN; - resample.point = linePoint; - stream.lineStart(); - } - function linePoint(λ, φ) { - var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); - resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); - stream.point(x0, y0); - } - function lineEnd() { - resample.point = point; - stream.lineEnd(); - } - function ringStart() { - lineStart(); - resample.point = ringPoint; - resample.lineEnd = ringEnd; - } - function ringPoint(λ, φ) { - linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; - resample.point = linePoint; - } - function ringEnd() { - resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); - resample.lineEnd = lineEnd; - lineEnd(); - } - return resample; - } - function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { - var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; - if (d2 > 4 * δ2 && depth--) { - var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; - if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { - resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); - stream.point(x2, y2); - resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); - } - } - } - resample.precision = function(_) { - if (!arguments.length) return Math.sqrt(δ2); - maxDepth = (δ2 = _ * _) > 0 && 16; - return resample; - }; - return resample; - } - d3.geo.path = function() { - var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; - function path(object) { - if (object) { - if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); - if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); - d3.geo.stream(object, cacheStream); - } - return contextStream.result(); - } - path.area = function(object) { - d3_geo_pathAreaSum = 0; - d3.geo.stream(object, projectStream(d3_geo_pathArea)); - return d3_geo_pathAreaSum; - }; - path.centroid = function(object) { - d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; - d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); - return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; - }; - path.bounds = function(object) { - d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); - d3.geo.stream(object, projectStream(d3_geo_pathBounds)); - return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; - }; - path.projection = function(_) { - if (!arguments.length) return projection; - projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; - return reset(); - }; - path.context = function(_) { - if (!arguments.length) return context; - contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); - if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); - return reset(); - }; - path.pointRadius = function(_) { - if (!arguments.length) return pointRadius; - pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); - return path; - }; - function reset() { - cacheStream = null; - return path; - } - return path.projection(d3.geo.albersUsa()).context(null); - }; - function d3_geo_pathProjectStream(project) { - var resample = d3_geo_resample(function(x, y) { - return project([ x * d3_degrees, y * d3_degrees ]); - }); - return function(stream) { - return d3_geo_projectionRadians(resample(stream)); - }; - } - d3.geo.transform = function(methods) { - return { - stream: function(stream) { - var transform = new d3_geo_transform(stream); - for (var k in methods) transform[k] = methods[k]; - return transform; - } - }; - }; - function d3_geo_transform(stream) { - this.stream = stream; - } - d3_geo_transform.prototype = { - point: function(x, y) { - this.stream.point(x, y); - }, - sphere: function() { - this.stream.sphere(); - }, - lineStart: function() { - this.stream.lineStart(); - }, - lineEnd: function() { - this.stream.lineEnd(); - }, - polygonStart: function() { - this.stream.polygonStart(); - }, - polygonEnd: function() { - this.stream.polygonEnd(); - } - }; - function d3_geo_transformPoint(stream, point) { - return { - point: point, - sphere: function() { - stream.sphere(); - }, - lineStart: function() { - stream.lineStart(); - }, - lineEnd: function() { - stream.lineEnd(); - }, - polygonStart: function() { - stream.polygonStart(); - }, - polygonEnd: function() { - stream.polygonEnd(); - } - }; - } - d3.geo.projection = d3_geo_projection; - d3.geo.projectionMutator = d3_geo_projectionMutator; - function d3_geo_projection(project) { - return d3_geo_projectionMutator(function() { - return project; - })(); - } - function d3_geo_projectionMutator(projectAt) { - var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { - x = project(x, y); - return [ x[0] * k + δx, δy - x[1] * k ]; - }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; - function projection(point) { - point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); - return [ point[0] * k + δx, δy - point[1] * k ]; - } - function invert(point) { - point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); - return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; - } - projection.stream = function(output) { - if (stream) stream.valid = false; - stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); - stream.valid = true; - return stream; - }; - projection.clipAngle = function(_) { - if (!arguments.length) return clipAngle; - preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); - return invalidate(); - }; - projection.clipExtent = function(_) { - if (!arguments.length) return clipExtent; - clipExtent = _; - postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; - return invalidate(); - }; - projection.scale = function(_) { - if (!arguments.length) return k; - k = +_; - return reset(); - }; - projection.translate = function(_) { - if (!arguments.length) return [ x, y ]; - x = +_[0]; - y = +_[1]; - return reset(); - }; - projection.center = function(_) { - if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; - λ = _[0] % 360 * d3_radians; - φ = _[1] % 360 * d3_radians; - return reset(); - }; - projection.rotate = function(_) { - if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; - δλ = _[0] % 360 * d3_radians; - δφ = _[1] % 360 * d3_radians; - δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; - return reset(); - }; - d3.rebind(projection, projectResample, "precision"); - function reset() { - projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); - var center = project(λ, φ); - δx = x - center[0] * k; - δy = y + center[1] * k; - return invalidate(); - } - function invalidate() { - if (stream) stream.valid = false, stream = null; - return projection; - } - return function() { - project = projectAt.apply(this, arguments); - projection.invert = project.invert && invert; - return reset(); - }; - } - function d3_geo_projectionRadians(stream) { - return d3_geo_transformPoint(stream, function(x, y) { - stream.point(x * d3_radians, y * d3_radians); - }); - } - function d3_geo_equirectangular(λ, φ) { - return [ λ, φ ]; - } - (d3.geo.equirectangular = function() { - return d3_geo_projection(d3_geo_equirectangular); - }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; - d3.geo.rotation = function(rotate) { - rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); - function forward(coordinates) { - coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); - return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; - } - forward.invert = function(coordinates) { - coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); - return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; - }; - return forward; - }; - function d3_geo_identityRotation(λ, φ) { - return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; - } - d3_geo_identityRotation.invert = d3_geo_equirectangular; - function d3_geo_rotation(δλ, δφ, δγ) { - return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; - } - function d3_geo_forwardRotationλ(δλ) { - return function(λ, φ) { - return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; - }; - } - function d3_geo_rotationλ(δλ) { - var rotation = d3_geo_forwardRotationλ(δλ); - rotation.invert = d3_geo_forwardRotationλ(-δλ); - return rotation; - } - function d3_geo_rotationφγ(δφ, δγ) { - var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); - function rotation(λ, φ) { - var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; - return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ]; - } - rotation.invert = function(λ, φ) { - var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; - return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ]; - }; - return rotation; - } - d3.geo.circle = function() { - var origin = [ 0, 0 ], angle, precision = 6, interpolate; - function circle() { - var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; - interpolate(null, null, 1, { - point: function(x, y) { - ring.push(x = rotate(x, y)); - x[0] *= d3_degrees, x[1] *= d3_degrees; - } - }); - return { - type: "Polygon", - coordinates: [ ring ] - }; - } - circle.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return circle; - }; - circle.angle = function(x) { - if (!arguments.length) return angle; - interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); - return circle; - }; - circle.precision = function(_) { - if (!arguments.length) return precision; - interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); - return circle; - }; - return circle.angle(90); - }; - function d3_geo_circleInterpolate(radius, precision) { - var cr = Math.cos(radius), sr = Math.sin(radius); - return function(from, to, direction, listener) { - var step = direction * precision; - if (from != null) { - from = d3_geo_circleAngle(cr, from); - to = d3_geo_circleAngle(cr, to); - if (direction > 0 ? from < to : from > to) from += direction * τ; - } else { - from = radius + direction * τ; - to = radius - .5 * step; - } - for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { - listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); - } - }; - } - function d3_geo_circleAngle(cr, point) { - var a = d3_geo_cartesian(point); - a[0] -= cr; - d3_geo_cartesianNormalize(a); - var angle = d3_acos(-a[1]); - return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); - } - d3.geo.distance = function(a, b) { - var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t; - return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ); - }; - d3.geo.graticule = function() { - var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; - function graticule() { - return { - type: "MultiLineString", - coordinates: lines() - }; - } - function lines() { - return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { - return abs(x % DX) > ε; - }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { - return abs(y % DY) > ε; - }).map(y)); - } - graticule.lines = function() { - return lines().map(function(coordinates) { - return { - type: "LineString", - coordinates: coordinates - }; - }); - }; - graticule.outline = function() { - return { - type: "Polygon", - coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] - }; - }; - graticule.extent = function(_) { - if (!arguments.length) return graticule.minorExtent(); - return graticule.majorExtent(_).minorExtent(_); - }; - graticule.majorExtent = function(_) { - if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; - X0 = +_[0][0], X1 = +_[1][0]; - Y0 = +_[0][1], Y1 = +_[1][1]; - if (X0 > X1) _ = X0, X0 = X1, X1 = _; - if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; - return graticule.precision(precision); - }; - graticule.minorExtent = function(_) { - if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; - x0 = +_[0][0], x1 = +_[1][0]; - y0 = +_[0][1], y1 = +_[1][1]; - if (x0 > x1) _ = x0, x0 = x1, x1 = _; - if (y0 > y1) _ = y0, y0 = y1, y1 = _; - return graticule.precision(precision); - }; - graticule.step = function(_) { - if (!arguments.length) return graticule.minorStep(); - return graticule.majorStep(_).minorStep(_); - }; - graticule.majorStep = function(_) { - if (!arguments.length) return [ DX, DY ]; - DX = +_[0], DY = +_[1]; - return graticule; - }; - graticule.minorStep = function(_) { - if (!arguments.length) return [ dx, dy ]; - dx = +_[0], dy = +_[1]; - return graticule; - }; - graticule.precision = function(_) { - if (!arguments.length) return precision; - precision = +_; - x = d3_geo_graticuleX(y0, y1, 90); - y = d3_geo_graticuleY(x0, x1, precision); - X = d3_geo_graticuleX(Y0, Y1, 90); - Y = d3_geo_graticuleY(X0, X1, precision); - return graticule; - }; - return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); - }; - function d3_geo_graticuleX(y0, y1, dy) { - var y = d3.range(y0, y1 - ε, dy).concat(y1); - return function(x) { - return y.map(function(y) { - return [ x, y ]; - }); - }; - } - function d3_geo_graticuleY(x0, x1, dx) { - var x = d3.range(x0, x1 - ε, dx).concat(x1); - return function(y) { - return x.map(function(x) { - return [ x, y ]; - }); - }; - } - function d3_source(d) { - return d.source; - } - function d3_target(d) { - return d.target; - } - d3.geo.greatArc = function() { - var source = d3_source, source_, target = d3_target, target_; - function greatArc() { - return { - type: "LineString", - coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] - }; - } - greatArc.distance = function() { - return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); - }; - greatArc.source = function(_) { - if (!arguments.length) return source; - source = _, source_ = typeof _ === "function" ? null : _; - return greatArc; - }; - greatArc.target = function(_) { - if (!arguments.length) return target; - target = _, target_ = typeof _ === "function" ? null : _; - return greatArc; - }; - greatArc.precision = function() { - return arguments.length ? greatArc : 0; - }; - return greatArc; - }; - d3.geo.interpolate = function(source, target) { - return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); - }; - function d3_geo_interpolate(x0, y0, x1, y1) { - var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); - var interpolate = d ? function(t) { - var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; - return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; - } : function() { - return [ x0 * d3_degrees, y0 * d3_degrees ]; - }; - interpolate.distance = d; - return interpolate; - } - d3.geo.length = function(object) { - d3_geo_lengthSum = 0; - d3.geo.stream(object, d3_geo_length); - return d3_geo_lengthSum; - }; - var d3_geo_lengthSum; - var d3_geo_length = { - sphere: d3_noop, - point: d3_noop, - lineStart: d3_geo_lengthLineStart, - lineEnd: d3_noop, - polygonStart: d3_noop, - polygonEnd: d3_noop - }; - function d3_geo_lengthLineStart() { - var λ0, sinφ0, cosφ0; - d3_geo_length.point = function(λ, φ) { - λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ); - d3_geo_length.point = nextPoint; - }; - d3_geo_length.lineEnd = function() { - d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; - }; - function nextPoint(λ, φ) { - var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t); - d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ); - λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ; - } - } - function d3_geo_azimuthal(scale, angle) { - function azimuthal(λ, φ) { - var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); - return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; - } - azimuthal.invert = function(x, y) { - var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c); - return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ]; - }; - return azimuthal; - } - var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { - return Math.sqrt(2 / (1 + cosλcosφ)); - }, function(ρ) { - return 2 * Math.asin(ρ / 2); - }); - (d3.geo.azimuthalEqualArea = function() { - return d3_geo_projection(d3_geo_azimuthalEqualArea); - }).raw = d3_geo_azimuthalEqualArea; - var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { - var c = Math.acos(cosλcosφ); - return c && c / Math.sin(c); - }, d3_identity); - (d3.geo.azimuthalEquidistant = function() { - return d3_geo_projection(d3_geo_azimuthalEquidistant); - }).raw = d3_geo_azimuthalEquidistant; - function d3_geo_conicConformal(φ0, φ1) { - var cosφ0 = Math.cos(φ0), t = function(φ) { - return Math.tan(π / 4 + φ / 2); - }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n; - if (!n) return d3_geo_mercator; - function forward(λ, φ) { - if (F > 0) { - if (φ < -halfπ + ε) φ = -halfπ + ε; - } else { - if (φ > halfπ - ε) φ = halfπ - ε; - } - var ρ = F / Math.pow(t(φ), n); - return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y); - return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ]; - }; - return forward; - } - (d3.geo.conicConformal = function() { - return d3_geo_conic(d3_geo_conicConformal); - }).raw = d3_geo_conicConformal; - function d3_geo_conicEquidistant(φ0, φ1) { - var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0; - if (abs(n) < ε) return d3_geo_equirectangular; - function forward(λ, φ) { - var ρ = G - φ; - return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = G - y; - return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ]; - }; - return forward; - } - (d3.geo.conicEquidistant = function() { - return d3_geo_conic(d3_geo_conicEquidistant); - }).raw = d3_geo_conicEquidistant; - var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { - return 1 / cosλcosφ; - }, Math.atan); - (d3.geo.gnomonic = function() { - return d3_geo_projection(d3_geo_gnomonic); - }).raw = d3_geo_gnomonic; - function d3_geo_mercator(λ, φ) { - return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ]; - } - d3_geo_mercator.invert = function(x, y) { - return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ]; - }; - function d3_geo_mercatorProjection(project) { - var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; - m.scale = function() { - var v = scale.apply(m, arguments); - return v === m ? clipAuto ? m.clipExtent(null) : m : v; - }; - m.translate = function() { - var v = translate.apply(m, arguments); - return v === m ? clipAuto ? m.clipExtent(null) : m : v; - }; - m.clipExtent = function(_) { - var v = clipExtent.apply(m, arguments); - if (v === m) { - if (clipAuto = _ == null) { - var k = π * scale(), t = translate(); - clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); - } - } else if (clipAuto) { - v = null; - } - return v; - }; - return m.clipExtent(null); - } - (d3.geo.mercator = function() { - return d3_geo_mercatorProjection(d3_geo_mercator); - }).raw = d3_geo_mercator; - var d3_geo_orthographic = d3_geo_azimuthal(function() { - return 1; - }, Math.asin); - (d3.geo.orthographic = function() { - return d3_geo_projection(d3_geo_orthographic); - }).raw = d3_geo_orthographic; - var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { - return 1 / (1 + cosλcosφ); - }, function(ρ) { - return 2 * Math.atan(ρ); - }); - (d3.geo.stereographic = function() { - return d3_geo_projection(d3_geo_stereographic); - }).raw = d3_geo_stereographic; - function d3_geo_transverseMercator(λ, φ) { - return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ]; - } - d3_geo_transverseMercator.invert = function(x, y) { - return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ]; - }; - (d3.geo.transverseMercator = function() { - var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; - projection.center = function(_) { - return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]); - }; - projection.rotate = function(_) { - return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), - [ _[0], _[1], _[2] - 90 ]); - }; - return rotate([ 0, 0, 90 ]); - }).raw = d3_geo_transverseMercator; - d3.geom = {}; - function d3_geom_pointX(d) { - return d[0]; - } - function d3_geom_pointY(d) { - return d[1]; - } - d3.geom.hull = function(vertices) { - var x = d3_geom_pointX, y = d3_geom_pointY; - if (arguments.length) return hull(vertices); - function hull(data) { - if (data.length < 3) return []; - var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; - for (i = 0; i < n; i++) { - points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); - } - points.sort(d3_geom_hullOrder); - for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); - var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); - var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = []; - for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); - for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); - return polygon; - } - hull.x = function(_) { - return arguments.length ? (x = _, hull) : x; - }; - hull.y = function(_) { - return arguments.length ? (y = _, hull) : y; - }; - return hull; - }; - function d3_geom_hullUpper(points) { - var n = points.length, hull = [ 0, 1 ], hs = 2; - for (var i = 2; i < n; i++) { - while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; - hull[hs++] = i; - } - return hull.slice(0, hs); - } - function d3_geom_hullOrder(a, b) { - return a[0] - b[0] || a[1] - b[1]; - } - d3.geom.polygon = function(coordinates) { - d3_subclass(coordinates, d3_geom_polygonPrototype); - return coordinates; - }; - var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; - d3_geom_polygonPrototype.area = function() { - var i = -1, n = this.length, a, b = this[n - 1], area = 0; - while (++i < n) { - a = b; - b = this[i]; - area += a[1] * b[0] - a[0] * b[1]; - } - return area * .5; - }; - d3_geom_polygonPrototype.centroid = function(k) { - var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; - if (!arguments.length) k = -1 / (6 * this.area()); - while (++i < n) { - a = b; - b = this[i]; - c = a[0] * b[1] - b[0] * a[1]; - x += (a[0] + b[0]) * c; - y += (a[1] + b[1]) * c; - } - return [ x * k, y * k ]; - }; - d3_geom_polygonPrototype.clip = function(subject) { - var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; - while (++i < n) { - input = subject.slice(); - subject.length = 0; - b = this[i]; - c = input[(m = input.length - closed) - 1]; - j = -1; - while (++j < m) { - d = input[j]; - if (d3_geom_polygonInside(d, a, b)) { - if (!d3_geom_polygonInside(c, a, b)) { - subject.push(d3_geom_polygonIntersect(c, d, a, b)); - } - subject.push(d); - } else if (d3_geom_polygonInside(c, a, b)) { - subject.push(d3_geom_polygonIntersect(c, d, a, b)); - } - c = d; - } - if (closed) subject.push(subject[0]); - a = b; - } - return subject; - }; - function d3_geom_polygonInside(p, a, b) { - return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); - } - function d3_geom_polygonIntersect(c, d, a, b) { - var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); - return [ x1 + ua * x21, y1 + ua * y21 ]; - } - function d3_geom_polygonClosed(coordinates) { - var a = coordinates[0], b = coordinates[coordinates.length - 1]; - return !(a[0] - b[0] || a[1] - b[1]); - } - var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; - function d3_geom_voronoiBeach() { - d3_geom_voronoiRedBlackNode(this); - this.edge = this.site = this.circle = null; - } - function d3_geom_voronoiCreateBeach(site) { - var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); - beach.site = site; - return beach; - } - function d3_geom_voronoiDetachBeach(beach) { - d3_geom_voronoiDetachCircle(beach); - d3_geom_voronoiBeaches.remove(beach); - d3_geom_voronoiBeachPool.push(beach); - d3_geom_voronoiRedBlackNode(beach); - } - function d3_geom_voronoiRemoveBeach(beach) { - var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { - x: x, - y: y - }, previous = beach.P, next = beach.N, disappearing = [ beach ]; - d3_geom_voronoiDetachBeach(beach); - var lArc = previous; - while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { - previous = lArc.P; - disappearing.unshift(lArc); - d3_geom_voronoiDetachBeach(lArc); - lArc = previous; - } - disappearing.unshift(lArc); - d3_geom_voronoiDetachCircle(lArc); - var rArc = next; - while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { - next = rArc.N; - disappearing.push(rArc); - d3_geom_voronoiDetachBeach(rArc); - rArc = next; - } - disappearing.push(rArc); - d3_geom_voronoiDetachCircle(rArc); - var nArcs = disappearing.length, iArc; - for (iArc = 1; iArc < nArcs; ++iArc) { - rArc = disappearing[iArc]; - lArc = disappearing[iArc - 1]; - d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); - } - lArc = disappearing[0]; - rArc = disappearing[nArcs - 1]; - rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - } - function d3_geom_voronoiAddBeach(site) { - var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; - while (node) { - dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; - if (dxl > ε) node = node.L; else { - dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); - if (dxr > ε) { - if (!node.R) { - lArc = node; - break; - } - node = node.R; - } else { - if (dxl > -ε) { - lArc = node.P; - rArc = node; - } else if (dxr > -ε) { - lArc = node; - rArc = node.N; - } else { - lArc = rArc = node; - } - break; - } - } - } - var newArc = d3_geom_voronoiCreateBeach(site); - d3_geom_voronoiBeaches.insert(lArc, newArc); - if (!lArc && !rArc) return; - if (lArc === rArc) { - d3_geom_voronoiDetachCircle(lArc); - rArc = d3_geom_voronoiCreateBeach(lArc.site); - d3_geom_voronoiBeaches.insert(newArc, rArc); - newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - return; - } - if (!rArc) { - newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); - return; - } - d3_geom_voronoiDetachCircle(lArc); - d3_geom_voronoiDetachCircle(rArc); - var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { - x: (cy * hb - by * hc) / d + ax, - y: (bx * hc - cx * hb) / d + ay - }; - d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); - newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); - rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - } - function d3_geom_voronoiLeftBreakPoint(arc, directrix) { - var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; - if (!pby2) return rfocx; - var lArc = arc.P; - if (!lArc) return -Infinity; - site = lArc.site; - var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; - if (!plby2) return lfocx; - var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; - if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; - return (rfocx + lfocx) / 2; - } - function d3_geom_voronoiRightBreakPoint(arc, directrix) { - var rArc = arc.N; - if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); - var site = arc.site; - return site.y === directrix ? site.x : Infinity; - } - function d3_geom_voronoiCell(site) { - this.site = site; - this.edges = []; - } - d3_geom_voronoiCell.prototype.prepare = function() { - var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; - while (iHalfEdge--) { - edge = halfEdges[iHalfEdge].edge; - if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); - } - halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); - return halfEdges.length; - }; - function d3_geom_voronoiCloseCells(extent) { - var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; - while (iCell--) { - cell = cells[iCell]; - if (!cell || !cell.prepare()) continue; - halfEdges = cell.edges; - nHalfEdges = halfEdges.length; - iHalfEdge = 0; - while (iHalfEdge < nHalfEdges) { - end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; - start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; - if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { - halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { - x: x0, - y: abs(x2 - x0) < ε ? y2 : y1 - } : abs(y3 - y1) < ε && x1 - x3 > ε ? { - x: abs(y2 - y1) < ε ? x2 : x1, - y: y1 - } : abs(x3 - x1) < ε && y3 - y0 > ε ? { - x: x1, - y: abs(x2 - x1) < ε ? y2 : y0 - } : abs(y3 - y0) < ε && x3 - x0 > ε ? { - x: abs(y2 - y0) < ε ? x2 : x0, - y: y0 - } : null), cell.site, null)); - ++nHalfEdges; - } - } - } - } - function d3_geom_voronoiHalfEdgeOrder(a, b) { - return b.angle - a.angle; - } - function d3_geom_voronoiCircle() { - d3_geom_voronoiRedBlackNode(this); - this.x = this.y = this.arc = this.site = this.cy = null; - } - function d3_geom_voronoiAttachCircle(arc) { - var lArc = arc.P, rArc = arc.N; - if (!lArc || !rArc) return; - var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; - if (lSite === rSite) return; - var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; - var d = 2 * (ax * cy - ay * cx); - if (d >= -ε2) return; - var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; - var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); - circle.arc = arc; - circle.site = cSite; - circle.x = x + bx; - circle.y = cy + Math.sqrt(x * x + y * y); - circle.cy = cy; - arc.circle = circle; - var before = null, node = d3_geom_voronoiCircles._; - while (node) { - if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { - if (node.L) node = node.L; else { - before = node.P; - break; - } - } else { - if (node.R) node = node.R; else { - before = node; - break; - } - } - } - d3_geom_voronoiCircles.insert(before, circle); - if (!before) d3_geom_voronoiFirstCircle = circle; - } - function d3_geom_voronoiDetachCircle(arc) { - var circle = arc.circle; - if (circle) { - if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; - d3_geom_voronoiCircles.remove(circle); - d3_geom_voronoiCirclePool.push(circle); - d3_geom_voronoiRedBlackNode(circle); - arc.circle = null; - } - } - function d3_geom_voronoiClipEdges(extent) { - var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; - while (i--) { - e = edges[i]; - if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { - e.a = e.b = null; - edges.splice(i, 1); - } - } - } - function d3_geom_voronoiConnectEdge(edge, extent) { - var vb = edge.b; - if (vb) return true; - var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; - if (ry === ly) { - if (fx < x0 || fx >= x1) return; - if (lx > rx) { - if (!va) va = { - x: fx, - y: y0 - }; else if (va.y >= y1) return; - vb = { - x: fx, - y: y1 - }; - } else { - if (!va) va = { - x: fx, - y: y1 - }; else if (va.y < y0) return; - vb = { - x: fx, - y: y0 - }; - } - } else { - fm = (lx - rx) / (ry - ly); - fb = fy - fm * fx; - if (fm < -1 || fm > 1) { - if (lx > rx) { - if (!va) va = { - x: (y0 - fb) / fm, - y: y0 - }; else if (va.y >= y1) return; - vb = { - x: (y1 - fb) / fm, - y: y1 - }; - } else { - if (!va) va = { - x: (y1 - fb) / fm, - y: y1 - }; else if (va.y < y0) return; - vb = { - x: (y0 - fb) / fm, - y: y0 - }; - } - } else { - if (ly < ry) { - if (!va) va = { - x: x0, - y: fm * x0 + fb - }; else if (va.x >= x1) return; - vb = { - x: x1, - y: fm * x1 + fb - }; - } else { - if (!va) va = { - x: x1, - y: fm * x1 + fb - }; else if (va.x < x0) return; - vb = { - x: x0, - y: fm * x0 + fb - }; - } - } - } - edge.a = va; - edge.b = vb; - return true; - } - function d3_geom_voronoiEdge(lSite, rSite) { - this.l = lSite; - this.r = rSite; - this.a = this.b = null; - } - function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { - var edge = new d3_geom_voronoiEdge(lSite, rSite); - d3_geom_voronoiEdges.push(edge); - if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); - if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); - d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); - d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); - return edge; - } - function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { - var edge = new d3_geom_voronoiEdge(lSite, null); - edge.a = va; - edge.b = vb; - d3_geom_voronoiEdges.push(edge); - return edge; - } - function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { - if (!edge.a && !edge.b) { - edge.a = vertex; - edge.l = lSite; - edge.r = rSite; - } else if (edge.l === rSite) { - edge.b = vertex; - } else { - edge.a = vertex; - } - } - function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { - var va = edge.a, vb = edge.b; - this.edge = edge; - this.site = lSite; - this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); - } - d3_geom_voronoiHalfEdge.prototype = { - start: function() { - return this.edge.l === this.site ? this.edge.a : this.edge.b; - }, - end: function() { - return this.edge.l === this.site ? this.edge.b : this.edge.a; - } - }; - function d3_geom_voronoiRedBlackTree() { - this._ = null; - } - function d3_geom_voronoiRedBlackNode(node) { - node.U = node.C = node.L = node.R = node.P = node.N = null; - } - d3_geom_voronoiRedBlackTree.prototype = { - insert: function(after, node) { - var parent, grandpa, uncle; - if (after) { - node.P = after; - node.N = after.N; - if (after.N) after.N.P = node; - after.N = node; - if (after.R) { - after = after.R; - while (after.L) after = after.L; - after.L = node; - } else { - after.R = node; - } - parent = after; - } else if (this._) { - after = d3_geom_voronoiRedBlackFirst(this._); - node.P = null; - node.N = after; - after.P = after.L = node; - parent = after; - } else { - node.P = node.N = null; - this._ = node; - parent = null; - } - node.L = node.R = null; - node.U = parent; - node.C = true; - after = node; - while (parent && parent.C) { - grandpa = parent.U; - if (parent === grandpa.L) { - uncle = grandpa.R; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.R) { - d3_geom_voronoiRedBlackRotateLeft(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - d3_geom_voronoiRedBlackRotateRight(this, grandpa); - } - } else { - uncle = grandpa.L; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.L) { - d3_geom_voronoiRedBlackRotateRight(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, grandpa); - } - } - parent = after.U; - } - this._.C = false; - }, - remove: function(node) { - if (node.N) node.N.P = node.P; - if (node.P) node.P.N = node.N; - node.N = node.P = null; - var parent = node.U, sibling, left = node.L, right = node.R, next, red; - if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); - if (parent) { - if (parent.L === node) parent.L = next; else parent.R = next; - } else { - this._ = next; - } - if (left && right) { - red = next.C; - next.C = node.C; - next.L = left; - left.U = next; - if (next !== right) { - parent = next.U; - next.U = node.U; - node = next.R; - parent.L = node; - next.R = right; - right.U = next; - } else { - next.U = parent; - parent = next; - node = next.R; - } - } else { - red = node.C; - node = next; - } - if (node) node.U = parent; - if (red) return; - if (node && node.C) { - node.C = false; - return; - } - do { - if (node === this._) break; - if (node === parent.L) { - sibling = parent.R; - if (sibling.C) { - sibling.C = false; - parent.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, parent); - sibling = parent.R; - } - if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { - if (!sibling.R || !sibling.R.C) { - sibling.L.C = false; - sibling.C = true; - d3_geom_voronoiRedBlackRotateRight(this, sibling); - sibling = parent.R; - } - sibling.C = parent.C; - parent.C = sibling.R.C = false; - d3_geom_voronoiRedBlackRotateLeft(this, parent); - node = this._; - break; - } - } else { - sibling = parent.L; - if (sibling.C) { - sibling.C = false; - parent.C = true; - d3_geom_voronoiRedBlackRotateRight(this, parent); - sibling = parent.L; - } - if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { - if (!sibling.L || !sibling.L.C) { - sibling.R.C = false; - sibling.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, sibling); - sibling = parent.L; - } - sibling.C = parent.C; - parent.C = sibling.L.C = false; - d3_geom_voronoiRedBlackRotateRight(this, parent); - node = this._; - break; - } - } - sibling.C = true; - node = parent; - parent = parent.U; - } while (!node.C); - if (node) node.C = false; - } - }; - function d3_geom_voronoiRedBlackRotateLeft(tree, node) { - var p = node, q = node.R, parent = p.U; - if (parent) { - if (parent.L === p) parent.L = q; else parent.R = q; - } else { - tree._ = q; - } - q.U = parent; - p.U = q; - p.R = q.L; - if (p.R) p.R.U = p; - q.L = p; - } - function d3_geom_voronoiRedBlackRotateRight(tree, node) { - var p = node, q = node.L, parent = p.U; - if (parent) { - if (parent.L === p) parent.L = q; else parent.R = q; - } else { - tree._ = q; - } - q.U = parent; - p.U = q; - p.L = q.R; - if (p.L) p.L.U = p; - q.R = p; - } - function d3_geom_voronoiRedBlackFirst(node) { - while (node.L) node = node.L; - return node; - } - function d3_geom_voronoi(sites, bbox) { - var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; - d3_geom_voronoiEdges = []; - d3_geom_voronoiCells = new Array(sites.length); - d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); - d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); - while (true) { - circle = d3_geom_voronoiFirstCircle; - if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { - if (site.x !== x0 || site.y !== y0) { - d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); - d3_geom_voronoiAddBeach(site); - x0 = site.x, y0 = site.y; - } - site = sites.pop(); - } else if (circle) { - d3_geom_voronoiRemoveBeach(circle.arc); - } else { - break; - } - } - if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); - var diagram = { - cells: d3_geom_voronoiCells, - edges: d3_geom_voronoiEdges - }; - d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; - return diagram; - } - function d3_geom_voronoiVertexOrder(a, b) { - return b.y - a.y || b.x - a.x; - } - d3.geom.voronoi = function(points) { - var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; - if (points) return voronoi(points); - function voronoi(data) { - var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; - d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { - var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { - var s = e.start(); - return [ s.x, s.y ]; - }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; - polygon.point = data[i]; - }); - return polygons; - } - function sites(data) { - return data.map(function(d, i) { - return { - x: Math.round(fx(d, i) / ε) * ε, - y: Math.round(fy(d, i) / ε) * ε, - i: i - }; - }); - } - voronoi.links = function(data) { - return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { - return edge.l && edge.r; - }).map(function(edge) { - return { - source: data[edge.l.i], - target: data[edge.r.i] - }; - }); - }; - voronoi.triangles = function(data) { - var triangles = []; - d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { - var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; - while (++j < m) { - e0 = e1; - s0 = s1; - e1 = edges[j].edge; - s1 = e1.l === site ? e1.r : e1.l; - if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { - triangles.push([ data[i], data[s0.i], data[s1.i] ]); - } - } - }); - return triangles; - }; - voronoi.x = function(_) { - return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; - }; - voronoi.y = function(_) { - return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; - }; - voronoi.clipExtent = function(_) { - if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; - clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; - return voronoi; - }; - voronoi.size = function(_) { - if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; - return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); - }; - return voronoi; - }; - var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; - function d3_geom_voronoiTriangleArea(a, b, c) { - return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); - } - d3.geom.delaunay = function(vertices) { - return d3.geom.voronoi().triangles(vertices); - }; - d3.geom.quadtree = function(points, x1, y1, x2, y2) { - var x = d3_geom_pointX, y = d3_geom_pointY, compat; - if (compat = arguments.length) { - x = d3_geom_quadtreeCompatX; - y = d3_geom_quadtreeCompatY; - if (compat === 3) { - y2 = y1; - x2 = x1; - y1 = x1 = 0; - } - return quadtree(points); - } - function quadtree(data) { - var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; - if (x1 != null) { - x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; - } else { - x2_ = y2_ = -(x1_ = y1_ = Infinity); - xs = [], ys = []; - n = data.length; - if (compat) for (i = 0; i < n; ++i) { - d = data[i]; - if (d.x < x1_) x1_ = d.x; - if (d.y < y1_) y1_ = d.y; - if (d.x > x2_) x2_ = d.x; - if (d.y > y2_) y2_ = d.y; - xs.push(d.x); - ys.push(d.y); - } else for (i = 0; i < n; ++i) { - var x_ = +fx(d = data[i], i), y_ = +fy(d, i); - if (x_ < x1_) x1_ = x_; - if (y_ < y1_) y1_ = y_; - if (x_ > x2_) x2_ = x_; - if (y_ > y2_) y2_ = y_; - xs.push(x_); - ys.push(y_); - } - } - var dx = x2_ - x1_, dy = y2_ - y1_; - if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; - function insert(n, d, x, y, x1, y1, x2, y2) { - if (isNaN(x) || isNaN(y)) return; - if (n.leaf) { - var nx = n.x, ny = n.y; - if (nx != null) { - if (abs(nx - x) + abs(ny - y) < .01) { - insertChild(n, d, x, y, x1, y1, x2, y2); - } else { - var nPoint = n.point; - n.x = n.y = n.point = null; - insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); - insertChild(n, d, x, y, x1, y1, x2, y2); - } - } else { - n.x = x, n.y = y, n.point = d; - } - } else { - insertChild(n, d, x, y, x1, y1, x2, y2); - } - } - function insertChild(n, d, x, y, x1, y1, x2, y2) { - var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right; - n.leaf = false; - n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); - if (right) x1 = xm; else x2 = xm; - if (below) y1 = ym; else y2 = ym; - insert(n, d, x, y, x1, y1, x2, y2); - } - var root = d3_geom_quadtreeNode(); - root.add = function(d) { - insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); - }; - root.visit = function(f) { - d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); - }; - root.find = function(point) { - return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_); - }; - i = -1; - if (x1 == null) { - while (++i < n) { - insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); - } - --i; - } else data.forEach(root.add); - xs = ys = data = d = null; - return root; - } - quadtree.x = function(_) { - return arguments.length ? (x = _, quadtree) : x; - }; - quadtree.y = function(_) { - return arguments.length ? (y = _, quadtree) : y; - }; - quadtree.extent = function(_) { - if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; - if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], - y2 = +_[1][1]; - return quadtree; - }; - quadtree.size = function(_) { - if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; - if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; - return quadtree; - }; - return quadtree; - }; - function d3_geom_quadtreeCompatX(d) { - return d.x; - } - function d3_geom_quadtreeCompatY(d) { - return d.y; - } - function d3_geom_quadtreeNode() { - return { - leaf: true, - nodes: [], - point: null, - x: null, - y: null - }; - } - function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { - if (!f(node, x1, y1, x2, y2)) { - var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; - if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); - if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); - if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); - if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); - } - } - function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) { - var minDistance2 = Infinity, closestPoint; - (function find(node, x1, y1, x2, y2) { - if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return; - if (point = node.point) { - var point, dx = x - point[0], dy = y - point[1], distance2 = dx * dx + dy * dy; - if (distance2 < minDistance2) { - var distance = Math.sqrt(minDistance2 = distance2); - x0 = x - distance, y0 = y - distance; - x3 = x + distance, y3 = y + distance; - closestPoint = point; - } - } - var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym; - for (var i = below << 1 | right, j = i + 4; i < j; ++i) { - if (node = children[i & 3]) switch (i & 3) { - case 0: - find(node, x1, y1, xm, ym); - break; - - case 1: - find(node, xm, y1, x2, ym); - break; - - case 2: - find(node, x1, ym, xm, y2); - break; - - case 3: - find(node, xm, ym, x2, y2); - break; - } - } - })(root, x0, y0, x3, y3); - return closestPoint; - } - d3.interpolateRgb = d3_interpolateRgb; - function d3_interpolateRgb(a, b) { - a = d3.rgb(a); - b = d3.rgb(b); - var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; - return function(t) { - return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); - }; - } - d3.interpolateObject = d3_interpolateObject; - function d3_interpolateObject(a, b) { - var i = {}, c = {}, k; - for (k in a) { - if (k in b) { - i[k] = d3_interpolate(a[k], b[k]); - } else { - c[k] = a[k]; - } - } - for (k in b) { - if (!(k in a)) { - c[k] = b[k]; - } - } - return function(t) { - for (k in i) c[k] = i[k](t); - return c; - }; - } - d3.interpolateNumber = d3_interpolateNumber; - function d3_interpolateNumber(a, b) { - a = +a, b = +b; - return function(t) { - return a * (1 - t) + b * t; - }; - } - d3.interpolateString = d3_interpolateString; - function d3_interpolateString(a, b) { - var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; - a = a + "", b = b + ""; - while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) { - if ((bs = bm.index) > bi) { - bs = b.slice(bi, bs); - if (s[i]) s[i] += bs; else s[++i] = bs; - } - if ((am = am[0]) === (bm = bm[0])) { - if (s[i]) s[i] += bm; else s[++i] = bm; - } else { - s[++i] = null; - q.push({ - i: i, - x: d3_interpolateNumber(am, bm) - }); - } - bi = d3_interpolate_numberB.lastIndex; - } - if (bi < b.length) { - bs = b.slice(bi); - if (s[i]) s[i] += bs; else s[++i] = bs; - } - return s.length < 2 ? q[0] ? (b = q[0].x, function(t) { - return b(t) + ""; - }) : function() { - return b; - } : (b = q.length, function(t) { - for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }); - } - var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g"); - d3.interpolate = d3_interpolate; - function d3_interpolate(a, b) { - var i = d3.interpolators.length, f; - while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; - return f; - } - d3.interpolators = [ function(a, b) { - var t = typeof b; - return (t === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b); - } ]; - d3.interpolateArray = d3_interpolateArray; - function d3_interpolateArray(a, b) { - var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; - for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); - for (;i < na; ++i) c[i] = a[i]; - for (;i < nb; ++i) c[i] = b[i]; - return function(t) { - for (i = 0; i < n0; ++i) c[i] = x[i](t); - return c; - }; - } - var d3_ease_default = function() { - return d3_identity; - }; - var d3_ease = d3.map({ - linear: d3_ease_default, - poly: d3_ease_poly, - quad: function() { - return d3_ease_quad; - }, - cubic: function() { - return d3_ease_cubic; - }, - sin: function() { - return d3_ease_sin; - }, - exp: function() { - return d3_ease_exp; - }, - circle: function() { - return d3_ease_circle; - }, - elastic: d3_ease_elastic, - back: d3_ease_back, - bounce: function() { - return d3_ease_bounce; - } - }); - var d3_ease_mode = d3.map({ - "in": d3_identity, - out: d3_ease_reverse, - "in-out": d3_ease_reflect, - "out-in": function(f) { - return d3_ease_reflect(d3_ease_reverse(f)); - } - }); - d3.ease = function(name) { - var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in"; - t = d3_ease.get(t) || d3_ease_default; - m = d3_ease_mode.get(m) || d3_identity; - return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); - }; - function d3_ease_clamp(f) { - return function(t) { - return t <= 0 ? 0 : t >= 1 ? 1 : f(t); - }; - } - function d3_ease_reverse(f) { - return function(t) { - return 1 - f(1 - t); - }; - } - function d3_ease_reflect(f) { - return function(t) { - return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); - }; - } - function d3_ease_quad(t) { - return t * t; - } - function d3_ease_cubic(t) { - return t * t * t; - } - function d3_ease_cubicInOut(t) { - if (t <= 0) return 0; - if (t >= 1) return 1; - var t2 = t * t, t3 = t2 * t; - return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); - } - function d3_ease_poly(e) { - return function(t) { - return Math.pow(t, e); - }; - } - function d3_ease_sin(t) { - return 1 - Math.cos(t * halfπ); - } - function d3_ease_exp(t) { - return Math.pow(2, 10 * (t - 1)); - } - function d3_ease_circle(t) { - return 1 - Math.sqrt(1 - t * t); - } - function d3_ease_elastic(a, p) { - var s; - if (arguments.length < 2) p = .45; - if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4; - return function(t) { - return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p); - }; - } - function d3_ease_back(s) { - if (!s) s = 1.70158; - return function(t) { - return t * t * ((s + 1) * t - s); - }; - } - function d3_ease_bounce(t) { - return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; - } - d3.interpolateHcl = d3_interpolateHcl; - function d3_interpolateHcl(a, b) { - a = d3.hcl(a); - b = d3.hcl(b); - var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; - if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; - if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; - return function(t) { - return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; - }; - } - d3.interpolateHsl = d3_interpolateHsl; - function d3_interpolateHsl(a, b) { - a = d3.hsl(a); - b = d3.hsl(b); - var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; - if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; - if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; - return function(t) { - return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; - }; - } - d3.interpolateLab = d3_interpolateLab; - function d3_interpolateLab(a, b) { - a = d3.lab(a); - b = d3.lab(b); - var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; - return function(t) { - return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; - }; - } - d3.interpolateRound = d3_interpolateRound; - function d3_interpolateRound(a, b) { - b -= a; - return function(t) { - return Math.round(a + b * t); - }; - } - d3.transform = function(string) { - var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); - return (d3.transform = function(string) { - if (string != null) { - g.setAttribute("transform", string); - var t = g.transform.baseVal.consolidate(); - } - return new d3_transform(t ? t.matrix : d3_transformIdentity); - })(string); - }; - function d3_transform(m) { - var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; - if (r0[0] * r1[1] < r1[0] * r0[1]) { - r0[0] *= -1; - r0[1] *= -1; - kx *= -1; - kz *= -1; - } - this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; - this.translate = [ m.e, m.f ]; - this.scale = [ kx, ky ]; - this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; - } - d3_transform.prototype.toString = function() { - return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; - }; - function d3_transformDot(a, b) { - return a[0] * b[0] + a[1] * b[1]; - } - function d3_transformNormalize(a) { - var k = Math.sqrt(d3_transformDot(a, a)); - if (k) { - a[0] /= k; - a[1] /= k; - } - return k; - } - function d3_transformCombine(a, b, k) { - a[0] += k * b[0]; - a[1] += k * b[1]; - return a; - } - var d3_transformIdentity = { - a: 1, - b: 0, - c: 0, - d: 1, - e: 0, - f: 0 - }; - d3.interpolateTransform = d3_interpolateTransform; - function d3_interpolateTransform(a, b) { - var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale; - if (ta[0] != tb[0] || ta[1] != tb[1]) { - s.push("translate(", null, ",", null, ")"); - q.push({ - i: 1, - x: d3_interpolateNumber(ta[0], tb[0]) - }, { - i: 3, - x: d3_interpolateNumber(ta[1], tb[1]) - }); - } else if (tb[0] || tb[1]) { - s.push("translate(" + tb + ")"); - } else { - s.push(""); - } - if (ra != rb) { - if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; - q.push({ - i: s.push(s.pop() + "rotate(", null, ")") - 2, - x: d3_interpolateNumber(ra, rb) - }); - } else if (rb) { - s.push(s.pop() + "rotate(" + rb + ")"); - } - if (wa != wb) { - q.push({ - i: s.push(s.pop() + "skewX(", null, ")") - 2, - x: d3_interpolateNumber(wa, wb) - }); - } else if (wb) { - s.push(s.pop() + "skewX(" + wb + ")"); - } - if (ka[0] != kb[0] || ka[1] != kb[1]) { - n = s.push(s.pop() + "scale(", null, ",", null, ")"); - q.push({ - i: n - 4, - x: d3_interpolateNumber(ka[0], kb[0]) - }, { - i: n - 2, - x: d3_interpolateNumber(ka[1], kb[1]) - }); - } else if (kb[0] != 1 || kb[1] != 1) { - s.push(s.pop() + "scale(" + kb + ")"); - } - n = q.length; - return function(t) { - var i = -1, o; - while (++i < n) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - } - function d3_uninterpolateNumber(a, b) { - b = (b -= a = +a) || 1 / b; - return function(x) { - return (x - a) / b; - }; - } - function d3_uninterpolateClamp(a, b) { - b = (b -= a = +a) || 1 / b; - return function(x) { - return Math.max(0, Math.min(1, (x - a) / b)); - }; - } - d3.layout = {}; - d3.layout.bundle = function() { - return function(links) { - var paths = [], i = -1, n = links.length; - while (++i < n) paths.push(d3_layout_bundlePath(links[i])); - return paths; - }; - }; - function d3_layout_bundlePath(link) { - var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; - while (start !== lca) { - start = start.parent; - points.push(start); - } - var k = points.length; - while (end !== lca) { - points.splice(k, 0, end); - end = end.parent; - } - return points; - } - function d3_layout_bundleAncestors(node) { - var ancestors = [], parent = node.parent; - while (parent != null) { - ancestors.push(node); - node = parent; - parent = parent.parent; - } - ancestors.push(node); - return ancestors; - } - function d3_layout_bundleLeastCommonAncestor(a, b) { - if (a === b) return a; - var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; - while (aNode === bNode) { - sharedNode = aNode; - aNode = aNodes.pop(); - bNode = bNodes.pop(); - } - return sharedNode; - } - d3.layout.chord = function() { - var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; - function relayout() { - var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; - chords = []; - groups = []; - k = 0, i = -1; - while (++i < n) { - x = 0, j = -1; - while (++j < n) { - x += matrix[i][j]; - } - groupSums.push(x); - subgroupIndex.push(d3.range(n)); - k += x; - } - if (sortGroups) { - groupIndex.sort(function(a, b) { - return sortGroups(groupSums[a], groupSums[b]); - }); - } - if (sortSubgroups) { - subgroupIndex.forEach(function(d, i) { - d.sort(function(a, b) { - return sortSubgroups(matrix[i][a], matrix[i][b]); - }); - }); - } - k = (τ - padding * n) / k; - x = 0, i = -1; - while (++i < n) { - x0 = x, j = -1; - while (++j < n) { - var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; - subgroups[di + "-" + dj] = { - index: di, - subindex: dj, - startAngle: a0, - endAngle: a1, - value: v - }; - } - groups[di] = { - index: di, - startAngle: x0, - endAngle: x, - value: (x - x0) / k - }; - x += padding; - } - i = -1; - while (++i < n) { - j = i - 1; - while (++j < n) { - var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; - if (source.value || target.value) { - chords.push(source.value < target.value ? { - source: target, - target: source - } : { - source: source, - target: target - }); - } - } - } - if (sortChords) resort(); - } - function resort() { - chords.sort(function(a, b) { - return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); - }); - } - chord.matrix = function(x) { - if (!arguments.length) return matrix; - n = (matrix = x) && matrix.length; - chords = groups = null; - return chord; - }; - chord.padding = function(x) { - if (!arguments.length) return padding; - padding = x; - chords = groups = null; - return chord; - }; - chord.sortGroups = function(x) { - if (!arguments.length) return sortGroups; - sortGroups = x; - chords = groups = null; - return chord; - }; - chord.sortSubgroups = function(x) { - if (!arguments.length) return sortSubgroups; - sortSubgroups = x; - chords = null; - return chord; - }; - chord.sortChords = function(x) { - if (!arguments.length) return sortChords; - sortChords = x; - if (chords) resort(); - return chord; - }; - chord.chords = function() { - if (!chords) relayout(); - return chords; - }; - chord.groups = function() { - if (!groups) relayout(); - return groups; - }; - return chord; - }; - d3.layout.force = function() { - var force = {}, event = d3.dispatch("start", "tick", "end"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; - function repulse(node) { - return function(quad, x1, _, x2) { - if (quad.point !== node) { - var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; - if (dw * dw / theta2 < dn) { - if (dn < chargeDistance2) { - var k = quad.charge / dn; - node.px -= dx * k; - node.py -= dy * k; - } - return true; - } - if (quad.point && dn && dn < chargeDistance2) { - var k = quad.pointCharge / dn; - node.px -= dx * k; - node.py -= dy * k; - } - } - return !quad.charge; - }; - } - force.tick = function() { - if ((alpha *= .99) < .005) { - event.end({ - type: "end", - alpha: alpha = 0 - }); - return true; - } - var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; - for (i = 0; i < m; ++i) { - o = links[i]; - s = o.source; - t = o.target; - x = t.x - s.x; - y = t.y - s.y; - if (l = x * x + y * y) { - l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; - x *= l; - y *= l; - t.x -= x * (k = s.weight / (t.weight + s.weight)); - t.y -= y * k; - s.x += x * (k = 1 - k); - s.y += y * k; - } - } - if (k = alpha * gravity) { - x = size[0] / 2; - y = size[1] / 2; - i = -1; - if (k) while (++i < n) { - o = nodes[i]; - o.x += (x - o.x) * k; - o.y += (y - o.y) * k; - } - } - if (charge) { - d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); - i = -1; - while (++i < n) { - if (!(o = nodes[i]).fixed) { - q.visit(repulse(o)); - } - } - } - i = -1; - while (++i < n) { - o = nodes[i]; - if (o.fixed) { - o.x = o.px; - o.y = o.py; - } else { - o.x -= (o.px - (o.px = o.x)) * friction; - o.y -= (o.py - (o.py = o.y)) * friction; - } - } - event.tick({ - type: "tick", - alpha: alpha - }); - }; - force.nodes = function(x) { - if (!arguments.length) return nodes; - nodes = x; - return force; - }; - force.links = function(x) { - if (!arguments.length) return links; - links = x; - return force; - }; - force.size = function(x) { - if (!arguments.length) return size; - size = x; - return force; - }; - force.linkDistance = function(x) { - if (!arguments.length) return linkDistance; - linkDistance = typeof x === "function" ? x : +x; - return force; - }; - force.distance = force.linkDistance; - force.linkStrength = function(x) { - if (!arguments.length) return linkStrength; - linkStrength = typeof x === "function" ? x : +x; - return force; - }; - force.friction = function(x) { - if (!arguments.length) return friction; - friction = +x; - return force; - }; - force.charge = function(x) { - if (!arguments.length) return charge; - charge = typeof x === "function" ? x : +x; - return force; - }; - force.chargeDistance = function(x) { - if (!arguments.length) return Math.sqrt(chargeDistance2); - chargeDistance2 = x * x; - return force; - }; - force.gravity = function(x) { - if (!arguments.length) return gravity; - gravity = +x; - return force; - }; - force.theta = function(x) { - if (!arguments.length) return Math.sqrt(theta2); - theta2 = x * x; - return force; - }; - force.alpha = function(x) { - if (!arguments.length) return alpha; - x = +x; - if (alpha) { - if (x > 0) alpha = x; else alpha = 0; - } else if (x > 0) { - event.start({ - type: "start", - alpha: alpha = x - }); - d3.timer(force.tick); - } - return force; - }; - force.start = function() { - var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; - for (i = 0; i < n; ++i) { - (o = nodes[i]).index = i; - o.weight = 0; - } - for (i = 0; i < m; ++i) { - o = links[i]; - if (typeof o.source == "number") o.source = nodes[o.source]; - if (typeof o.target == "number") o.target = nodes[o.target]; - ++o.source.weight; - ++o.target.weight; - } - for (i = 0; i < n; ++i) { - o = nodes[i]; - if (isNaN(o.x)) o.x = position("x", w); - if (isNaN(o.y)) o.y = position("y", h); - if (isNaN(o.px)) o.px = o.x; - if (isNaN(o.py)) o.py = o.y; - } - distances = []; - if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; - strengths = []; - if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; - charges = []; - if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; - function position(dimension, size) { - if (!neighbors) { - neighbors = new Array(n); - for (j = 0; j < n; ++j) { - neighbors[j] = []; - } - for (j = 0; j < m; ++j) { - var o = links[j]; - neighbors[o.source.index].push(o.target); - neighbors[o.target.index].push(o.source); - } - } - var candidates = neighbors[i], j = -1, m = candidates.length, x; - while (++j < m) if (!isNaN(x = candidates[j][dimension])) return x; - return Math.random() * size; - } - return force.resume(); - }; - force.resume = function() { - return force.alpha(.1); - }; - force.stop = function() { - return force.alpha(0); - }; - force.drag = function() { - if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); - if (!arguments.length) return drag; - this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); - }; - function dragmove(d) { - d.px = d3.event.x, d.py = d3.event.y; - force.resume(); - } - return d3.rebind(force, event, "on"); - }; - function d3_layout_forceDragstart(d) { - d.fixed |= 2; - } - function d3_layout_forceDragend(d) { - d.fixed &= ~6; - } - function d3_layout_forceMouseover(d) { - d.fixed |= 4; - d.px = d.x, d.py = d.y; - } - function d3_layout_forceMouseout(d) { - d.fixed &= ~4; - } - function d3_layout_forceAccumulate(quad, alpha, charges) { - var cx = 0, cy = 0; - quad.charge = 0; - if (!quad.leaf) { - var nodes = quad.nodes, n = nodes.length, i = -1, c; - while (++i < n) { - c = nodes[i]; - if (c == null) continue; - d3_layout_forceAccumulate(c, alpha, charges); - quad.charge += c.charge; - cx += c.charge * c.cx; - cy += c.charge * c.cy; - } - } - if (quad.point) { - if (!quad.leaf) { - quad.point.x += Math.random() - .5; - quad.point.y += Math.random() - .5; - } - var k = alpha * charges[quad.point.index]; - quad.charge += quad.pointCharge = k; - cx += k * quad.point.x; - cy += k * quad.point.y; - } - quad.cx = cx / quad.charge; - quad.cy = cy / quad.charge; - } - var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; - d3.layout.hierarchy = function() { - var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; - function hierarchy(root) { - var stack = [ root ], nodes = [], node; - root.depth = 0; - while ((node = stack.pop()) != null) { - nodes.push(node); - if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) { - var n, childs, child; - while (--n >= 0) { - stack.push(child = childs[n]); - child.parent = node; - child.depth = node.depth + 1; - } - if (value) node.value = 0; - node.children = childs; - } else { - if (value) node.value = +value.call(hierarchy, node, node.depth) || 0; - delete node.children; - } - } - d3_layout_hierarchyVisitAfter(root, function(node) { - var childs, parent; - if (sort && (childs = node.children)) childs.sort(sort); - if (value && (parent = node.parent)) parent.value += node.value; - }); - return nodes; - } - hierarchy.sort = function(x) { - if (!arguments.length) return sort; - sort = x; - return hierarchy; - }; - hierarchy.children = function(x) { - if (!arguments.length) return children; - children = x; - return hierarchy; - }; - hierarchy.value = function(x) { - if (!arguments.length) return value; - value = x; - return hierarchy; - }; - hierarchy.revalue = function(root) { - if (value) { - d3_layout_hierarchyVisitBefore(root, function(node) { - if (node.children) node.value = 0; - }); - d3_layout_hierarchyVisitAfter(root, function(node) { - var parent; - if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0; - if (parent = node.parent) parent.value += node.value; - }); - } - return root; - }; - return hierarchy; - }; - function d3_layout_hierarchyRebind(object, hierarchy) { - d3.rebind(object, hierarchy, "sort", "children", "value"); - object.nodes = object; - object.links = d3_layout_hierarchyLinks; - return object; - } - function d3_layout_hierarchyVisitBefore(node, callback) { - var nodes = [ node ]; - while ((node = nodes.pop()) != null) { - callback(node); - if ((children = node.children) && (n = children.length)) { - var n, children; - while (--n >= 0) nodes.push(children[n]); - } - } - } - function d3_layout_hierarchyVisitAfter(node, callback) { - var nodes = [ node ], nodes2 = []; - while ((node = nodes.pop()) != null) { - nodes2.push(node); - if ((children = node.children) && (n = children.length)) { - var i = -1, n, children; - while (++i < n) nodes.push(children[i]); - } - } - while ((node = nodes2.pop()) != null) { - callback(node); - } - } - function d3_layout_hierarchyChildren(d) { - return d.children; - } - function d3_layout_hierarchyValue(d) { - return d.value; - } - function d3_layout_hierarchySort(a, b) { - return b.value - a.value; - } - function d3_layout_hierarchyLinks(nodes) { - return d3.merge(nodes.map(function(parent) { - return (parent.children || []).map(function(child) { - return { - source: parent, - target: child - }; - }); - })); - } - d3.layout.partition = function() { - var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; - function position(node, x, dx, dy) { - var children = node.children; - node.x = x; - node.y = node.depth * dy; - node.dx = dx; - node.dy = dy; - if (children && (n = children.length)) { - var i = -1, n, c, d; - dx = node.value ? dx / node.value : 0; - while (++i < n) { - position(c = children[i], x, d = c.value * dx, dy); - x += d; - } - } - } - function depth(node) { - var children = node.children, d = 0; - if (children && (n = children.length)) { - var i = -1, n; - while (++i < n) d = Math.max(d, depth(children[i])); - } - return 1 + d; - } - function partition(d, i) { - var nodes = hierarchy.call(this, d, i); - position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); - return nodes; - } - partition.size = function(x) { - if (!arguments.length) return size; - size = x; - return partition; - }; - return d3_layout_hierarchyRebind(partition, hierarchy); - }; - d3.layout.pie = function() { - var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0; - function pie(data) { - var n = data.length, values = data.map(function(d, i) { - return +value.call(pie, d, i); - }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), k = (da - n * pa) / d3.sum(values), index = d3.range(n), arcs = [], v; - if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { - return values[j] - values[i]; - } : function(i, j) { - return sort(data[i], data[j]); - }); - index.forEach(function(i) { - arcs[i] = { - data: data[i], - value: v = values[i], - startAngle: a, - endAngle: a += v * k + pa, - padAngle: p - }; - }); - return arcs; - } - pie.value = function(_) { - if (!arguments.length) return value; - value = _; - return pie; - }; - pie.sort = function(_) { - if (!arguments.length) return sort; - sort = _; - return pie; - }; - pie.startAngle = function(_) { - if (!arguments.length) return startAngle; - startAngle = _; - return pie; - }; - pie.endAngle = function(_) { - if (!arguments.length) return endAngle; - endAngle = _; - return pie; - }; - pie.padAngle = function(_) { - if (!arguments.length) return padAngle; - padAngle = _; - return pie; - }; - return pie; - }; - var d3_layout_pieSortByValue = {}; - d3.layout.stack = function() { - var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; - function stack(data, index) { - if (!(n = data.length)) return data; - var series = data.map(function(d, i) { - return values.call(stack, d, i); - }); - var points = series.map(function(d) { - return d.map(function(v, i) { - return [ x.call(stack, v, i), y.call(stack, v, i) ]; - }); - }); - var orders = order.call(stack, points, index); - series = d3.permute(series, orders); - points = d3.permute(points, orders); - var offsets = offset.call(stack, points, index); - var m = series[0].length, n, i, j, o; - for (j = 0; j < m; ++j) { - out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); - for (i = 1; i < n; ++i) { - out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); - } - } - return data; - } - stack.values = function(x) { - if (!arguments.length) return values; - values = x; - return stack; - }; - stack.order = function(x) { - if (!arguments.length) return order; - order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; - return stack; - }; - stack.offset = function(x) { - if (!arguments.length) return offset; - offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; - return stack; - }; - stack.x = function(z) { - if (!arguments.length) return x; - x = z; - return stack; - }; - stack.y = function(z) { - if (!arguments.length) return y; - y = z; - return stack; - }; - stack.out = function(z) { - if (!arguments.length) return out; - out = z; - return stack; - }; - return stack; - }; - function d3_layout_stackX(d) { - return d.x; - } - function d3_layout_stackY(d) { - return d.y; - } - function d3_layout_stackOut(d, y0, y) { - d.y0 = y0; - d.y = y; - } - var d3_layout_stackOrders = d3.map({ - "inside-out": function(data) { - var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { - return max[a] - max[b]; - }), top = 0, bottom = 0, tops = [], bottoms = []; - for (i = 0; i < n; ++i) { - j = index[i]; - if (top < bottom) { - top += sums[j]; - tops.push(j); - } else { - bottom += sums[j]; - bottoms.push(j); - } - } - return bottoms.reverse().concat(tops); - }, - reverse: function(data) { - return d3.range(data.length).reverse(); - }, - "default": d3_layout_stackOrderDefault - }); - var d3_layout_stackOffsets = d3.map({ - silhouette: function(data) { - var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; - for (j = 0; j < m; ++j) { - for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; - if (o > max) max = o; - sums.push(o); - } - for (j = 0; j < m; ++j) { - y0[j] = (max - sums[j]) / 2; - } - return y0; - }, - wiggle: function(data) { - var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; - y0[0] = o = o0 = 0; - for (j = 1; j < m; ++j) { - for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; - for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { - for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { - s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; - } - s2 += s3 * data[i][j][1]; - } - y0[j] = o -= s1 ? s2 / s1 * dx : 0; - if (o < o0) o0 = o; - } - for (j = 0; j < m; ++j) y0[j] -= o0; - return y0; - }, - expand: function(data) { - var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; - for (j = 0; j < m; ++j) { - for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; - if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; - } - for (j = 0; j < m; ++j) y0[j] = 0; - return y0; - }, - zero: d3_layout_stackOffsetZero - }); - function d3_layout_stackOrderDefault(data) { - return d3.range(data.length); - } - function d3_layout_stackOffsetZero(data) { - var j = -1, m = data[0].length, y0 = []; - while (++j < m) y0[j] = 0; - return y0; - } - function d3_layout_stackMaxIndex(array) { - var i = 1, j = 0, v = array[0][1], k, n = array.length; - for (;i < n; ++i) { - if ((k = array[i][1]) > v) { - j = i; - v = k; - } - } - return j; - } - function d3_layout_stackReduceSum(d) { - return d.reduce(d3_layout_stackSum, 0); - } - function d3_layout_stackSum(p, d) { - return p + d[1]; - } - d3.layout.histogram = function() { - var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; - function histogram(data, i) { - var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; - while (++i < m) { - bin = bins[i] = []; - bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); - bin.y = 0; - } - if (m > 0) { - i = -1; - while (++i < n) { - x = values[i]; - if (x >= range[0] && x <= range[1]) { - bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; - bin.y += k; - bin.push(data[i]); - } - } - } - return bins; - } - histogram.value = function(x) { - if (!arguments.length) return valuer; - valuer = x; - return histogram; - }; - histogram.range = function(x) { - if (!arguments.length) return ranger; - ranger = d3_functor(x); - return histogram; - }; - histogram.bins = function(x) { - if (!arguments.length) return binner; - binner = typeof x === "number" ? function(range) { - return d3_layout_histogramBinFixed(range, x); - } : d3_functor(x); - return histogram; - }; - histogram.frequency = function(x) { - if (!arguments.length) return frequency; - frequency = !!x; - return histogram; - }; - return histogram; - }; - function d3_layout_histogramBinSturges(range, values) { - return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); - } - function d3_layout_histogramBinFixed(range, n) { - var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; - while (++x <= n) f[x] = m * x + b; - return f; - } - function d3_layout_histogramRange(values) { - return [ d3.min(values), d3.max(values) ]; - } - d3.layout.pack = function() { - var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; - function pack(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { - return radius; - }; - root.x = root.y = 0; - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r = +r(d.value); - }); - d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); - if (padding) { - var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r += dr; - }); - d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r -= dr; - }); - } - d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); - return nodes; - } - pack.size = function(_) { - if (!arguments.length) return size; - size = _; - return pack; - }; - pack.radius = function(_) { - if (!arguments.length) return radius; - radius = _ == null || typeof _ === "function" ? _ : +_; - return pack; - }; - pack.padding = function(_) { - if (!arguments.length) return padding; - padding = +_; - return pack; - }; - return d3_layout_hierarchyRebind(pack, hierarchy); - }; - function d3_layout_packSort(a, b) { - return a.value - b.value; - } - function d3_layout_packInsert(a, b) { - var c = a._pack_next; - a._pack_next = b; - b._pack_prev = a; - b._pack_next = c; - c._pack_prev = b; - } - function d3_layout_packSplice(a, b) { - a._pack_next = b; - b._pack_prev = a; - } - function d3_layout_packIntersects(a, b) { - var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; - return .999 * dr * dr > dx * dx + dy * dy; - } - function d3_layout_packSiblings(node) { - if (!(nodes = node.children) || !(n = nodes.length)) return; - var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; - function bound(node) { - xMin = Math.min(node.x - node.r, xMin); - xMax = Math.max(node.x + node.r, xMax); - yMin = Math.min(node.y - node.r, yMin); - yMax = Math.max(node.y + node.r, yMax); - } - nodes.forEach(d3_layout_packLink); - a = nodes[0]; - a.x = -a.r; - a.y = 0; - bound(a); - if (n > 1) { - b = nodes[1]; - b.x = b.r; - b.y = 0; - bound(b); - if (n > 2) { - c = nodes[2]; - d3_layout_packPlace(a, b, c); - bound(c); - d3_layout_packInsert(a, c); - a._pack_prev = c; - d3_layout_packInsert(c, b); - b = a._pack_next; - for (i = 3; i < n; i++) { - d3_layout_packPlace(a, b, c = nodes[i]); - var isect = 0, s1 = 1, s2 = 1; - for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { - if (d3_layout_packIntersects(j, c)) { - isect = 1; - break; - } - } - if (isect == 1) { - for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { - if (d3_layout_packIntersects(k, c)) { - break; - } - } - } - if (isect) { - if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); - i--; - } else { - d3_layout_packInsert(a, c); - b = c; - bound(c); - } - } - } - } - var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; - for (i = 0; i < n; i++) { - c = nodes[i]; - c.x -= cx; - c.y -= cy; - cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); - } - node.r = cr; - nodes.forEach(d3_layout_packUnlink); - } - function d3_layout_packLink(node) { - node._pack_next = node._pack_prev = node; - } - function d3_layout_packUnlink(node) { - delete node._pack_next; - delete node._pack_prev; - } - function d3_layout_packTransform(node, x, y, k) { - var children = node.children; - node.x = x += k * node.x; - node.y = y += k * node.y; - node.r *= k; - if (children) { - var i = -1, n = children.length; - while (++i < n) d3_layout_packTransform(children[i], x, y, k); - } - } - function d3_layout_packPlace(a, b, c) { - var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; - if (db && (dx || dy)) { - var da = b.r + c.r, dc = dx * dx + dy * dy; - da *= da; - db *= db; - var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); - c.x = a.x + x * dx + y * dy; - c.y = a.y + x * dy - y * dx; - } else { - c.x = a.x + db; - c.y = a.y; - } - } - d3.layout.tree = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null; - function tree(d, i) { - var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0); - d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z; - d3_layout_hierarchyVisitBefore(root1, secondWalk); - if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else { - var left = root0, right = root0, bottom = root0; - d3_layout_hierarchyVisitBefore(root0, function(node) { - if (node.x < left.x) left = node; - if (node.x > right.x) right = node; - if (node.depth > bottom.depth) bottom = node; - }); - var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1); - d3_layout_hierarchyVisitBefore(root0, function(node) { - node.x = (node.x + tx) * kx; - node.y = node.depth * ky; - }); - } - return nodes; - } - function wrapTree(root0) { - var root1 = { - A: null, - children: [ root0 ] - }, queue = [ root1 ], node1; - while ((node1 = queue.pop()) != null) { - for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) { - queue.push((children[i] = child = { - _: children[i], - parent: node1, - children: (child = children[i].children) && child.slice() || [], - A: null, - a: null, - z: 0, - m: 0, - c: 0, - s: 0, - t: null, - i: i - }).a = child); - } - } - return root1.children[0]; - } - function firstWalk(v) { - var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null; - if (children.length) { - d3_layout_treeShift(v); - var midpoint = (children[0].z + children[children.length - 1].z) / 2; - if (w) { - v.z = w.z + separation(v._, w._); - v.m = v.z - midpoint; - } else { - v.z = midpoint; - } - } else if (w) { - v.z = w.z + separation(v._, w._); - } - v.parent.A = apportion(v, w, v.parent.A || siblings[0]); - } - function secondWalk(v) { - v._.x = v.z + v.parent.m; - v.m += v.parent.m; - } - function apportion(v, w, ancestor) { - if (w) { - var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift; - while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { - vom = d3_layout_treeLeft(vom); - vop = d3_layout_treeRight(vop); - vop.a = v; - shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); - if (shift > 0) { - d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift); - sip += shift; - sop += shift; - } - sim += vim.m; - sip += vip.m; - som += vom.m; - sop += vop.m; - } - if (vim && !d3_layout_treeRight(vop)) { - vop.t = vim; - vop.m += sim - sop; - } - if (vip && !d3_layout_treeLeft(vom)) { - vom.t = vip; - vom.m += sip - som; - ancestor = v; - } - } - return ancestor; - } - function sizeNode(node) { - node.x *= size[0]; - node.y = node.depth * size[1]; - } - tree.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return tree; - }; - tree.size = function(x) { - if (!arguments.length) return nodeSize ? null : size; - nodeSize = (size = x) == null ? sizeNode : null; - return tree; - }; - tree.nodeSize = function(x) { - if (!arguments.length) return nodeSize ? size : null; - nodeSize = (size = x) == null ? null : sizeNode; - return tree; - }; - return d3_layout_hierarchyRebind(tree, hierarchy); - }; - function d3_layout_treeSeparation(a, b) { - return a.parent == b.parent ? 1 : 2; - } - function d3_layout_treeLeft(v) { - var children = v.children; - return children.length ? children[0] : v.t; - } - function d3_layout_treeRight(v) { - var children = v.children, n; - return (n = children.length) ? children[n - 1] : v.t; - } - function d3_layout_treeMove(wm, wp, shift) { - var change = shift / (wp.i - wm.i); - wp.c -= change; - wp.s += shift; - wm.c += change; - wp.z += shift; - wp.m += shift; - } - function d3_layout_treeShift(v) { - var shift = 0, change = 0, children = v.children, i = children.length, w; - while (--i >= 0) { - w = children[i]; - w.z += shift; - w.m += shift; - shift += w.s + (change += w.c); - } - } - function d3_layout_treeAncestor(vim, v, ancestor) { - return vim.a.parent === v.parent ? vim.a : ancestor; - } - d3.layout.cluster = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; - function cluster(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; - d3_layout_hierarchyVisitAfter(root, function(node) { - var children = node.children; - if (children && children.length) { - node.x = d3_layout_clusterX(children); - node.y = d3_layout_clusterY(children); - } else { - node.x = previousNode ? x += separation(node, previousNode) : 0; - node.y = 0; - previousNode = node; - } - }); - var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; - d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) { - node.x = (node.x - root.x) * size[0]; - node.y = (root.y - node.y) * size[1]; - } : function(node) { - node.x = (node.x - x0) / (x1 - x0) * size[0]; - node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; - }); - return nodes; - } - cluster.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return cluster; - }; - cluster.size = function(x) { - if (!arguments.length) return nodeSize ? null : size; - nodeSize = (size = x) == null; - return cluster; - }; - cluster.nodeSize = function(x) { - if (!arguments.length) return nodeSize ? size : null; - nodeSize = (size = x) != null; - return cluster; - }; - return d3_layout_hierarchyRebind(cluster, hierarchy); - }; - function d3_layout_clusterY(children) { - return 1 + d3.max(children, function(child) { - return child.y; - }); - } - function d3_layout_clusterX(children) { - return children.reduce(function(x, child) { - return x + child.x; - }, 0) / children.length; - } - function d3_layout_clusterLeft(node) { - var children = node.children; - return children && children.length ? d3_layout_clusterLeft(children[0]) : node; - } - function d3_layout_clusterRight(node) { - var children = node.children, n; - return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; - } - d3.layout.treemap = function() { - var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); - function scale(children, k) { - var i = -1, n = children.length, child, area; - while (++i < n) { - area = (child = children[i]).value * (k < 0 ? 0 : k); - child.area = isNaN(area) || area <= 0 ? 0 : area; - } - } - function squarify(node) { - var children = node.children; - if (children && children.length) { - var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; - scale(remaining, rect.dx * rect.dy / node.value); - row.area = 0; - while ((n = remaining.length) > 0) { - row.push(child = remaining[n - 1]); - row.area += child.area; - if (mode !== "squarify" || (score = worst(row, u)) <= best) { - remaining.pop(); - best = score; - } else { - row.area -= row.pop().area; - position(row, u, rect, false); - u = Math.min(rect.dx, rect.dy); - row.length = row.area = 0; - best = Infinity; - } - } - if (row.length) { - position(row, u, rect, true); - row.length = row.area = 0; - } - children.forEach(squarify); - } - } - function stickify(node) { - var children = node.children; - if (children && children.length) { - var rect = pad(node), remaining = children.slice(), child, row = []; - scale(remaining, rect.dx * rect.dy / node.value); - row.area = 0; - while (child = remaining.pop()) { - row.push(child); - row.area += child.area; - if (child.z != null) { - position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); - row.length = row.area = 0; - } - } - children.forEach(stickify); - } - } - function worst(row, u) { - var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; - while (++i < n) { - if (!(r = row[i].area)) continue; - if (r < rmin) rmin = r; - if (r > rmax) rmax = r; - } - s *= s; - u *= u; - return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; - } - function position(row, u, rect, flush) { - var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; - if (u == rect.dx) { - if (flush || v > rect.dy) v = rect.dy; - while (++i < n) { - o = row[i]; - o.x = x; - o.y = y; - o.dy = v; - x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); - } - o.z = true; - o.dx += rect.x + rect.dx - x; - rect.y += v; - rect.dy -= v; - } else { - if (flush || v > rect.dx) v = rect.dx; - while (++i < n) { - o = row[i]; - o.x = x; - o.y = y; - o.dx = v; - y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); - } - o.z = false; - o.dy += rect.y + rect.dy - y; - rect.x += v; - rect.dx -= v; - } - } - function treemap(d) { - var nodes = stickies || hierarchy(d), root = nodes[0]; - root.x = 0; - root.y = 0; - root.dx = size[0]; - root.dy = size[1]; - if (stickies) hierarchy.revalue(root); - scale([ root ], root.dx * root.dy / root.value); - (stickies ? stickify : squarify)(root); - if (sticky) stickies = nodes; - return nodes; - } - treemap.size = function(x) { - if (!arguments.length) return size; - size = x; - return treemap; - }; - treemap.padding = function(x) { - if (!arguments.length) return padding; - function padFunction(node) { - var p = x.call(treemap, node, node.depth); - return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); - } - function padConstant(node) { - return d3_layout_treemapPad(node, x); - } - var type; - pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], - padConstant) : padConstant; - return treemap; - }; - treemap.round = function(x) { - if (!arguments.length) return round != Number; - round = x ? Math.round : Number; - return treemap; - }; - treemap.sticky = function(x) { - if (!arguments.length) return sticky; - sticky = x; - stickies = null; - return treemap; - }; - treemap.ratio = function(x) { - if (!arguments.length) return ratio; - ratio = x; - return treemap; - }; - treemap.mode = function(x) { - if (!arguments.length) return mode; - mode = x + ""; - return treemap; - }; - return d3_layout_hierarchyRebind(treemap, hierarchy); - }; - function d3_layout_treemapPadNull(node) { - return { - x: node.x, - y: node.y, - dx: node.dx, - dy: node.dy - }; - } - function d3_layout_treemapPad(node, padding) { - var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; - if (dx < 0) { - x += dx / 2; - dx = 0; - } - if (dy < 0) { - y += dy / 2; - dy = 0; - } - return { - x: x, - y: y, - dx: dx, - dy: dy - }; - } - d3.random = { - normal: function(µ, σ) { - var n = arguments.length; - if (n < 2) σ = 1; - if (n < 1) µ = 0; - return function() { - var x, y, r; - do { - x = Math.random() * 2 - 1; - y = Math.random() * 2 - 1; - r = x * x + y * y; - } while (!r || r > 1); - return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); - }; - }, - logNormal: function() { - var random = d3.random.normal.apply(d3, arguments); - return function() { - return Math.exp(random()); - }; - }, - bates: function(m) { - var random = d3.random.irwinHall(m); - return function() { - return random() / m; - }; - }, - irwinHall: function(m) { - return function() { - for (var s = 0, j = 0; j < m; j++) s += Math.random(); - return s; - }; - } - }; - d3.scale = {}; - function d3_scaleExtent(domain) { - var start = domain[0], stop = domain[domain.length - 1]; - return start < stop ? [ start, stop ] : [ stop, start ]; - } - function d3_scaleRange(scale) { - return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); - } - function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { - var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); - return function(x) { - return i(u(x)); - }; - } - function d3_scale_nice(domain, nice) { - var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; - if (x1 < x0) { - dx = i0, i0 = i1, i1 = dx; - dx = x0, x0 = x1, x1 = dx; - } - domain[i0] = nice.floor(x0); - domain[i1] = nice.ceil(x1); - return domain; - } - function d3_scale_niceStep(step) { - return step ? { - floor: function(x) { - return Math.floor(x / step) * step; - }, - ceil: function(x) { - return Math.ceil(x / step) * step; - } - } : d3_scale_niceIdentity; - } - var d3_scale_niceIdentity = { - floor: d3_identity, - ceil: d3_identity - }; - function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { - var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; - if (domain[k] < domain[0]) { - domain = domain.slice().reverse(); - range = range.slice().reverse(); - } - while (++j <= k) { - u.push(uninterpolate(domain[j - 1], domain[j])); - i.push(interpolate(range[j - 1], range[j])); - } - return function(x) { - var j = d3.bisect(domain, x, 1, k) - 1; - return i[j](u[j](x)); - }; - } - d3.scale.linear = function() { - return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); - }; - function d3_scale_linear(domain, range, interpolate, clamp) { - var output, input; - function rescale() { - var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; - output = linear(domain, range, uninterpolate, interpolate); - input = linear(range, domain, uninterpolate, d3_interpolate); - return scale; - } - function scale(x) { - return output(x); - } - scale.invert = function(y) { - return input(y); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(Number); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.rangeRound = function(x) { - return scale.range(x).interpolate(d3_interpolateRound); - }; - scale.clamp = function(x) { - if (!arguments.length) return clamp; - clamp = x; - return rescale(); - }; - scale.interpolate = function(x) { - if (!arguments.length) return interpolate; - interpolate = x; - return rescale(); - }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - scale.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - scale.nice = function(m) { - d3_scale_linearNice(domain, m); - return rescale(); - }; - scale.copy = function() { - return d3_scale_linear(domain, range, interpolate, clamp); - }; - return rescale(); - } - function d3_scale_linearRebind(scale, linear) { - return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); - } - function d3_scale_linearNice(domain, m) { - return d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); - } - function d3_scale_linearTickRange(domain, m) { - if (m == null) m = 10; - var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; - if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; - extent[0] = Math.ceil(extent[0] / step) * step; - extent[1] = Math.floor(extent[1] / step) * step + step * .5; - extent[2] = step; - return extent; - } - function d3_scale_linearTicks(domain, m) { - return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); - } - function d3_scale_linearTickFormat(domain, m, format) { - var range = d3_scale_linearTickRange(domain, m); - if (format) { - var match = d3_format_re.exec(format); - match.shift(); - if (match[8] === "s") { - var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1]))); - if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2])); - match[8] = "f"; - format = d3.format(match.join("")); - return function(d) { - return format(prefix.scale(d)) + prefix.symbol; - }; - } - if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range); - format = match.join(""); - } else { - format = ",." + d3_scale_linearPrecision(range[2]) + "f"; - } - return d3.format(format); - } - var d3_scale_linearFormatSignificant = { - s: 1, - g: 1, - p: 1, - r: 1, - e: 1 - }; - function d3_scale_linearPrecision(value) { - return -Math.floor(Math.log(value) / Math.LN10 + .01); - } - function d3_scale_linearFormatPrecision(type, range) { - var p = d3_scale_linearPrecision(range[2]); - return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; - } - d3.scale.log = function() { - return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); - }; - function d3_scale_log(linear, base, positive, domain) { - function log(x) { - return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); - } - function pow(x) { - return positive ? Math.pow(base, x) : -Math.pow(base, -x); - } - function scale(x) { - return linear(log(x)); - } - scale.invert = function(x) { - return pow(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - positive = x[0] >= 0; - linear.domain((domain = x.map(Number)).map(log)); - return scale; - }; - scale.base = function(_) { - if (!arguments.length) return base; - base = +_; - linear.domain(domain.map(log)); - return scale; - }; - scale.nice = function() { - var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); - linear.domain(niced); - domain = niced.map(pow); - return scale; - }; - scale.ticks = function() { - var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; - if (isFinite(j - i)) { - if (positive) { - for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); - ticks.push(pow(i)); - } else { - ticks.push(pow(i)); - for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); - } - for (i = 0; ticks[i] < u; i++) {} - for (j = ticks.length; ticks[j - 1] > v; j--) {} - ticks = ticks.slice(i, j); - } - return ticks; - }; - scale.tickFormat = function(n, format) { - if (!arguments.length) return d3_scale_logFormat; - if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); - var k = Math.max(.1, n / scale.ticks().length), f = positive ? (e = 1e-12, Math.ceil) : (e = -1e-12, - Math.floor), e; - return function(d) { - return d / pow(f(log(d) + e)) <= k ? format(d) : ""; - }; - }; - scale.copy = function() { - return d3_scale_log(linear.copy(), base, positive, domain); - }; - return d3_scale_linearRebind(scale, linear); - } - var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { - floor: function(x) { - return -Math.ceil(-x); - }, - ceil: function(x) { - return -Math.floor(-x); - } - }; - d3.scale.pow = function() { - return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); - }; - function d3_scale_pow(linear, exponent, domain) { - var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); - function scale(x) { - return linear(powp(x)); - } - scale.invert = function(x) { - return powb(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - linear.domain((domain = x.map(Number)).map(powp)); - return scale; - }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - scale.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - scale.nice = function(m) { - return scale.domain(d3_scale_linearNice(domain, m)); - }; - scale.exponent = function(x) { - if (!arguments.length) return exponent; - powp = d3_scale_powPow(exponent = x); - powb = d3_scale_powPow(1 / exponent); - linear.domain(domain.map(powp)); - return scale; - }; - scale.copy = function() { - return d3_scale_pow(linear.copy(), exponent, domain); - }; - return d3_scale_linearRebind(scale, linear); - } - function d3_scale_powPow(e) { - return function(x) { - return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); - }; - } - d3.scale.sqrt = function() { - return d3.scale.pow().exponent(.5); - }; - d3.scale.ordinal = function() { - return d3_scale_ordinal([], { - t: "range", - a: [ [] ] - }); - }; - function d3_scale_ordinal(domain, ranger) { - var index, range, rangeBand; - function scale(x) { - return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length]; - } - function steps(start, step) { - return d3.range(domain.length).map(function(i) { - return start + step * i; - }); - } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = []; - index = new d3_Map(); - var i = -1, n = x.length, xi; - while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); - return scale[ranger.t].apply(scale, ranger.a); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - rangeBand = 0; - ranger = { - t: "range", - a: arguments - }; - return scale; - }; - scale.rangePoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, - 0) : (stop - start) / (domain.length - 1 + padding); - range = steps(start + step * padding / 2, step); - rangeBand = 0; - ranger = { - t: "rangePoints", - a: arguments - }; - return scale; - }; - scale.rangeRoundPoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), - 0) : (stop - start) / (domain.length - 1 + padding) | 0; - range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step); - rangeBand = 0; - ranger = { - t: "rangeRoundPoints", - a: arguments - }; - return scale; - }; - scale.rangeBands = function(x, padding, outerPadding) { - if (arguments.length < 2) padding = 0; - if (arguments.length < 3) outerPadding = padding; - var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); - range = steps(start + step * outerPadding, step); - if (reverse) range.reverse(); - rangeBand = step * (1 - padding); - ranger = { - t: "rangeBands", - a: arguments - }; - return scale; - }; - scale.rangeRoundBands = function(x, padding, outerPadding) { - if (arguments.length < 2) padding = 0; - if (arguments.length < 3) outerPadding = padding; - var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)); - range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step); - if (reverse) range.reverse(); - rangeBand = Math.round(step * (1 - padding)); - ranger = { - t: "rangeRoundBands", - a: arguments - }; - return scale; - }; - scale.rangeBand = function() { - return rangeBand; - }; - scale.rangeExtent = function() { - return d3_scaleExtent(ranger.a[0]); - }; - scale.copy = function() { - return d3_scale_ordinal(domain, ranger); - }; - return scale.domain(domain); - } - d3.scale.category10 = function() { - return d3.scale.ordinal().range(d3_category10); - }; - d3.scale.category20 = function() { - return d3.scale.ordinal().range(d3_category20); - }; - d3.scale.category20b = function() { - return d3.scale.ordinal().range(d3_category20b); - }; - d3.scale.category20c = function() { - return d3.scale.ordinal().range(d3_category20c); - }; - var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); - var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); - var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); - var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); - d3.scale.quantile = function() { - return d3_scale_quantile([], []); - }; - function d3_scale_quantile(domain, range) { - var thresholds; - function rescale() { - var k = 0, q = range.length; - thresholds = []; - while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); - return scale; - } - function scale(x) { - if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; - } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.quantiles = function() { - return thresholds; - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; - }; - scale.copy = function() { - return d3_scale_quantile(domain, range); - }; - return rescale(); - } - d3.scale.quantize = function() { - return d3_scale_quantize(0, 1, [ 0, 1 ]); - }; - function d3_scale_quantize(x0, x1, range) { - var kx, i; - function scale(x) { - return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; - } - function rescale() { - kx = range.length / (x1 - x0); - i = range.length - 1; - return scale; - } - scale.domain = function(x) { - if (!arguments.length) return [ x0, x1 ]; - x0 = +x[0]; - x1 = +x[x.length - 1]; - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - y = y < 0 ? NaN : y / kx + x0; - return [ y, y + 1 / kx ]; - }; - scale.copy = function() { - return d3_scale_quantize(x0, x1, range); - }; - return rescale(); - } - d3.scale.threshold = function() { - return d3_scale_threshold([ .5 ], [ 0, 1 ]); - }; - function d3_scale_threshold(domain, range) { - function scale(x) { - if (x <= x) return range[d3.bisect(domain, x)]; - } - scale.domain = function(_) { - if (!arguments.length) return domain; - domain = _; - return scale; - }; - scale.range = function(_) { - if (!arguments.length) return range; - range = _; - return scale; - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - return [ domain[y - 1], domain[y] ]; - }; - scale.copy = function() { - return d3_scale_threshold(domain, range); - }; - return scale; - } - d3.scale.identity = function() { - return d3_scale_identity([ 0, 1 ]); - }; - function d3_scale_identity(domain) { - function identity(x) { - return +x; - } - identity.invert = identity; - identity.domain = identity.range = function(x) { - if (!arguments.length) return domain; - domain = x.map(identity); - return identity; - }; - identity.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - identity.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - identity.copy = function() { - return d3_scale_identity(domain); - }; - return identity; - } - d3.svg = {}; - function d3_zero() { - return 0; - } - d3.svg.arc = function() { - var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle; - function arc() { - var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1; - if (r1 < r0) rc = r1, r1 = r0, r0 = rc; - if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z"; - var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = []; - if (ap = (+padAngle.apply(this, arguments) || 0) / 2) { - rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments); - if (!cw) p1 *= -1; - if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap)); - if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap)); - } - if (r1) { - x0 = r1 * Math.cos(a0 + p1); - y0 = r1 * Math.sin(a0 + p1); - x1 = r1 * Math.cos(a1 - p1); - y1 = r1 * Math.sin(a1 - p1); - var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1; - if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) { - var h1 = (a0 + a1) / 2; - x0 = r1 * Math.cos(h1); - y0 = r1 * Math.sin(h1); - x1 = y1 = null; - } - } else { - x0 = y0 = 0; - } - if (r0) { - x2 = r0 * Math.cos(a1 - p0); - y2 = r0 * Math.sin(a1 - p0); - x3 = r0 * Math.cos(a0 + p0); - y3 = r0 * Math.sin(a0 + p0); - var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1; - if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) { - var h0 = (a0 + a1) / 2; - x2 = r0 * Math.cos(h0); - y2 = r0 * Math.sin(h0); - x3 = y3 = null; - } - } else { - x2 = y2 = 0; - } - if ((rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) { - cr = r0 < r1 ^ cw ? 0 : 1; - var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]); - if (x1 != null) { - var rc1 = Math.min(rc, (r1 - lc) / (kc + 1)), t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw); - if (rc === rc1) { - path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]); - } else { - path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]); - } - } else { - path.push("M", x0, ",", y0); - } - if (x3 != null) { - var rc0 = Math.min(rc, (r0 - lc) / (kc - 1)), t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw); - if (rc === rc0) { - path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); - } else { - path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); - } - } else { - path.push("L", x2, ",", y2); - } - } else { - path.push("M", x0, ",", y0); - if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1); - path.push("L", x2, ",", y2); - if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3); - } - path.push("Z"); - return path.join(""); - } - function circleSegment(r1, cw) { - return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1; - } - arc.innerRadius = function(v) { - if (!arguments.length) return innerRadius; - innerRadius = d3_functor(v); - return arc; - }; - arc.outerRadius = function(v) { - if (!arguments.length) return outerRadius; - outerRadius = d3_functor(v); - return arc; - }; - arc.cornerRadius = function(v) { - if (!arguments.length) return cornerRadius; - cornerRadius = d3_functor(v); - return arc; - }; - arc.padRadius = function(v) { - if (!arguments.length) return padRadius; - padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v); - return arc; - }; - arc.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return arc; - }; - arc.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return arc; - }; - arc.padAngle = function(v) { - if (!arguments.length) return padAngle; - padAngle = d3_functor(v); - return arc; - }; - arc.centroid = function() { - var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ; - return [ Math.cos(a) * r, Math.sin(a) * r ]; - }; - return arc; - }; - var d3_svg_arcAuto = "auto"; - function d3_svg_arcInnerRadius(d) { - return d.innerRadius; - } - function d3_svg_arcOuterRadius(d) { - return d.outerRadius; - } - function d3_svg_arcStartAngle(d) { - return d.startAngle; - } - function d3_svg_arcEndAngle(d) { - return d.endAngle; - } - function d3_svg_arcPadAngle(d) { - return d && d.padAngle; - } - function d3_svg_arcSweep(x0, y0, x1, y1) { - return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1; - } - function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) { - var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(r * r * d2 - D * D), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3; - if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; - return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ]; - } - function d3_svg_line(projection) { - var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; - function line(data) { - var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); - function segment() { - segments.push("M", interpolate(projection(points), tension)); - } - while (++i < n) { - if (defined.call(this, d = data[i], i)) { - points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); - } else if (points.length) { - segment(); - points = []; - } - } - if (points.length) segment(); - return segments.length ? segments.join("") : null; - } - line.x = function(_) { - if (!arguments.length) return x; - x = _; - return line; - }; - line.y = function(_) { - if (!arguments.length) return y; - y = _; - return line; - }; - line.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return line; - }; - line.interpolate = function(_) { - if (!arguments.length) return interpolateKey; - if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; - return line; - }; - line.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return line; - }; - return line; - } - d3.svg.line = function() { - return d3_svg_line(d3_identity); - }; - var d3_svg_lineInterpolators = d3.map({ - linear: d3_svg_lineLinear, - "linear-closed": d3_svg_lineLinearClosed, - step: d3_svg_lineStep, - "step-before": d3_svg_lineStepBefore, - "step-after": d3_svg_lineStepAfter, - basis: d3_svg_lineBasis, - "basis-open": d3_svg_lineBasisOpen, - "basis-closed": d3_svg_lineBasisClosed, - bundle: d3_svg_lineBundle, - cardinal: d3_svg_lineCardinal, - "cardinal-open": d3_svg_lineCardinalOpen, - "cardinal-closed": d3_svg_lineCardinalClosed, - monotone: d3_svg_lineMonotone - }); - d3_svg_lineInterpolators.forEach(function(key, value) { - value.key = key; - value.closed = /-closed$/.test(key); - }); - function d3_svg_lineLinear(points) { - return points.join("L"); - } - function d3_svg_lineLinearClosed(points) { - return d3_svg_lineLinear(points) + "Z"; - } - function d3_svg_lineStep(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); - if (n > 1) path.push("H", p[0]); - return path.join(""); - } - function d3_svg_lineStepBefore(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); - return path.join(""); - } - function d3_svg_lineStepAfter(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); - return path.join(""); - } - function d3_svg_lineCardinalOpen(points, tension) { - return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension)); - } - function d3_svg_lineCardinalClosed(points, tension) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), - points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); - } - function d3_svg_lineCardinal(points, tension) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); - } - function d3_svg_lineHermite(points, tangents) { - if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { - return d3_svg_lineLinear(points); - } - var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; - if (quad) { - path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; - p0 = points[1]; - pi = 2; - } - if (tangents.length > 1) { - t = tangents[1]; - p = points[pi]; - pi++; - path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; - for (var i = 2; i < tangents.length; i++, pi++) { - p = points[pi]; - t = tangents[i]; - path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; - } - } - if (quad) { - var lp = points[pi]; - path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; - } - return path; - } - function d3_svg_lineCardinalTangents(points, tension) { - var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; - while (++i < n) { - p0 = p1; - p1 = p2; - p2 = points[i]; - tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); - } - return tangents; - } - function d3_svg_lineBasis(points) { - if (points.length < 3) return d3_svg_lineLinear(points); - var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; - points.push(points[n - 1]); - while (++i <= n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - points.pop(); - path.push("L", pi); - return path.join(""); - } - function d3_svg_lineBasisOpen(points) { - if (points.length < 4) return d3_svg_lineLinear(points); - var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; - while (++i < 3) { - pi = points[i]; - px.push(pi[0]); - py.push(pi[1]); - } - path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); - --i; - while (++i < n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); - } - function d3_svg_lineBasisClosed(points) { - var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; - while (++i < 4) { - pi = points[i % n]; - px.push(pi[0]); - py.push(pi[1]); - } - path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; - --i; - while (++i < m) { - pi = points[i % n]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); - } - function d3_svg_lineBundle(points, tension) { - var n = points.length - 1; - if (n) { - var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; - while (++i <= n) { - p = points[i]; - t = i / n; - p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); - p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); - } - } - return d3_svg_lineBasis(points); - } - function d3_svg_lineDot4(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; - } - var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; - function d3_svg_lineBasisBezier(path, x, y) { - path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); - } - function d3_svg_lineSlope(p0, p1) { - return (p1[1] - p0[1]) / (p1[0] - p0[0]); - } - function d3_svg_lineFiniteDifferences(points) { - var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); - while (++i < j) { - m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; - } - m[i] = d; - return m; - } - function d3_svg_lineMonotoneTangents(points) { - var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; - while (++i < j) { - d = d3_svg_lineSlope(points[i], points[i + 1]); - if (abs(d) < ε) { - m[i] = m[i + 1] = 0; - } else { - a = m[i] / d; - b = m[i + 1] / d; - s = a * a + b * b; - if (s > 9) { - s = d * 3 / Math.sqrt(s); - m[i] = s * a; - m[i + 1] = s * b; - } - } - } - i = -1; - while (++i <= j) { - s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); - tangents.push([ s || 0, m[i] * s || 0 ]); - } - return tangents; - } - function d3_svg_lineMonotone(points) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); - } - d3.svg.line.radial = function() { - var line = d3_svg_line(d3_svg_lineRadial); - line.radius = line.x, delete line.x; - line.angle = line.y, delete line.y; - return line; - }; - function d3_svg_lineRadial(points) { - var point, i = -1, n = points.length, r, a; - while (++i < n) { - point = points[i]; - r = point[0]; - a = point[1] - halfπ; - point[0] = r * Math.cos(a); - point[1] = r * Math.sin(a); - } - return points; - } - function d3_svg_area(projection) { - var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; - function area(data) { - var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { - return x; - } : d3_functor(x1), fy1 = y0 === y1 ? function() { - return y; - } : d3_functor(y1), x, y; - function segment() { - segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); - } - while (++i < n) { - if (defined.call(this, d = data[i], i)) { - points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); - points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); - } else if (points0.length) { - segment(); - points0 = []; - points1 = []; - } - } - if (points0.length) segment(); - return segments.length ? segments.join("") : null; - } - area.x = function(_) { - if (!arguments.length) return x1; - x0 = x1 = _; - return area; - }; - area.x0 = function(_) { - if (!arguments.length) return x0; - x0 = _; - return area; - }; - area.x1 = function(_) { - if (!arguments.length) return x1; - x1 = _; - return area; - }; - area.y = function(_) { - if (!arguments.length) return y1; - y0 = y1 = _; - return area; - }; - area.y0 = function(_) { - if (!arguments.length) return y0; - y0 = _; - return area; - }; - area.y1 = function(_) { - if (!arguments.length) return y1; - y1 = _; - return area; - }; - area.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return area; - }; - area.interpolate = function(_) { - if (!arguments.length) return interpolateKey; - if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; - interpolateReverse = interpolate.reverse || interpolate; - L = interpolate.closed ? "M" : "L"; - return area; - }; - area.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return area; - }; - return area; - } - d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; - d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; - d3.svg.area = function() { - return d3_svg_area(d3_identity); - }; - d3.svg.area.radial = function() { - var area = d3_svg_area(d3_svg_lineRadial); - area.radius = area.x, delete area.x; - area.innerRadius = area.x0, delete area.x0; - area.outerRadius = area.x1, delete area.x1; - area.angle = area.y, delete area.y; - area.startAngle = area.y0, delete area.y0; - area.endAngle = area.y1, delete area.y1; - return area; - }; - d3.svg.chord = function() { - var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; - function chord(d, i) { - var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); - return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; - } - function subgroup(self, f, d, i) { - var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ; - return { - r: r, - a0: a0, - a1: a1, - p0: [ r * Math.cos(a0), r * Math.sin(a0) ], - p1: [ r * Math.cos(a1), r * Math.sin(a1) ] - }; - } - function equals(a, b) { - return a.a0 == b.a0 && a.a1 == b.a1; - } - function arc(r, p, a) { - return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p; - } - function curve(r0, p0, r1, p1) { - return "Q 0,0 " + p1; - } - chord.radius = function(v) { - if (!arguments.length) return radius; - radius = d3_functor(v); - return chord; - }; - chord.source = function(v) { - if (!arguments.length) return source; - source = d3_functor(v); - return chord; - }; - chord.target = function(v) { - if (!arguments.length) return target; - target = d3_functor(v); - return chord; - }; - chord.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return chord; - }; - chord.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return chord; - }; - return chord; - }; - function d3_svg_chordRadius(d) { - return d.radius; - } - d3.svg.diagonal = function() { - var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; - function diagonal(d, i) { - var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { - x: p0.x, - y: m - }, { - x: p3.x, - y: m - }, p3 ]; - p = p.map(projection); - return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; - } - diagonal.source = function(x) { - if (!arguments.length) return source; - source = d3_functor(x); - return diagonal; - }; - diagonal.target = function(x) { - if (!arguments.length) return target; - target = d3_functor(x); - return diagonal; - }; - diagonal.projection = function(x) { - if (!arguments.length) return projection; - projection = x; - return diagonal; - }; - return diagonal; - }; - function d3_svg_diagonalProjection(d) { - return [ d.x, d.y ]; - } - d3.svg.diagonal.radial = function() { - var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; - diagonal.projection = function(x) { - return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; - }; - return diagonal; - }; - function d3_svg_diagonalRadialProjection(projection) { - return function() { - var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ; - return [ r * Math.cos(a), r * Math.sin(a) ]; - }; - } - d3.svg.symbol = function() { - var type = d3_svg_symbolType, size = d3_svg_symbolSize; - function symbol(d, i) { - return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); - } - symbol.type = function(x) { - if (!arguments.length) return type; - type = d3_functor(x); - return symbol; - }; - symbol.size = function(x) { - if (!arguments.length) return size; - size = d3_functor(x); - return symbol; - }; - return symbol; - }; - function d3_svg_symbolSize() { - return 64; - } - function d3_svg_symbolType() { - return "circle"; - } - function d3_svg_symbolCircle(size) { - var r = Math.sqrt(size / π); - return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; - } - var d3_svg_symbols = d3.map({ - circle: d3_svg_symbolCircle, - cross: function(size) { - var r = Math.sqrt(size / 5) / 2; - return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; - }, - diamond: function(size) { - var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; - return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; - }, - square: function(size) { - var r = Math.sqrt(size) / 2; - return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; - }, - "triangle-down": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; - }, - "triangle-up": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; - } - }); - d3.svg.symbolTypes = d3_svg_symbols.keys(); - var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); - d3_selectionPrototype.transition = function(name) { - var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || { - time: Date.now(), - ease: d3_ease_cubicInOut, - delay: 0, - duration: 250 - }; - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) d3_transitionNode(node, i, ns, id, transition); - subgroup.push(node); - } - } - return d3_transition(subgroups, ns, id); - }; - d3_selectionPrototype.interrupt = function(name) { - return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name))); - }; - var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace()); - function d3_selection_interruptNS(ns) { - return function() { - var lock, active; - if ((lock = this[ns]) && (active = lock[lock.active])) { - if (--lock.count) { - delete lock[lock.active]; - lock.active += .5; - } else { - delete this[ns]; - } - active.event && active.event.interrupt.call(this, this.__data__, active.index); - } - }; - } - function d3_transition(groups, ns, id) { - d3_subclass(groups, d3_transitionPrototype); - groups.namespace = ns; - groups.id = id; - return groups; - } - var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit; - d3_transitionPrototype.call = d3_selectionPrototype.call; - d3_transitionPrototype.empty = d3_selectionPrototype.empty; - d3_transitionPrototype.node = d3_selectionPrototype.node; - d3_transitionPrototype.size = d3_selectionPrototype.size; - d3.transition = function(selection, name) { - return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3_selectionRoot.transition(selection); - }; - d3.transition.prototype = d3_transitionPrototype; - d3_transitionPrototype.select = function(selector) { - var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node; - selector = d3_selection_selector(selector); - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - d3_transitionNode(subnode, i, ns, id, node[ns][id]); - subgroup.push(subnode); - } else { - subgroup.push(null); - } - } - } - return d3_transition(subgroups, ns, id); - }; - d3_transitionPrototype.selectAll = function(selector) { - var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition; - selector = d3_selection_selectorAll(selector); - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - transition = node[ns][id]; - subnodes = selector.call(node, node.__data__, i, j); - subgroups.push(subgroup = []); - for (var k = -1, o = subnodes.length; ++k < o; ) { - if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition); - subgroup.push(subnode); - } - } - } - } - return d3_transition(subgroups, ns, id); - }; - d3_transitionPrototype.filter = function(filter) { - var subgroups = [], subgroup, group, node; - if (typeof filter !== "function") filter = d3_selection_filter(filter); - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { - subgroup.push(node); - } - } - } - return d3_transition(subgroups, this.namespace, this.id); - }; - d3_transitionPrototype.tween = function(name, tween) { - var id = this.id, ns = this.namespace; - if (arguments.length < 2) return this.node()[ns][id].tween.get(name); - return d3_selection_each(this, tween == null ? function(node) { - node[ns][id].tween.remove(name); - } : function(node) { - node[ns][id].tween.set(name, tween); - }); - }; - function d3_transition_tween(groups, name, value, tween) { - var id = groups.id, ns = groups.namespace; - return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { - node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j))); - } : (value = tween(value), function(node) { - node[ns][id].tween.set(name, value); - })); - } - d3_transitionPrototype.attr = function(nameNS, value) { - if (arguments.length < 2) { - for (value in nameNS) this.attr(value, nameNS[value]); - return this; - } - var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - function attrTween(b) { - return b == null ? attrNull : (b += "", function() { - var a = this.getAttribute(name), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttribute(name, i(t)); - }); - }); - } - function attrTweenNS(b) { - return b == null ? attrNullNS : (b += "", function() { - var a = this.getAttributeNS(name.space, name.local), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttributeNS(name.space, name.local, i(t)); - }); - }); - } - return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween); - }; - d3_transitionPrototype.attrTween = function(nameNS, tween) { - var name = d3.ns.qualify(nameNS); - function attrTween(d, i) { - var f = tween.call(this, d, i, this.getAttribute(name)); - return f && function(t) { - this.setAttribute(name, f(t)); - }; - } - function attrTweenNS(d, i) { - var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); - return f && function(t) { - this.setAttributeNS(name.space, name.local, f(t)); - }; - } - return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); - }; - d3_transitionPrototype.style = function(name, value, priority) { - var n = arguments.length; - if (n < 3) { - if (typeof name !== "string") { - if (n < 2) value = ""; - for (priority in name) this.style(priority, name[priority], value); - return this; - } - priority = ""; - } - function styleNull() { - this.style.removeProperty(name); - } - function styleString(b) { - return b == null ? styleNull : (b += "", function() { - var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i; - return a !== b && (i = d3_interpolate(a, b), function(t) { - this.style.setProperty(name, i(t), priority); - }); - }); - } - return d3_transition_tween(this, "style." + name, value, styleString); - }; - d3_transitionPrototype.styleTween = function(name, tween, priority) { - if (arguments.length < 3) priority = ""; - function styleTween(d, i) { - var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name)); - return f && function(t) { - this.style.setProperty(name, f(t), priority); - }; - } - return this.tween("style." + name, styleTween); - }; - d3_transitionPrototype.text = function(value) { - return d3_transition_tween(this, "text", value, d3_transition_text); - }; - function d3_transition_text(b) { - if (b == null) b = ""; - return function() { - this.textContent = b; - }; - } - d3_transitionPrototype.remove = function() { - var ns = this.namespace; - return this.each("end.transition", function() { - var p; - if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this); - }); - }; - d3_transitionPrototype.ease = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].ease; - if (typeof value !== "function") value = d3.ease.apply(d3, arguments); - return d3_selection_each(this, function(node) { - node[ns][id].ease = value; - }); - }; - d3_transitionPrototype.delay = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].delay; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node[ns][id].delay = +value.call(node, node.__data__, i, j); - } : (value = +value, function(node) { - node[ns][id].delay = value; - })); - }; - d3_transitionPrototype.duration = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].duration; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j)); - } : (value = Math.max(1, value), function(node) { - node[ns][id].duration = value; - })); - }; - d3_transitionPrototype.each = function(type, listener) { - var id = this.id, ns = this.namespace; - if (arguments.length < 2) { - var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; - try { - d3_transitionInheritId = id; - d3_selection_each(this, function(node, i, j) { - d3_transitionInherit = node[ns][id]; - type.call(node, node.__data__, i, j); - }); - } finally { - d3_transitionInherit = inherit; - d3_transitionInheritId = inheritId; - } - } else { - d3_selection_each(this, function(node) { - var transition = node[ns][id]; - (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener); - }); - } - return this; - }; - d3_transitionPrototype.transition = function() { - var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition; - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - if (node = group[i]) { - transition = node[ns][id0]; - d3_transitionNode(node, i, ns, id1, { - time: transition.time, - ease: transition.ease, - delay: transition.delay + transition.duration, - duration: transition.duration - }); - } - subgroup.push(node); - } - } - return d3_transition(subgroups, ns, id1); - }; - function d3_transitionNamespace(name) { - return name == null ? "__transition__" : "__transition_" + name + "__"; - } - function d3_transitionNode(node, i, ns, id, inherit) { - var lock = node[ns] || (node[ns] = { - active: 0, - count: 0 - }), transition = lock[id]; - if (!transition) { - var time = inherit.time; - transition = lock[id] = { - tween: new d3_Map(), - time: time, - delay: inherit.delay, - duration: inherit.duration, - ease: inherit.ease, - index: i - }; - inherit = null; - ++lock.count; - d3.timer(function(elapsed) { - var delay = transition.delay, duration, ease, timer = d3_timer_active, tweened = []; - timer.t = delay + time; - if (delay <= elapsed) return start(elapsed - delay); - timer.c = start; - function start(elapsed) { - if (lock.active > id) return stop(); - var active = lock[lock.active]; - if (active) { - --lock.count; - delete lock[lock.active]; - active.event && active.event.interrupt.call(node, node.__data__, active.index); - } - lock.active = id; - transition.event && transition.event.start.call(node, node.__data__, i); - transition.tween.forEach(function(key, value) { - if (value = value.call(node, node.__data__, i)) { - tweened.push(value); - } - }); - ease = transition.ease; - duration = transition.duration; - d3.timer(function() { - timer.c = tick(elapsed || 1) ? d3_true : tick; - return 1; - }, 0, time); - } - function tick(elapsed) { - if (lock.active !== id) return 1; - var t = elapsed / duration, e = ease(t), n = tweened.length; - while (n > 0) { - tweened[--n].call(node, e); - } - if (t >= 1) { - transition.event && transition.event.end.call(node, node.__data__, i); - return stop(); - } - } - function stop() { - if (--lock.count) delete lock[id]; else delete node[ns]; - return 1; - } - }, 0, time); - } - } - d3.svg.axis = function() { - var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; - function axis(g) { - g.each(function() { - var g = d3.select(this); - var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); - var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform; - var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), - d3.transition(path)); - tickEnter.append("line"); - tickEnter.append("text"); - var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2; - if (orient === "bottom" || orient === "top") { - tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2"; - text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle"); - pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize); - } else { - tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2"; - text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start"); - pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize); - } - lineEnter.attr(y2, sign * innerTickSize); - textEnter.attr(y1, sign * tickSpacing); - lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize); - textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing); - if (scale1.rangeBand) { - var x = scale1, dx = x.rangeBand() / 2; - scale0 = scale1 = function(d) { - return x(d) + dx; - }; - } else if (scale0.rangeBand) { - scale0 = scale1; - } else { - tickExit.call(tickTransform, scale1, scale0); - } - tickEnter.call(tickTransform, scale0, scale1); - tickUpdate.call(tickTransform, scale1, scale1); - }); - } - axis.scale = function(x) { - if (!arguments.length) return scale; - scale = x; - return axis; - }; - axis.orient = function(x) { - if (!arguments.length) return orient; - orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; - return axis; - }; - axis.ticks = function() { - if (!arguments.length) return tickArguments_; - tickArguments_ = arguments; - return axis; - }; - axis.tickValues = function(x) { - if (!arguments.length) return tickValues; - tickValues = x; - return axis; - }; - axis.tickFormat = function(x) { - if (!arguments.length) return tickFormat_; - tickFormat_ = x; - return axis; - }; - axis.tickSize = function(x) { - var n = arguments.length; - if (!n) return innerTickSize; - innerTickSize = +x; - outerTickSize = +arguments[n - 1]; - return axis; - }; - axis.innerTickSize = function(x) { - if (!arguments.length) return innerTickSize; - innerTickSize = +x; - return axis; - }; - axis.outerTickSize = function(x) { - if (!arguments.length) return outerTickSize; - outerTickSize = +x; - return axis; - }; - axis.tickPadding = function(x) { - if (!arguments.length) return tickPadding; - tickPadding = +x; - return axis; - }; - axis.tickSubdivide = function() { - return arguments.length && axis; - }; - return axis; - }; - var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { - top: 1, - right: 1, - bottom: 1, - left: 1 - }; - function d3_svg_axisX(selection, x0, x1) { - selection.attr("transform", function(d) { - var v0 = x0(d); - return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)"; - }); - } - function d3_svg_axisY(selection, y0, y1) { - selection.attr("transform", function(d) { - var v0 = y0(d); - return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")"; - }); - } - d3.svg.brush = function() { - var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; - function brush(g) { - g.each(function() { - var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); - var background = g.selectAll(".background").data([ 0 ]); - background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); - g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); - var resize = g.selectAll(".resize").data(resizes, d3_identity); - resize.exit().remove(); - resize.enter().append("g").attr("class", function(d) { - return "resize " + d; - }).style("cursor", function(d) { - return d3_svg_brushCursor[d]; - }).append("rect").attr("x", function(d) { - return /[ew]$/.test(d) ? -3 : null; - }).attr("y", function(d) { - return /^[ns]/.test(d) ? -3 : null; - }).attr("width", 6).attr("height", 6).style("visibility", "hidden"); - resize.style("display", brush.empty() ? "none" : null); - var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; - if (x) { - range = d3_scaleRange(x); - backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); - redrawX(gUpdate); - } - if (y) { - range = d3_scaleRange(y); - backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); - redrawY(gUpdate); - } - redraw(gUpdate); - }); - } - brush.event = function(g) { - g.each(function() { - var event_ = event.of(this, arguments), extent1 = { - x: xExtent, - y: yExtent, - i: xExtentDomain, - j: yExtentDomain - }, extent0 = this.__chart__ || extent1; - this.__chart__ = extent1; - if (d3_transitionInheritId) { - d3.select(this).transition().each("start.brush", function() { - xExtentDomain = extent0.i; - yExtentDomain = extent0.j; - xExtent = extent0.x; - yExtent = extent0.y; - event_({ - type: "brushstart" - }); - }).tween("brush:brush", function() { - var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); - xExtentDomain = yExtentDomain = null; - return function(t) { - xExtent = extent1.x = xi(t); - yExtent = extent1.y = yi(t); - event_({ - type: "brush", - mode: "resize" - }); - }; - }).each("end.brush", function() { - xExtentDomain = extent1.i; - yExtentDomain = extent1.j; - event_({ - type: "brush", - mode: "resize" - }); - event_({ - type: "brushend" - }); - }); - } else { - event_({ - type: "brushstart" - }); - event_({ - type: "brush", - mode: "resize" - }); - event_({ - type: "brushend" - }); - } - }); - }; - function redraw(g) { - g.selectAll(".resize").attr("transform", function(d) { - return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; - }); - } - function redrawX(g) { - g.select(".extent").attr("x", xExtent[0]); - g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); - } - function redrawY(g) { - g.select(".extent").attr("y", yExtent[0]); - g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); - } - function brushstart() { - var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(), center, origin = d3.mouse(target), offset; - var w = d3.select(d3_window).on("keydown.brush", keydown).on("keyup.brush", keyup); - if (d3.event.changedTouches) { - w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); - } else { - w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); - } - g.interrupt().selectAll("*").interrupt(); - if (dragging) { - origin[0] = xExtent[0] - origin[0]; - origin[1] = yExtent[0] - origin[1]; - } else if (resizing) { - var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); - offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; - origin[0] = xExtent[ex]; - origin[1] = yExtent[ey]; - } else if (d3.event.altKey) center = origin.slice(); - g.style("pointer-events", "none").selectAll(".resize").style("display", null); - d3.select("body").style("cursor", eventTarget.style("cursor")); - event_({ - type: "brushstart" - }); - brushmove(); - function keydown() { - if (d3.event.keyCode == 32) { - if (!dragging) { - center = null; - origin[0] -= xExtent[1]; - origin[1] -= yExtent[1]; - dragging = 2; - } - d3_eventPreventDefault(); - } - } - function keyup() { - if (d3.event.keyCode == 32 && dragging == 2) { - origin[0] += xExtent[1]; - origin[1] += yExtent[1]; - dragging = 0; - d3_eventPreventDefault(); - } - } - function brushmove() { - var point = d3.mouse(target), moved = false; - if (offset) { - point[0] += offset[0]; - point[1] += offset[1]; - } - if (!dragging) { - if (d3.event.altKey) { - if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; - origin[0] = xExtent[+(point[0] < center[0])]; - origin[1] = yExtent[+(point[1] < center[1])]; - } else center = null; - } - if (resizingX && move1(point, x, 0)) { - redrawX(g); - moved = true; - } - if (resizingY && move1(point, y, 1)) { - redrawY(g); - moved = true; - } - if (moved) { - redraw(g); - event_({ - type: "brush", - mode: dragging ? "move" : "resize" - }); - } - } - function move1(point, scale, i) { - var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; - if (dragging) { - r0 -= position; - r1 -= size + position; - } - min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; - if (dragging) { - max = (min += position) + size; - } else { - if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); - if (position < min) { - max = min; - min = position; - } else { - max = position; - } - } - if (extent[0] != min || extent[1] != max) { - if (i) yExtentDomain = null; else xExtentDomain = null; - extent[0] = min; - extent[1] = max; - return true; - } - } - function brushend() { - brushmove(); - g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); - d3.select("body").style("cursor", null); - w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); - dragRestore(); - event_({ - type: "brushend" - }); - } - } - brush.x = function(z) { - if (!arguments.length) return x; - x = z; - resizes = d3_svg_brushResizes[!x << 1 | !y]; - return brush; - }; - brush.y = function(z) { - if (!arguments.length) return y; - y = z; - resizes = d3_svg_brushResizes[!x << 1 | !y]; - return brush; - }; - brush.clamp = function(z) { - if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; - if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; - return brush; - }; - brush.extent = function(z) { - var x0, x1, y0, y1, t; - if (!arguments.length) { - if (x) { - if (xExtentDomain) { - x0 = xExtentDomain[0], x1 = xExtentDomain[1]; - } else { - x0 = xExtent[0], x1 = xExtent[1]; - if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - } - } - if (y) { - if (yExtentDomain) { - y0 = yExtentDomain[0], y1 = yExtentDomain[1]; - } else { - y0 = yExtent[0], y1 = yExtent[1]; - if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - } - } - return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; - } - if (x) { - x0 = z[0], x1 = z[1]; - if (y) x0 = x0[0], x1 = x1[0]; - xExtentDomain = [ x0, x1 ]; - if (x.invert) x0 = x(x0), x1 = x(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; - } - if (y) { - y0 = z[0], y1 = z[1]; - if (x) y0 = y0[1], y1 = y1[1]; - yExtentDomain = [ y0, y1 ]; - if (y.invert) y0 = y(y0), y1 = y(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; - } - return brush; - }; - brush.clear = function() { - if (!brush.empty()) { - xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; - xExtentDomain = yExtentDomain = null; - } - return brush; - }; - brush.empty = function() { - return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; - }; - return d3.rebind(brush, event, "on"); - }; - var d3_svg_brushCursor = { - n: "ns-resize", - e: "ew-resize", - s: "ns-resize", - w: "ew-resize", - nw: "nwse-resize", - ne: "nesw-resize", - se: "nwse-resize", - sw: "nesw-resize" - }; - var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; - var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; - var d3_time_formatUtc = d3_time_format.utc; - var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); - d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; - function d3_time_formatIsoNative(date) { - return date.toISOString(); - } - d3_time_formatIsoNative.parse = function(string) { - var date = new Date(string); - return isNaN(date) ? null : date; - }; - d3_time_formatIsoNative.toString = d3_time_formatIso.toString; - d3_time.second = d3_time_interval(function(date) { - return new d3_date(Math.floor(date / 1e3) * 1e3); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 1e3); - }, function(date) { - return date.getSeconds(); - }); - d3_time.seconds = d3_time.second.range; - d3_time.seconds.utc = d3_time.second.utc.range; - d3_time.minute = d3_time_interval(function(date) { - return new d3_date(Math.floor(date / 6e4) * 6e4); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 6e4); - }, function(date) { - return date.getMinutes(); - }); - d3_time.minutes = d3_time.minute.range; - d3_time.minutes.utc = d3_time.minute.utc.range; - d3_time.hour = d3_time_interval(function(date) { - var timezone = date.getTimezoneOffset() / 60; - return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 36e5); - }, function(date) { - return date.getHours(); - }); - d3_time.hours = d3_time.hour.range; - d3_time.hours.utc = d3_time.hour.utc.range; - d3_time.month = d3_time_interval(function(date) { - date = d3_time.day(date); - date.setDate(1); - return date; - }, function(date, offset) { - date.setMonth(date.getMonth() + offset); - }, function(date) { - return date.getMonth(); - }); - d3_time.months = d3_time.month.range; - d3_time.months.utc = d3_time.month.utc.range; - function d3_time_scale(linear, methods, format) { - function scale(x) { - return linear(x); - } - scale.invert = function(x) { - return d3_time_scaleDate(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return linear.domain().map(d3_time_scaleDate); - linear.domain(x); - return scale; - }; - function tickMethod(extent, count) { - var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); - return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { - return d / 31536e6; - }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; - } - scale.nice = function(interval, skip) { - var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); - if (method) interval = method[0], skip = method[1]; - function skipped(date) { - return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; - } - return scale.domain(d3_scale_nice(domain, skip > 1 ? { - floor: function(date) { - while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); - return date; - }, - ceil: function(date) { - while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); - return date; - } - } : interval)); - }; - scale.ticks = function(interval, skip) { - var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { - range: interval - }, skip ]; - if (method) interval = method[0], skip = method[1]; - return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); - }; - scale.tickFormat = function() { - return format; - }; - scale.copy = function() { - return d3_time_scale(linear.copy(), methods, format); - }; - return d3_scale_linearRebind(scale, linear); - } - function d3_time_scaleDate(t) { - return new Date(t); - } - var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; - var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; - var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { - return d.getMilliseconds(); - } ], [ ":%S", function(d) { - return d.getSeconds(); - } ], [ "%I:%M", function(d) { - return d.getMinutes(); - } ], [ "%I %p", function(d) { - return d.getHours(); - } ], [ "%a %d", function(d) { - return d.getDay() && d.getDate() != 1; - } ], [ "%b %d", function(d) { - return d.getDate() != 1; - } ], [ "%B", function(d) { - return d.getMonth(); - } ], [ "%Y", d3_true ] ]); - var d3_time_scaleMilliseconds = { - range: function(start, stop, step) { - return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate); - }, - floor: d3_identity, - ceil: d3_identity - }; - d3_time_scaleLocalMethods.year = d3_time.year; - d3_time.scale = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); - }; - var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { - return [ m[0].utc, m[1] ]; - }); - var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { - return d.getUTCMilliseconds(); - } ], [ ":%S", function(d) { - return d.getUTCSeconds(); - } ], [ "%I:%M", function(d) { - return d.getUTCMinutes(); - } ], [ "%I %p", function(d) { - return d.getUTCHours(); - } ], [ "%a %d", function(d) { - return d.getUTCDay() && d.getUTCDate() != 1; - } ], [ "%b %d", function(d) { - return d.getUTCDate() != 1; - } ], [ "%B", function(d) { - return d.getUTCMonth(); - } ], [ "%Y", d3_true ] ]); - d3_time_scaleUtcMethods.year = d3_time.year.utc; - d3_time.scale.utc = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); - }; - d3.text = d3_xhrType(function(request) { - return request.responseText; - }); - d3.json = function(url, callback) { - return d3_xhr(url, "application/json", d3_json, callback); - }; - function d3_json(request) { - return JSON.parse(request.responseText); - } - d3.html = function(url, callback) { - return d3_xhr(url, "text/html", d3_html, callback); - }; - function d3_html(request) { - var range = d3_document.createRange(); - range.selectNode(d3_document.body); - return range.createContextualFragment(request.responseText); - } - d3.xml = d3_xhrType(function(request) { - return request.responseXML; - }); - if (typeof define === "function" && define.amd) define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; - this.d3 = d3; -}(); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/d3.v3.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/d3.v3.js deleted file mode 100644 index 77615c0c..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/d3.v3.js +++ /dev/null @@ -1,5 +0,0 @@ -d3=function(){function n(n){return null!=n&&!isNaN(n)}function t(n){return n.length}function e(n){for(var t=1;n*t%1;)t*=10;return t}function r(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function u(){}function i(){}function o(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function a(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=Do.length;r>e;++e){var u=Do[e]+t;if(u in n)return u}}function c(){}function l(){}function s(n){function t(){for(var t,r=e,u=-1,i=r.length;++ue;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function T(n){return Lo(n,Io),n}function q(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t0&&(n=n.substring(0,a));var s=Zo.get(n);return s&&(n=s,l=j),a?t?u:r:t?c:i}function D(n,t){return function(e){var r=mo.event;mo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{mo.event=r}}}function j(n,t){var e=D(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function L(){var n=".dragsuppress-"+ ++Xo,t="touchmove"+n,e="selectstart"+n,r="dragstart"+n,u="click"+n,i=mo.select(_o).on(t,f).on(e,f).on(r,f),o=bo.style,a=o[Vo];return o[Vo]="none",function(t){function e(){i.on(u,null)}i.on(n,null),o[Vo]=a,t&&(i.on(u,function(){f(),e()},!0),setTimeout(e,0))}}function H(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>$o&&(_o.scrollX||_o.scrollY)){e=mo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();$o=!(u.f||u.e),e.remove()}return $o?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function F(n){return n>0?1:0>n?-1:0}function P(n){return n>1?0:-1>n?Bo:Math.acos(n)}function O(n){return n>1?Jo:-1>n?-Jo:Math.asin(n)}function R(n){return((n=Math.exp(n))-1/n)/2}function Y(n){return((n=Math.exp(n))+1/n)/2}function I(n){return((n=Math.exp(2*n))-1)/(n+1)}function U(n){return(n=Math.sin(n/2))*n}function Z(){}function V(n,t,e){return new X(n,t,e)}function X(n,t,e){this.h=n,this.s=t,this.l=e}function $(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,ot(u(n+120),u(n),u(n-120))}function B(n,t,e){return new W(n,t,e)}function W(n,t,e){this.h=n,this.c=t,this.l=e}function J(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),G(e,Math.cos(n*=Qo)*t,Math.sin(n)*t)}function G(n,t,e){return new K(n,t,e)}function K(n,t,e){this.l=n,this.a=t,this.b=e}function Q(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=tt(u)*sa,r=tt(r)*fa,i=tt(i)*ha,ot(rt(3.2404542*u-1.5371385*r-.4985314*i),rt(-.969266*u+1.8760108*r+.041556*i),rt(.0556434*u-.2040259*r+1.0572252*i))}function nt(n,t,e){return n>0?B(Math.atan2(e,t)*na,Math.sqrt(t*t+e*e),n):B(0/0,0/0,n)}function tt(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function et(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function rt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function ut(n){return ot(n>>16,255&n>>8,255&n)}function it(n){return ut(n)+""}function ot(n,t,e){return new at(n,t,e)}function at(n,t,e){this.r=n,this.g=t,this.b=e}function ct(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function lt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(gt(u[0]),gt(u[1]),gt(u[2]))}return(i=da.get(n))?t(i.r,i.g,i.b):(null!=n&&"#"===n.charAt(0)&&(4===n.length?(o=n.charAt(1),o+=o,a=n.charAt(2),a+=a,c=n.charAt(3),c+=c):7===n.length&&(o=n.substring(1,3),a=n.substring(3,5),c=n.substring(5,7)),o=parseInt(o,16),a=parseInt(a,16),c=parseInt(c,16)),t(o,a,c))}function st(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),V(r,u,c)}function ft(n,t,e){n=ht(n),t=ht(t),e=ht(e);var r=et((.4124564*n+.3575761*t+.1804375*e)/sa),u=et((.2126729*n+.7151522*t+.072175*e)/fa),i=et((.0193339*n+.119192*t+.9503041*e)/ha);return G(116*u-16,500*(r-u),200*(u-i))}function ht(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function gt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function pt(n){return"function"==typeof n?n:function(){return n}}function dt(n){return n}function vt(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),mt(t,e,n,r)}}function mt(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=mo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,l=null;return!_o.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=mo.event;mo.event=n;try{o.progress.call(i,c)}finally{mo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(l=n,i):l},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Mo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var s in a)c.setRequestHeader(s,a[s]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=l&&(c.responseType=l),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},mo.rebind(i,o,"on"),null==r?i:i.get(yt(r))}function yt(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Mt(){var n=bt(),t=_t()-n;t>24?(isFinite(t)&&(clearTimeout(Ma),Ma=setTimeout(Mt,t)),ya=0):(ya=1,ba(Mt))}function xt(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now()),xa.callback=n,xa.time=e+t}function bt(){var n=Date.now();for(xa=va;xa;)n>=xa.time&&(xa.flush=xa.callback(n-xa.time)),xa=xa.next;return n}function _t(){for(var n,t=va,e=1/0;t;)t.flush?t=n?n.next=t.next:va=t.next:(t.time8?function(n){return n/e}:function(n){return n*e},symbol:n}}function St(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Et(n){return n+""}function kt(){}function At(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function Nt(n,t){n&&Da.hasOwnProperty(n.type)&&Da[n.type](n,t)}function Tt(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++ua;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c={point:e,points:n,other:null,visited:!1,entry:!0,subject:!0},l={point:e,points:[e],other:c,visited:!1,entry:!1,subject:!1};c.other=l,i.push(c),o.push(l),c={point:r,points:[r],other:null,visited:!1,entry:!1,subject:!0},l={point:r,points:[r],other:c,visited:!1,entry:!0,subject:!1},c.other=l,i.push(c),o.push(l)}}),o.sort(t),$t(i),$t(o),i.length){for(var a=0,c=e,l=o.length;l>a;++a)o[a].entry=c=!c;for(var s,f,h,g=i[0];;){for(s=g;s.visited;)if((s=s.next)===g)return;f=s.points,u.lineStart();do{if(s.visited=s.other.visited=!0,s.entry){if(s.subject)for(var a=0;a=0;)u.point((h=f[a])[0],h[1])}else r(s.point,s.prev.point,-1,u);s=s.prev}s=s.other,f=s.points}while(!s.visited);u.lineEnd()}}}function $t(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Wt))}}var g,p,d,v=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:l,polygonStart:function(){y.point=s,y.lineStart=f,y.lineEnd=h,g=[],p=[],i.polygonStart()},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=l,g=mo.merge(g);var n=Kt(m,p);g.length?Xt(g,Gt,n,e,i):n&&(i.lineStart(),e(null,null,1,i),i.lineEnd()),i.polygonEnd(),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},M=Jt(),x=t(M);return y}}function Wt(n){return n.length>1}function Jt(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:c,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Gt(n,t){return((n=n.point)[0]<0?n[1]-Jo-Go:Jo-n[1])-((t=t.point)[0]<0?t[1]-Jo-Go:Jo-t[1])}function Kt(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;La.reset();for(var a=0,c=t.length;c>a;++a){var l=t[a],s=l.length;if(s)for(var f=l[0],h=f[0],g=f[1]/2+Bo/4,p=Math.sin(g),d=Math.cos(g),v=1;;){v===s&&(v=0),n=l[v];var m=n[0],y=n[1]/2+Bo/4,M=Math.sin(y),x=Math.cos(y),b=m-h,_=Math.abs(b)>Bo,w=p*M;if(La.add(Math.atan2(w*Math.sin(b),d*x+w*Math.cos(b))),i+=_?b+(b>=0?2:-2)*Bo:b,_^h>=e^m>=e){var S=jt(Ct(f),Ct(n));Ft(S);var E=jt(u,S);Ft(E);var k=(_^b>=0?-1:1)*O(E[2]);(r>k||r===k&&(S[0]||S[1]))&&(o+=_^b>=0?1:-1)}if(!v++)break;h=m,p=M,d=x,f=n}}return(-Go>i||Go>i&&0>La)^1&o}function Qt(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?Bo:-Bo,c=Math.abs(i-e);Math.abs(c-Bo)0?Jo:-Jo),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=Bo&&(Math.abs(e-u)Go?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function te(n,t,e,r){var u;if(null==n)u=e*Jo,r.point(-Bo,u),r.point(0,u),r.point(Bo,u),r.point(Bo,0),r.point(Bo,-u),r.point(0,-u),r.point(-Bo,-u),r.point(-Bo,0),r.point(-Bo,u);else if(Math.abs(n[0]-t[0])>Go){var i=(n[0]i}function e(n){var e,i,c,l,s;return{lineStart:function(){l=c=!1,s=1},point:function(f,h){var g,p=[f,h],d=t(f,h),v=o?d?0:u(f,h):d?u(f+(0>f?Bo:-Bo),h):0;if(!e&&(l=c=d)&&n.lineStart(),d!==c&&(g=r(e,p),(Ot(e,g)||Ot(p,g))&&(p[0]+=Go,p[1]+=Go,d=t(p[0],p[1]))),d!==c)s=0,d?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^d){var m;v&i||!(m=r(p,e,!0))||(s=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!d||e&&Ot(e,p)||n.point(p[0],p[1]),e=p,c=d,i=v},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return s|(l&&c)<<1}}}function r(n,t,e){var r=Ct(n),u=Ct(t),o=[1,0,0],a=jt(r,u),c=Dt(a,a),l=a[0],s=c-l*l;if(!s)return!e&&n;var f=i*c/s,h=-i*l/s,g=jt(o,a),p=Ht(o,f),d=Ht(a,h);Lt(p,d);var v=g,m=Dt(p,v),y=Dt(v,v),M=m*m-y*(Dt(p,p)-1);if(!(0>M)){var x=Math.sqrt(M),b=Ht(v,(-m-x)/y);if(Lt(b,p),b=Pt(b),!e)return b;var _,w=n[0],S=t[0],E=n[1],k=t[1];w>S&&(_=w,w=S,S=_);var A=S-w,N=Math.abs(A-Bo)A;if(!N&&E>k&&(_=E,E=k,k=_),T?N?E+k>0^b[1]<(Math.abs(b[0]-w)Bo^(w<=b[0]&&b[0]<=S)){var q=Ht(v,(-m+x)/y);return Lt(q,p),[b,Pt(q)]}}}function u(t,e){var r=o?n:Bo-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=Math.abs(i)>Go,c=Te(n,6*Qo);return Bt(t,e,c,o?[0,-n]:[-Bo,n-Bo])}function re(n,t,e,r){function u(r,u){return Math.abs(r[0]-n)0?0:3:Math.abs(r[0]-e)0?2:1:Math.abs(r[1]-t)0?1:0:u>0?3:2}function i(n,t){return o(n.point,t.point)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}function a(u,i){var o=i[0]-u[0],a=i[1]-u[1],c=[0,1];return Math.abs(o)0&&(u[0]+=c[0]*o,u[1]+=c[0]*a),!0):!1}return function(c){function l(n){for(var t=0,e=y.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=y[u],c=a.length,l=a[0];c>o;++o)i=a[o],l[1]<=r?i[1]>r&&s(l,i,n)>0&&++t:i[1]<=r&&s(l,i,n)<0&&--t,l=i;return 0!==t}function s(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(e[0]-n[0])*(t[1]-n[1])}function f(i,a,c,l){var s=0,f=0;if(null==i||(s=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do l.point(0===s||3===s?n:e,s>1?r:t);while((s=(s+c+4)%4)!==f)}else l.point(a[0],a[1])}function h(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function g(n,t){h(n,t)&&c.point(n,t)}function p(){q.point=v,y&&y.push(M=[]),k=!0,E=!1,w=S=0/0}function d(){m&&(v(x,b),_&&E&&T.rejoin(),m.push(T.buffer())),q.point=g,E&&c.lineEnd()}function v(n,t){n=Math.max(-Ja,Math.min(Ja,n)),t=Math.max(-Ja,Math.min(Ja,t));var e=h(n,t);if(y&&M.push([n,t]),k)x=n,b=t,_=e,k=!1,e&&(c.lineStart(),c.point(n,t));else if(e&&E)c.point(n,t);else{var r=[w,S],u=[n,t];a(r,u)?(E||(c.lineStart(),c.point(r[0],r[1])),c.point(u[0],u[1]),e||c.lineEnd(),A=!1):e&&(c.lineStart(),c.point(n,t),A=!1)}w=n,S=t,E=e}var m,y,M,x,b,_,w,S,E,k,A,N=c,T=Jt(),q={point:g,lineStart:p,lineEnd:d,polygonStart:function(){c=T,m=[],y=[],A=!0},polygonEnd:function(){c=N,m=mo.merge(m);var t=l([n,r]),e=A&&t,u=m.length;(e||u)&&(c.polygonStart(),e&&(c.lineStart(),f(null,null,1,c),c.lineEnd()),u&&Xt(m,i,t,f,c),c.polygonEnd()),m=y=M=null}};return q}}function ue(n,t,e){if(Math.abs(t)=n;var r=n/t;if(t>0){if(r>e[1])return!1;r>e[0]&&(e[0]=r)}else{if(rn&&(Qa=n),n>tc&&(tc=n),nc>t&&(nc=t),t>ec&&(ec=t)}function se(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=fe(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=fe(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function fe(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function he(n,t){Oa+=n,Ra+=t,++Ya}function ge(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);Ia+=o*(t+n)/2,Ua+=o*(e+r)/2,Za+=o,he(t=n,e=r)}var t,e;ic.point=function(r,u){ic.point=n,he(t=r,e=u)}}function pe(){ic.point=he}function de(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);Ia+=o*(r+n)/2,Ua+=o*(u+t)/2,Za+=o,o=u*n-r*t,Va+=o*(r+n),Xa+=o*(u+t),$a+=3*o,he(r=n,u=t)}var t,e,r,u;ic.point=function(i,o){ic.point=n,he(t=r=i,e=u=o)},ic.lineEnd=function(){n(t,e)}}function ve(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,Wo)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:c};return a}function me(n){function t(t){function r(e,r){e=n(e,r),t.point(e[0],e[1])}function u(){M=0/0,S.point=o,t.lineStart()}function o(r,u){var o=Ct([r,u]),a=n(r,u);e(M,x,y,b,_,w,M=a[0],x=a[1],y=r,b=o[0],_=o[1],w=o[2],i,t),t.point(M,x)}function a(){S.point=r,t.lineEnd()}function c(){u(),S.point=l,S.lineEnd=s}function l(n,t){o(f=n,h=t),g=M,p=x,d=b,v=_,m=w,S.point=o}function s(){e(M,x,y,b,_,w,g,p,f,d,v,m,i,t),S.lineEnd=a,a()}var f,h,g,p,d,v,m,y,M,x,b,_,w,S={point:r,lineStart:u,lineEnd:a,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=u}};return S}function e(t,i,o,a,c,l,s,f,h,g,p,d,v,m){var y=s-t,M=f-i,x=y*y+M*M;if(x>4*r&&v--){var b=a+g,_=c+p,w=l+d,S=Math.sqrt(b*b+_*_+w*w),E=Math.asin(w/=S),k=Math.abs(Math.abs(w)-1)r||Math.abs((y*q+M*z)/x-.5)>.3||u>a*g+c*p+l*d)&&(e(t,i,o,a,c,l,N,T,k,b/=S,_/=S,w,v,m),m.point(N,T),e(N,T,k,b,_,w,s,f,h,g,p,d,v,m))}}var r=.5,u=Math.cos(30*Qo),i=16;return t.precision=function(n){return arguments.length?(i=(r=n*n)>0&&16,t):Math.sqrt(r)},t}function ye(n){this.stream=n}function Me(n){var t=me(function(t,e){return n([t*na,e*na])});return function(n){var e=new ye(n=t(n));return e.point=function(t,e){n.point(t*Qo,e*Qo)},e}}function xe(n){return be(function(){return n})()}function be(n){function t(n){return n=a(n[0]*Qo,n[1]*Qo),[n[0]*h+c,l-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(l-n[1])/h),n&&[n[0]*na,n[1]*na]}function r(){a=ie(o=Ee(m,y,M),i);var n=i(d,v);return c=g-n[0]*h,l=p+n[1]*h,u()}function u(){return s&&(s.valid=!1,s=null),t}var i,o,a,c,l,s,f=me(function(n,t){return n=i(n,t),[n[0]*h+c,l-n[1]*h]}),h=150,g=480,p=250,d=0,v=0,m=0,y=0,M=0,x=Wa,b=dt,_=null,w=null;return t.stream=function(n){return s&&(s.valid=!1),s=_e(x(o,f(b(n)))),s.valid=!0,s},t.clipAngle=function(n){return arguments.length?(x=null==n?(_=n,Wa):ee((_=+n)*Qo),u()):_},t.clipExtent=function(n){return arguments.length?(w=n,b=n?re(n[0][0],n[0][1],n[1][0],n[1][1]):dt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(d=n[0]%360*Qo,v=n[1]%360*Qo,r()):[d*na,v*na]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Qo,y=n[1]%360*Qo,M=n.length>2?n[2]%360*Qo:0,r()):[m*na,y*na,M*na]},mo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function _e(n){var t=new ye(n);return t.point=function(t,e){n.point(t*Qo,e*Qo)},t}function we(n,t){return[n,t]}function Se(n,t){return[n>Bo?n-Wo:-Bo>n?n+Wo:n,t]}function Ee(n,t,e){return n?t||e?ie(Ae(n),Ne(t,e)):Ae(n):t||e?Ne(t,e):Se}function ke(n){return function(t,e){return t+=n,[t>Bo?t-Wo:-Bo>t?t+Wo:t,e]}}function Ae(n){var t=ke(n);return t.invert=ke(-n),t}function Ne(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*r+a*u;return[Math.atan2(c*i-s*o,a*r-l*u),O(s*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*i-c*o;return[Math.atan2(c*i+l*o,a*r+s*u),O(s*r-a*u)]},e}function Te(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=qe(e,u),i=qe(e,i),(o>0?i>u:u>i)&&(u+=o*Wo)):(u=n+o*Wo,i=n-.5*c);for(var l,s=u;o>0?s>i:i>s;s-=c)a.point((l=Pt([e,-r*Math.cos(s),-r*Math.sin(s)]))[0],l[1])}}function qe(n,t){var e=Ct(t);e[0]-=n,Ft(e);var r=P(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Go)%(2*Math.PI)}function ze(n,t,e){var r=mo.range(n,t-Go,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function Ce(n,t,e){var r=mo.range(n,t-Go,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function De(n){return n.source}function je(n){return n.target}function Le(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),l=u*Math.sin(n),s=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(U(r-t)+u*o*U(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*s,u=e*l+t*f,o=e*i+t*a;return[Math.atan2(u,r)*na,Math.atan2(o,Math.sqrt(r*r+u*u))*na]}:function(){return[n*na,t*na]};return p.distance=h,p}function He(){function n(n,u){var i=Math.sin(u*=Qo),o=Math.cos(u),a=Math.abs((n*=Qo)-t),c=Math.cos(a);oc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;ac.point=function(u,i){t=u*Qo,e=Math.sin(i*=Qo),r=Math.cos(i),ac.point=n},ac.lineEnd=function(){ac.point=ac.lineEnd=c}}function Fe(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function Pe(n,t){function e(n,t){var e=Math.abs(Math.abs(t)-Jo)1&&u.push("H",r[0]),u.join("")}function We(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var l=2;l9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function fr(n){return n.length<3?Xe(n):n[0]+nr(n,sr(n))}function hr(n,t,e,r){var u,i,o,a,c,l,s;return u=r[n],i=u[0],o=u[1],u=r[t],a=u[0],c=u[1],u=r[e],l=u[0],s=u[1],(s-o)*(a-i)-(c-o)*(l-i)>0}function gr(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function pr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],l=e[1],s=t[1]-c,f=r[1]-l,h=(a*(c-l)-f*(u-i))/(f*o-a*s);return[u+h*o,c+h*s]}function dr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function vr(n,t){var e={list:n.map(function(n,t){return{index:t,x:n[0],y:n[1]}}).sort(function(n,t){return n.yt.y?1:n.xt.x?1:0}),bottomSite:null},r={list:[],leftEnd:null,rightEnd:null,init:function(){r.leftEnd=r.createHalfEdge(null,"l"),r.rightEnd=r.createHalfEdge(null,"l"),r.leftEnd.r=r.rightEnd,r.rightEnd.l=r.leftEnd,r.list.unshift(r.leftEnd,r.rightEnd)},createHalfEdge:function(n,t){return{edge:n,side:t,vertex:null,l:null,r:null}},insert:function(n,t){t.l=n,t.r=n.r,n.r.l=t,n.r=t},leftBound:function(n){var t=r.leftEnd;do t=t.r;while(t!=r.rightEnd&&u.rightOf(t,n));return t=t.l},del:function(n){n.l.r=n.r,n.r.l=n.l,n.edge=null},right:function(n){return n.r},left:function(n){return n.l},leftRegion:function(n){return null==n.edge?e.bottomSite:n.edge.region[n.side]},rightRegion:function(n){return null==n.edge?e.bottomSite:n.edge.region[yc[n.side]]}},u={bisect:function(n,t){var e={region:{l:n,r:t},ep:{l:null,r:null}},r=t.x-n.x,u=t.y-n.y,i=r>0?r:-r,o=u>0?u:-u;return e.c=n.x*r+n.y*u+.5*(r*r+u*u),i>o?(e.a=1,e.b=u/r,e.c/=r):(e.b=1,e.a=r/u,e.c/=u),e},intersect:function(n,t){var e=n.edge,r=t.edge;if(!e||!r||e.region.r==r.region.r)return null;var u=e.a*r.b-e.b*r.a;if(Math.abs(u)<1e-10)return null;var i,o,a=(e.c*r.b-r.c*e.b)/u,c=(r.c*e.a-e.c*r.a)/u,l=e.region.r,s=r.region.r;l.y=o.region.r.x;return f&&"l"===i.side||!f&&"r"===i.side?null:{x:a,y:c}},rightOf:function(n,t){var e=n.edge,r=e.region.r,u=t.x>r.x;if(u&&"l"===n.side)return 1;if(!u&&"r"===n.side)return 0;if(1===e.a){var i=t.y-r.y,o=t.x-r.x,a=0,c=0;if(!u&&e.b<0||u&&e.b>=0?c=a=i>=e.b*o:(c=t.x+t.y*e.b>e.c,e.b<0&&(c=!c),c||(a=1)),!a){var l=r.x-e.region.l.x;c=e.b*(o*o-i*i)h*h+g*g}return"l"===n.side?c:!c},endPoint:function(n,e,r){n.ep[e]=r,n.ep[yc[e]]&&t(n)},distance:function(n,t){var e=n.x-t.x,r=n.y-t.y;return Math.sqrt(e*e+r*r)}},i={list:[],insert:function(n,t,e){n.vertex=t,n.ystar=t.y+e;for(var r=0,u=i.list,o=u.length;o>r;r++){var a=u[r];if(!(n.ystar>a.ystar||n.ystar==a.ystar&&t.x>a.vertex.x))break}u.splice(r,0,n)},del:function(n){for(var t=0,e=i.list,r=e.length;r>t&&e[t]!=n;++t);e.splice(t,1)},empty:function(){return 0===i.list.length},nextEvent:function(n){for(var t=0,e=i.list,r=e.length;r>t;++t)if(e[t]==n)return e[t+1];return null},min:function(){var n=i.list[0];return{x:n.vertex.x,y:n.ystar}},extractMin:function(){return i.list.shift()}};r.init(),e.bottomSite=e.list.shift();for(var o,a,c,l,s,f,h,g,p,d,v,m,y,M=e.list.shift();;)if(i.empty()||(o=i.min()),M&&(i.empty()||M.yg.y&&(p=h,h=g,g=p,y="r"),m=u.bisect(h,g),f=r.createHalfEdge(m,y),r.insert(l,f),u.endPoint(m,yc[y],v),d=u.intersect(l,f),d&&(i.del(l),i.insert(l,d,u.distance(d,h))),d=u.intersect(f,s),d&&i.insert(f,d,u.distance(d,h))}for(a=r.right(r.leftEnd);a!=r.rightEnd;a=r.right(a))t(a.edge)}function mr(n){return n.x}function yr(n){return n.y}function Mr(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function xr(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&&xr(n,c[0],e,r,o,a),c[1]&&xr(n,c[1],o,r,u,a),c[2]&&xr(n,c[2],e,a,o,i),c[3]&&xr(n,c[3],o,a,u,i)}}function br(n,t){n=mo.rgb(n),t=mo.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+ct(Math.round(e+i*n))+ct(Math.round(r+o*n))+ct(Math.round(u+a*n))}}function _r(n,t){var e,r={},u={};for(e in n)e in t?r[e]=Er(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function wr(n,t){return t-=n=+n,function(e){return n+t*e}}function Sr(n,t){var e,r,u,i,o,a=0,c=0,l=[],s=[];for(n+="",t+="",Mc.lastIndex=0,r=0;e=Mc.exec(t);++r)e.index&&l.push(t.substring(a,c=e.index)),s.push({i:l.length,x:e[0]}),l.push(null),a=Mc.lastIndex;for(ar;++r)if(o=s[r],o.x==e[0]){if(o.i)if(null==l[o.i+1])for(l[o.i-1]+=o.x,l.splice(o.i,1),u=r+1;i>u;++u)s[u].i--;else for(l[o.i-1]+=o.x+l[o.i+1],l.splice(o.i,2),u=r+1;i>u;++u)s[u].i-=2;else if(null==l[o.i+1])l[o.i]=o.x;else for(l[o.i]=o.x+l[o.i+1],l.splice(o.i+1,1),u=r+1;i>u;++u)s[u].i--;s.splice(r,1),i--,r--}else o.x=wr(parseFloat(e[0]),parseFloat(o.x));for(;i>r;)o=s.pop(),null==l[o.i+1]?l[o.i]=o.x:(l[o.i]=o.x+l[o.i+1],l.splice(o.i+1,1)),i--;return 1===l.length?null==l[0]?(o=s[0].x,function(n){return o(n)+""}):function(){return t}:function(n){for(r=0;i>r;++r)l[(o=s[r]).i]=o.x(n);return l.join("")}}function Er(n,t){for(var e,r=mo.interpolators.length;--r>=0&&!(e=mo.interpolators[r](n,t)););return e}function kr(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(Er(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function Ar(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function Nr(n){return function(t){return 1-n(1-t)}}function Tr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function qr(n){return n*n}function zr(n){return n*n*n}function Cr(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Dr(n){return function(t){return Math.pow(t,n)}}function jr(n){return 1-Math.cos(n*Jo)}function Lr(n){return Math.pow(2,10*(n-1))}function Hr(n){return 1-Math.sqrt(1-n*n)}function Fr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/Wo*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*Wo/t)}}function Pr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Or(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Rr(n,t){n=mo.hcl(n),t=mo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return J(e+i*n,r+o*n,u+a*n)+""}}function Yr(n,t){n=mo.hsl(n),t=mo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return $(e+i*n,r+o*n,u+a*n)+""}}function Ir(n,t){n=mo.lab(n),t=mo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return Q(e+i*n,r+o*n,u+a*n)+""}}function Ur(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Zr(n){var t=[n.a,n.b],e=[n.c,n.d],r=Xr(t),u=Vr(t,e),i=Xr($r(e,t,-u))||0;t[0]*e[1]180?s+=360:s-l>180&&(l+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:wr(l,s)})):s&&r.push(r.pop()+"rotate("+s+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:wr(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:wr(g[0],p[0])},{i:e-2,x:wr(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++ie;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function vu(n){return n.reduce(mu,0)}function mu(n,t){return n+t[1]}function yu(n,t){return Mu(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function Mu(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function xu(n){return[mo.min(n),mo.max(n)]}function bu(n,t){return n.parent==t.parent?1:2}function _u(n){var t=n.children;return t&&t.length?t[0]:n._tree.thread}function wu(n){var t,e=n.children;return e&&(t=e.length)?e[t-1]:n._tree.thread}function Su(n,t){var e=n.children;if(e&&(u=e.length))for(var r,u,i=-1;++i0&&(n=r);return n}function Eu(n,t){return n.x-t.x}function ku(n,t){return t.x-n.x}function Au(n,t){return n.depth-t.depth}function Nu(n,t){function e(n,r){var u=n.children;if(u&&(o=u.length))for(var i,o,a=null,c=-1;++c=0;)t=u[i]._tree,t.prelim+=e,t.mod+=e,e+=t.shift+(r+=t.change)}function qu(n,t,e){n=n._tree,t=t._tree;var r=e/(t.number-n.number);n.change+=r,t.change-=r,t.shift+=e,t.prelim+=e,t.mod+=e}function zu(n,t,e){return n._tree.ancestor.parent==t.parent?n._tree.ancestor:e}function Cu(n,t){return n.value-t.value}function Du(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function ju(n,t){n._pack_next=t,t._pack_prev=n}function Lu(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function Hu(n){function t(n){s=Math.min(n.x-n.r,s),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(l=e.length)){var e,r,u,i,o,a,c,l,s=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(Fu),r=e[0],r.x=-r.r,r.y=0,t(r),l>1&&(u=e[1],u.x=u.r,u.y=0,t(u),l>2))for(i=e[2],Ru(r,u,i),t(i),Du(r,i),r._pack_prev=i,Du(i,u),u=r._pack_next,o=3;l>o;o++){Ru(r,u,i=e[o]);var p=0,d=1,v=1;for(a=u._pack_next;a!==u;a=a._pack_next,d++)if(Lu(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!Lu(c,i);c=c._pack_prev,v++);p?(v>d||d==v&&u.ro;o++)i=e[o],i.x-=m,i.y-=y,M=Math.max(M,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=M,e.forEach(Pu)}}function Fu(n){n._pack_next=n._pack_prev=n}function Pu(n){delete n._pack_next,delete n._pack_prev}function Ou(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++iu&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function $u(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Bu(n){return n.rangeExtent?n.rangeExtent():$u(n.range())}function Wu(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Ju(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Gu(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:Tc}function Ku(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?Ku:Wu,c=r?Jr:Wr;return o=u(n,t,c,e),a=u(t,n,c,Er),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Ur)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return ri(n,t)},i.tickFormat=function(t,e){return ui(n,t,e)},i.nice=function(t){return ti(n,t),u()},i.copy=function(){return Qu(n,t,e,r)},u()}function ni(n,t){return mo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function ti(n,t){return Ju(n,Gu(ei(n,t)[2]))}function ei(n,t){null==t&&(t=10);var e=$u(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function ri(n,t){return mo.range.apply(mo,ei(n,t))}function ui(n,t,e){var r=-Math.floor(Math.log(ei(n,t)[2])/Math.LN10+.01);return mo.format(e?e.replace(Aa,function(n,t,e,u,i,o,a,c,l,s){return[t,e,u,i,o,a,c,l||"."+(r-2*("%"===s)),s].join("")}):",."+r+"f")}function ii(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Ju(r.map(u),e?Math:zc);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=$u(r),o=[],a=n[0],c=n[1],l=Math.floor(u(a)),s=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(s-l)){if(e){for(;s>l;l++)for(var h=1;f>h;h++)o.push(i(l)*h);o.push(i(l))}else for(o.push(i(l));l++0;h--)o.push(i(l)*h);for(l=0;o[l]c;s--);o=o.slice(l,s)}return o},o.tickFormat=function(n,t){if(!arguments.length)return qc;arguments.length<2?t=qc:"function"!=typeof t&&(t=mo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return ii(n.copy(),t,e,r)},ni(o,n)}function oi(n,t,e){function r(t){return n(u(t))}var u=ai(t),i=ai(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return ri(e,n)},r.tickFormat=function(n,t){return ui(e,n,t)},r.nice=function(n){return r.domain(ti(e,n))},r.exponent=function(o){return arguments.length?(u=ai(t=o),i=ai(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return oi(n.copy(),t,e)},ni(r,n)}function ai(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function ci(n,t){function e(e){return o[((i.get(e)||"range"===t.t&&i.set(e,n.push(e)))-1)%o.length]}function r(t,e){return mo.range(n.length).map(function(n){return t+e*n})}var i,o,a;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new u;for(var o,a=-1,c=r.length;++ae?[0/0,0/0]:[e>0?u[e-1]:n[0],et?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return si(n,t,e)},u()}function fi(n,t){function e(e){return e>=e?t[mo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return fi(n,t)},e}function hi(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return ri(n,t)},t.tickFormat=function(t,e){return ui(n,t,e)},t.copy=function(){return hi(n)},t}function gi(n){return n.innerRadius}function pi(n){return n.outerRadius}function di(n){return n.startAngle}function vi(n){return n.endAngle}function mi(n){for(var t,e,r,u=-1,i=n.length;++ue?l():(i.active=e,o.event&&o.event.start.call(n,s,t),o.tween.forEach(function(e,r){(r=r.call(n,s,t))&&p.push(r)}),c(r||1)?1:(xt(c,h,a),void 0))}function c(r){if(i.active!==e)return l();for(var u=r/g,a=f(u),c=p.length;c>0;)p[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,s,t),l()):void 0}function l(){return--i.count?delete i[e]:delete n.__transition__,1}var s=n.__data__,f=o.ease,h=o.delay,g=o.duration,p=[];return r>=h?u(r-h):(xt(u,h,a),void 0)},0,a)}}function Ti(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function qi(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function zi(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Ci(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new Jc(e-1)),1),e}function i(n,e){return t(n=new Jc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{Jc=zi;var r=new zi;return r._=n,o(r,t,e)}finally{Jc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Di(n);return c.floor=c,c.round=Di(r),c.ceil=Di(u),c.offset=Di(i),c.range=a,n}function Di(n){return function(t,e){try{Jc=zi;var r=new zi;return r._=t,n(r,e)._}finally{Jc=Date}}}function ji(n){function t(t){for(var r,u,i,o=[],a=-1,c=0;++aa;){if(r>=l)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=ml[o in dl?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function Hi(n){return new RegExp("^(?:"+n.map(mo.requote).join("|")+")","i")}function Fi(n){for(var t=new u,e=-1,r=n.length;++en?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Oi(n,t,e){cl.lastIndex=0;var r=cl.exec(t.substring(e));return r?(n.w=ll.get(r[0].toLowerCase()),e+r[0].length):-1}function Ri(n,t,e){ol.lastIndex=0;var r=ol.exec(t.substring(e));return r?(n.w=al.get(r[0].toLowerCase()),e+r[0].length):-1}function Yi(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Ii(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e));return r?(n.U=+r[0],e+r[0].length):-1}function Ui(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e));return r?(n.W=+r[0],e+r[0].length):-1}function Zi(n,t,e){hl.lastIndex=0;var r=hl.exec(t.substring(e));return r?(n.m=gl.get(r[0].toLowerCase()),e+r[0].length):-1}function Vi(n,t,e){sl.lastIndex=0;var r=sl.exec(t.substring(e));return r?(n.m=fl.get(r[0].toLowerCase()),e+r[0].length):-1}function Xi(n,t,e){return Li(n,vl.c.toString(),t,e)}function $i(n,t,e){return Li(n,vl.x.toString(),t,e)}function Bi(n,t,e){return Li(n,vl.X.toString(),t,e)}function Wi(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Ji(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+2));return r?(n.y=Ki(+r[0]),e+r[0].length):-1}function Gi(n,t,e){return/^[+-]\d{4}$/.test(t=t.substring(e,e+5))?(n.Z=+t,e+5):-1}function Ki(n){return n+(n>68?1900:2e3)}function Qi(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function no(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function to(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function eo(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function ro(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function uo(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function io(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function oo(n,t,e){var r=Ml.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}function ao(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(Math.abs(t)/60),u=Math.abs(t)%60;return e+Pi(r,"0",2)+Pi(u,"0",2)}function co(n,t,e){pl.lastIndex=0;var r=pl.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function lo(n){function t(n){try{Jc=zi;var t=new Jc;return t._=n,e(t)}finally{Jc=Date}}var e=ji(n);return t.parse=function(n){try{Jc=zi;var t=e.parse(n);return t&&t._}finally{Jc=Date}},t.toString=e.toString,t}function so(n){return n.toISOString()}function fo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=mo.bisect(bl,u);return i==bl.length?[t.year,ei(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/bl[i-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=ho(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=ho(+t+1);return t}}:n))},r.ticks=function(n,t){var e=$u(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],ho(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return fo(n.copy(),t,e)},ni(r,n)}function ho(n){return new Date(n)}function go(n){return function(t){for(var e=n.length-1,r=n[e];!r[1](t);)r=n[--e];return r[0](t)}}function po(n){return JSON.parse(n.responseText)}function vo(n){var t=xo.createRange();return t.selectNode(xo.body),t.createContextualFragment(n.responseText)}var mo={version:"3.3.6"};Date.now||(Date.now=function(){return+new Date});var yo=[].slice,Mo=function(n){return yo.call(n)},xo=document,bo=xo.documentElement,_o=window;try{Mo(bo.childNodes)[0].nodeType}catch(wo){Mo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{xo.createElement("div").style.setProperty("opacity",0,"")}catch(So){var Eo=_o.Element.prototype,ko=Eo.setAttribute,Ao=Eo.setAttributeNS,No=_o.CSSStyleDeclaration.prototype,To=No.setProperty;Eo.setAttribute=function(n,t){ko.call(this,n,t+"")},Eo.setAttributeNS=function(n,t,e){Ao.call(this,n,t,e+"")},No.setProperty=function(n,t,e){To.call(this,n,t+"",e)}}mo.ascending=function(n,t){return t>n?-1:n>t?1:n>=t?0:0/0},mo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},mo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=e);)e=void 0;for(;++ur&&(e=r)}else{for(;++u=e);)e=void 0;for(;++ur&&(e=r)}return e},mo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=e);)e=void 0;for(;++ue&&(e=r)}else{for(;++u=e);)e=void 0;for(;++ue&&(e=r)}return e},mo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i=e);)e=u=void 0;for(;++ir&&(e=r),r>u&&(u=r))}else{for(;++i=e);)e=void 0;for(;++ir&&(e=r),r>u&&(u=r))}return[e,u]},mo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i1&&(t=t.map(e)),t=t.filter(n),t.length?mo.quantile(t.sort(mo.ascending),.5):void 0},mo.bisector=function(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n.call(t,t[i],i)r;){var i=r+u>>>1;er?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},mo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,e=mo.min(arguments,t),r=new Array(e);++nr)for(;(u=n+r*++a)>t;)i.push(u/o);else for(;(u=n+r*++a)=o.length)return r?r.call(i,a):e?a.sort(e):a;for(var l,s,f,h,g=-1,p=a.length,d=o[c++],v=new u;++g=o.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,i={},o=[],a=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(mo.map,e,0),0)},i.key=function(n){return o.push(n),i},i.sortKeys=function(n){return a[o.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},mo.set=function(n){var t=new i;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},r(i,{has:function(n){return zo+n in this},add:function(n){return this[zo+n]=!0,n},remove:function(n){return n=zo+n,n in this&&delete this[n]},values:function(){var n=[];return this.forEach(function(t){n.push(t)}),n},forEach:function(n){for(var t in this)t.charCodeAt(0)===Co&&n.call(this,t.substring(1))}}),mo.behavior={},mo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},mo.event=null,mo.requote=function(n){return n.replace(jo,"\\$&")};var jo=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,Lo={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},Ho=function(n,t){return t.querySelector(n)},Fo=function(n,t){return t.querySelectorAll(n)},Po=bo[a(bo,"matchesSelector")],Oo=function(n,t){return Po.call(n,t)};"function"==typeof Sizzle&&(Ho=function(n,t){return Sizzle(n,t)[0]||null},Fo=function(n,t){return Sizzle.uniqueSort(Sizzle(n,t))},Oo=Sizzle.matchesSelector),mo.selection=function(){return Uo};var Ro=mo.selection.prototype=[];Ro.select=function(n){var t,e,r,u,i=[];n=d(n);for(var o=-1,a=this.length;++o=0&&(e=n.substring(0,t),n=n.substring(t+1)),Yo.hasOwnProperty(e)?{space:Yo[e],local:n}:n}},Ro.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=mo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(m(t,n[t]));return this}return this.each(m(n,t))},Ro.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=n.trim().split(/^|\s+/g)).length,u=-1;if(t=e.classList){for(;++ur){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(_(e,n[e],t));return this}if(2>r)return _o.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(_(n,t,e))},Ro.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(w(t,n[t]));return this}return this.each(w(n,t))},Ro.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},Ro.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},Ro.append=function(n){return n=S(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Ro.insert=function(n,t){return n=S(n),t=d(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments))})},Ro.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},Ro.data=function(n,t){function e(n,e){var r,i,o,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),d=new Array(a);if(t){var v,m=new u,y=new u,M=[];for(r=-1;++rr;++r)p[r]=E(e[r]);for(;a>r;++r)d[r]=n[r]}p.update=g,p.parentNode=g.parentNode=d.parentNode=n.parentNode,c.push(p),l.push(g),s.push(d)}var r,i,o=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++oi;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a)&&t.push(r)}return p(u)},Ro.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},Ro.sort=function(n){n=A.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},Ro.size=function(){var n=0;return this.each(function(){++n}),n};var Io=[];mo.selection.enter=T,mo.selection.enter.prototype=Io,Io.append=Ro.append,Io.empty=Ro.empty,Io.node=Ro.node,Io.call=Ro.call,Io.size=Ro.size,Io.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++ar){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(C(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(C(n,t,e))};var Zo=mo.map({mouseenter:"mouseover",mouseleave:"mouseout"});Zo.forEach(function(n){"on"+n in xo&&Zo.remove(n)});var Vo=a(bo.style,"userSelect"),Xo=0;mo.mouse=function(n){return H(n,h())};var $o=/WebKit/.test(_o.navigator.userAgent)?-1:0;mo.touches=function(n,t){return arguments.length<2&&(t=h().touches),t?Mo(t).map(function(t){var e=H(n,t);return e.identifier=t.identifier,e}):[]},mo.behavior.drag=function(){function n(){this.on("mousedown.drag",o).on("touchstart.drag",a)}function t(){return mo.event.changedTouches[0].identifier}function e(n,t){return mo.touches(n).filter(function(n){return n.identifier===t})[0]}function r(n,t,e,r){return function(){function o(){var n=t(s,g),e=n[0]-d[0],r=n[1]-d[1];v|=e|r,d=n,f({type:"drag",x:n[0]+c[0],y:n[1]+c[1],dx:e,dy:r})}function a(){m.on(e+"."+p,null).on(r+"."+p,null),y(v&&mo.event.target===h),f({type:"dragend"})}var c,l=this,s=l.parentNode,f=u.of(l,arguments),h=mo.event.target,g=n(),p=null==g?"drag":"drag-"+g,d=t(s,g),v=0,m=mo.select(_o).on(e+"."+p,o).on(r+"."+p,a),y=L();i?(c=i.apply(l,arguments),c=[c.x-d[0],c.y-d[1]]):c=[0,0],f({type:"dragstart"})}}var u=g(n,"drag","dragstart","dragend"),i=null,o=r(c,mo.mouse,"mousemove","mouseup"),a=r(t,e,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},mo.rebind(n,u,"on")};var Bo=Math.PI,Wo=2*Bo,Jo=Bo/2,Go=1e-6,Ko=Go*Go,Qo=Bo/180,na=180/Bo,ta=Math.SQRT2,ea=2,ra=4;mo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=Y(d),o=i/(ea*h)*(e*I(ta*t+d)-R(d));return[r+o*l,u+o*s,i*e/Y(ta*t+d)]}return[r+n*l,u+n*s,i*Math.exp(ta*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],l=o-r,s=a-u,f=l*l+s*s,h=Math.sqrt(f),g=(c*c-i*i+ra*f)/(2*i*ea*h),p=(c*c-i*i-ra*f)/(2*c*ea*h),d=Math.log(Math.sqrt(g*g+1)-g),v=Math.log(Math.sqrt(p*p+1)-p),m=v-d,y=(m||Math.log(c/i))/ta;return e.duration=1e3*y,e},mo.behavior.zoom=function(){function n(n){n.on(A,l).on(oa+".zoom",h).on(N,p).on("dblclick.zoom",d).on(q,s)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(k[0],Math.min(k[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){b&&b.domain(x.range().map(function(n){return(n-S.x)/S.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-S.y)/S.k}).map(_.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function l(){function n(){s=1,u(mo.mouse(r),h),a(i)}function e(){f.on(N,_o===r?p:null).on(T,null),g(s&&mo.event.target===l),c(i)}var r=this,i=C.of(r,arguments),l=mo.event.target,s=0,f=mo.select(_o).on(N,n).on(T,e),h=t(mo.mouse(r)),g=L();z.call(r),o(i)}function s(){function n(){var n=mo.touches(p);return g=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){for(var t=mo.event.changedTouches,e=0,i=t.length;i>e;++e)v[t[e].identifier]=null;var o=n(),c=Date.now();if(1===o.length){if(500>c-M){var l=o[0],s=v[l.identifier];r(2*S.k),u(l,s),f(),a(d)}M=c}else if(o.length>1){var l=o[0],h=o[1],g=l[0]-h[0],p=l[1]-h[1];m=g*g+p*p}}function i(){for(var n,t,e,i,o=mo.touches(p),c=0,l=o.length;l>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var s=(s=e[0]-n[0])*s+(s=e[1]-n[1])*s,f=m&&Math.sqrt(s/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*g)}M=null,u(n,t),a(d)}function h(){if(mo.event.touches.length){for(var t=mo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}_.on(x,null).on(b,null),w.on(A,l).on(q,s),E(),c(d)}var g,p=this,d=C.of(p,arguments),v={},m=0,y=mo.event.changedTouches[0].identifier,x="touchmove.zoom-"+y,b="touchend.zoom-"+y,_=mo.select(_o).on(x,i).on(b,h),w=mo.select(p).on(A,null).on(q,e),E=L();z.call(p),e(),o(d)}function h(){var n=C.of(this,arguments);y?clearTimeout(y):(z.call(this),o(n)),y=setTimeout(function(){y=null,c(n)},50),f();var e=m||mo.mouse(this);v||(v=t(e)),r(Math.pow(2,.002*ua())*S.k),u(e,v),a(n)}function p(){v=null}function d(){var n=C.of(this,arguments),e=mo.mouse(this),i=t(e),l=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,mo.event.shiftKey?Math.ceil(l)-1:Math.floor(l)+1)),u(e,i),a(n),c(n)}var v,m,y,M,x,b,_,w,S={x:0,y:0,k:1},E=[960,500],k=ia,A="mousedown.zoom",N="mousemove.zoom",T="mouseup.zoom",q="touchstart.zoom",C=g(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=C.of(this,arguments),t=S;Oc?mo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=E[0],r=E[1],u=e/2,i=r/2,o=mo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(k=null==t?ia:[+t[0],+t[1]],n):k},n.center=function(t){return arguments.length?(m=t&&[+t[0],+t[1]],n):m},n.size=function(t){return arguments.length?(E=t&&[+t[0],+t[1]],n):E},n.x=function(t){return arguments.length?(b=t,x=t.copy(),S={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),S={x:0,y:0,k:1},n):w},mo.rebind(n,C,"on")};var ua,ia=[0,1/0],oa="onwheel"in xo?(ua=function(){return-mo.event.deltaY*(mo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in xo?(ua=function(){return mo.event.wheelDelta},"mousewheel"):(ua=function(){return-mo.event.detail},"MozMousePixelScroll");Z.prototype.toString=function(){return this.rgb()+""},mo.hsl=function(n,t,e){return 1===arguments.length?n instanceof X?V(n.h,n.s,n.l):lt(""+n,st,V):V(+n,+t,+e)};var aa=X.prototype=new Z;aa.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),V(this.h,this.s,this.l/n)},aa.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),V(this.h,this.s,n*this.l)},aa.rgb=function(){return $(this.h,this.s,this.l)},mo.hcl=function(n,t,e){return 1===arguments.length?n instanceof W?B(n.h,n.c,n.l):n instanceof K?nt(n.l,n.a,n.b):nt((n=ft((n=mo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):B(+n,+t,+e)};var ca=W.prototype=new Z;ca.brighter=function(n){return B(this.h,this.c,Math.min(100,this.l+la*(arguments.length?n:1)))},ca.darker=function(n){return B(this.h,this.c,Math.max(0,this.l-la*(arguments.length?n:1)))},ca.rgb=function(){return J(this.h,this.c,this.l).rgb()},mo.lab=function(n,t,e){return 1===arguments.length?n instanceof K?G(n.l,n.a,n.b):n instanceof W?J(n.l,n.c,n.h):ft((n=mo.rgb(n)).r,n.g,n.b):G(+n,+t,+e)};var la=18,sa=.95047,fa=1,ha=1.08883,ga=K.prototype=new Z;ga.brighter=function(n){return G(Math.min(100,this.l+la*(arguments.length?n:1)),this.a,this.b)},ga.darker=function(n){return G(Math.max(0,this.l-la*(arguments.length?n:1)),this.a,this.b)},ga.rgb=function(){return Q(this.l,this.a,this.b)},mo.rgb=function(n,t,e){return 1===arguments.length?n instanceof at?ot(n.r,n.g,n.b):lt(""+n,ot,$):ot(~~n,~~t,~~e)};var pa=at.prototype=new Z;pa.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),ot(Math.min(255,~~(t/n)),Math.min(255,~~(e/n)),Math.min(255,~~(r/n)))):ot(u,u,u)},pa.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),ot(~~(n*this.r),~~(n*this.g),~~(n*this.b))},pa.hsl=function(){return st(this.r,this.g,this.b)},pa.toString=function(){return"#"+ct(this.r)+ct(this.g)+ct(this.b)};var da=mo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});da.forEach(function(n,t){da.set(n,ut(t))}),mo.functor=pt,mo.xhr=vt(dt),mo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=mo.xhr(n,t,i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o.row(e)}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function o(t){return t.map(a).join(n)}function a(n){return c.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var c=new RegExp('["'+n+"\n]"),l=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(s>=c)return o;if(u)return u=!1,i;var t=s;if(34===n.charCodeAt(t)){for(var e=t;e++s;){var r=n.charCodeAt(s++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(s)&&(++s,++a);else if(r!==l)continue;return n.substring(t,s-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],c=n.length,s=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new i,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(a).join(n)].concat(t.map(function(t){return u.map(function(n){return a(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(o).join("\n")},e},mo.csv=mo.dsv(",","text/csv"),mo.tsv=mo.dsv(" ","text/tab-separated-values");var va,ma,ya,Ma,xa,ba=_o[a(_o,"requestAnimationFrame")]||function(n){setTimeout(n,17)};mo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={callback:n,time:u,next:null};ma?ma.next=i:va=i,ma=i,ya||(Ma=clearTimeout(Ma),ya=1,ba(Mt))},mo.timer.flush=function(){bt(),_t()};var _a=".",wa=",",Sa=[3,3],Ea="$",ka=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(wt);mo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=mo.round(n,St(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),ka[8+e/3]},mo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)},mo.format=function(n){var t=Aa.exec(n),e=t[1]||" ",r=t[2]||">",u=t[3]||"",i=t[4]||"",o=t[5],a=+t[6],c=t[7],l=t[8],s=t[9],f=1,h="",g=!1;switch(l&&(l=+l.substring(1)),(o||"0"===e&&"="===r)&&(o=e="0",r="=",c&&(a-=Math.floor((a-1)/4))),s){case"n":c=!0,s="g";break;case"%":f=100,h="%",s="f";break;case"p":f=100,h="%",s="r";break;case"b":case"o":case"x":case"X":"#"===i&&(i="0"+s.toLowerCase());case"c":case"d":g=!0,l=0;break;case"s":f=-1,s="r"}"#"===i?i="":"$"===i&&(i=Ea),"r"!=s||l||(s="g"),null!=l&&("g"==s?l=Math.max(1,Math.min(21,l)):("e"==s||"f"==s)&&(l=Math.max(0,Math.min(20,l)))),s=Na.get(s)||Et;var p=o&&c;return function(n){if(g&&n%1)return"";var t=0>n||0===n&&0>1/n?(n=-n,"-"):u;if(0>f){var d=mo.formatPrefix(n,l);n=d.scale(n),h=d.symbol}else n*=f;n=s(n,l);var v=n.lastIndexOf("."),m=0>v?n:n.substring(0,v),y=0>v?"":_a+n.substring(v+1);!o&&c&&(m=Ta(m));var M=i.length+m.length+y.length+(p?0:t.length),x=a>M?new Array(M=a-M+1).join(e):"";return p&&(m=Ta(x+m)),t+=i,n=m+y,("<"===r?t+n+x:">"===r?x+t+n:"^"===r?x.substring(0,M>>=1)+t+n+x.substring(M):t+(p?n:x+n))+h}};var Aa=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,Na=mo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=mo.round(n,St(n,t))).toFixed(Math.max(0,Math.min(20,St(n*(1+1e-15),t))))}}),Ta=dt;if(Sa){var qa=Sa.length;Ta=function(n){for(var t=n.length,e=[],r=0,u=Sa[0];t>0&&u>0;)e.push(n.substring(t-=u,t+u)),u=Sa[r=(r+1)%qa];return e.reverse().join(wa)}}mo.geo={},kt.prototype={s:0,t:0,add:function(n){At(n,this.t,za),At(za.s,this.s,this),this.s?this.t+=za.t:this.s=za.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var za=new kt;mo.geo.stream=function(n,t){n&&Ca.hasOwnProperty(n.type)?Ca[n.type](n,t):Nt(n,t)};var Ca={Feature:function(n,t){Nt(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++rn?4*Bo+n:n,Ha.lineStart=Ha.lineEnd=Ha.point=c}};mo.geo.bounds=function(){function n(n,t){M.push(x=[s=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=Ct([t*Qo,e*Qo]);if(m){var u=jt(m,r),i=[u[1],-u[0],0],o=jt(i,u);Ft(o),o=Pt(o);var c=t-p,l=c>0?1:-1,d=o[0]*na*l,v=Math.abs(c)>180;if(v^(d>l*p&&l*t>d)){var y=o[1]*na;y>g&&(g=y)}else if(d=(d+360)%360-180,v^(d>l*p&&l*t>d)){var y=-o[1]*na;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);v?p>t?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t):h>=s?(s>t&&(s=t),t>h&&(h=t)):t>p?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t)}else n(t,e);m=r,p=t}function e(){b.point=t}function r(){x[0]=s,x[1]=h,b.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=Math.abs(r)>180?r+(r>0?360:-360):r}else d=n,v=e;Ha.point(n,e),t(n,e)}function i(){Ha.lineStart()}function o(){u(d,v),Ha.lineEnd(),Math.abs(y)>Go&&(s=-(h=180)),x[0]=s,x[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function l(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nLa?(s=-(h=180),f=-(g=90)):y>Go?g=90:-Go>y&&(f=-90),x[0]=s,x[1]=h}};return function(n){g=h=-(s=f=1/0),M=[],mo.geo.stream(n,b);var t=M.length;if(t){M.sort(c);for(var e,r=1,u=M[0],i=[u];t>r;++r)e=M[r],l(e[0],u)||l(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,s=e[0],h=u[1])}return M=x=null,1/0===s||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[s,f],[h,g]]}}(),mo.geo.centroid=function(n){Fa=Pa=Oa=Ra=Ya=Ia=Ua=Za=Va=Xa=$a=0,mo.geo.stream(n,Ba);var t=Va,e=Xa,r=$a,u=t*t+e*e+r*r;return Ko>u&&(t=Ia,e=Ua,r=Za,Go>Pa&&(t=Oa,e=Ra,r=Ya),u=t*t+e*e+r*r,Ko>u)?[0/0,0/0]:[Math.atan2(e,t)*na,O(r/Math.sqrt(u))*na]};var Fa,Pa,Oa,Ra,Ya,Ia,Ua,Za,Va,Xa,$a,Ba={sphere:c,point:Rt,lineStart:It,lineEnd:Ut,polygonStart:function(){Ba.lineStart=Zt},polygonEnd:function(){Ba.lineStart=It}},Wa=Bt(Vt,Qt,te,[-Bo,-Bo/2]),Ja=1e9;mo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=re(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(mo.geo.conicEqualArea=function(){return oe(ae)}).raw=ae,mo.geo.albers=function(){return mo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},mo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=mo.geo.albers(),o=mo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=mo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var l=i.scale(),s=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[s-.455*l,f-.238*l],[s+.455*l,f+.238*l]]).stream(c).point,r=o.translate([s-.307*l,f+.201*l]).clipExtent([[s-.425*l+Go,f+.12*l+Go],[s-.214*l-Go,f+.234*l-Go]]).stream(c).point,u=a.translate([s-.205*l,f+.212*l]).clipExtent([[s-.214*l+Go,f+.166*l+Go],[s-.115*l-Go,f+.234*l-Go]]).stream(c).point,n},n.scale(1070)};var Ga,Ka,Qa,nc,tc,ec,rc={point:c,lineStart:c,lineEnd:c,polygonStart:function(){Ka=0,rc.lineStart=ce},polygonEnd:function(){rc.lineStart=rc.lineEnd=rc.point=c,Ga+=Math.abs(Ka/2)}},uc={point:le,lineStart:c,lineEnd:c,polygonStart:c,polygonEnd:c},ic={point:he,lineStart:ge,lineEnd:pe,polygonStart:function(){ic.lineStart=de},polygonEnd:function(){ic.point=he,ic.lineStart=ge,ic.lineEnd=pe}};mo.geo.transform=function(n){return{stream:function(t){var e=new ye(t);for(var r in n)e[r]=n[r];return e}}},ye.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},mo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),mo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Ga=0,mo.geo.stream(n,u(rc)),Ga},n.centroid=function(n){return Oa=Ra=Ya=Ia=Ua=Za=Va=Xa=$a=0,mo.geo.stream(n,u(ic)),$a?[Va/$a,Xa/$a]:Za?[Ia/Za,Ua/Za]:Ya?[Oa/Ya,Ra/Ya]:[0/0,0/0]},n.bounds=function(n){return tc=ec=-(Qa=nc=1/0),mo.geo.stream(n,u(uc)),[[Qa,nc],[tc,ec]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Me(n):dt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new se:new ve(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(mo.geo.albersUsa()).context(null)},mo.geo.projection=xe,mo.geo.projectionMutator=be,(mo.geo.equirectangular=function(){return xe(we)}).raw=we.invert=we,mo.geo.rotation=function(n){function t(t){return t=n(t[0]*Qo,t[1]*Qo),t[0]*=na,t[1]*=na,t}return n=Ee(n[0]%360*Qo,n[1]*Qo,n.length>2?n[2]*Qo:0),t.invert=function(t){return t=n.invert(t[0]*Qo,t[1]*Qo),t[0]*=na,t[1]*=na,t},t},Se.invert=we,mo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=Ee(-n[0]*Qo,-n[1]*Qo,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=na,n[1]*=na}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=Te((t=+r)*Qo,u*Qo),n):t},n.precision=function(r){return arguments.length?(e=Te(t*Qo,(u=+r)*Qo),n):u},n.angle(90)},mo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Qo,u=n[1]*Qo,i=t[1]*Qo,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),l=Math.cos(u),s=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=l*s-c*f*a)*e),c*s+l*f*a)},mo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return mo.range(Math.ceil(i/v)*v,u,v).map(h).concat(mo.range(Math.ceil(l/m)*m,c,m).map(g)).concat(mo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return Math.abs(n%v)>Go -}).map(s)).concat(mo.range(Math.ceil(a/d)*d,o,d).filter(function(n){return Math.abs(n%m)>Go}).map(f))}var e,r,u,i,o,a,c,l,s,f,h,g,p=10,d=p,v=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(l).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],l=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),l>c&&(t=l,l=c,c=t),n.precision(y)):[[i,l],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(v=+t[0],m=+t[1],n):[v,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],d=+t[1],n):[p,d]},n.precision=function(t){return arguments.length?(y=+t,s=ze(a,o,90),f=Ce(r,e,y),h=ze(l,c,90),g=Ce(i,u,y),n):y},n.majorExtent([[-180,-90+Go],[180,90-Go]]).minorExtent([[-180,-80-Go],[180,80+Go]])},mo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=De,u=je;return n.distance=function(){return mo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},mo.geo.interpolate=function(n,t){return Le(n[0]*Qo,n[1]*Qo,t[0]*Qo,t[1]*Qo)},mo.geo.length=function(n){return oc=0,mo.geo.stream(n,ac),oc};var oc,ac={sphere:c,point:c,lineStart:He,lineEnd:c,polygonStart:c,polygonEnd:c},cc=Fe(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(mo.geo.azimuthalEqualArea=function(){return xe(cc)}).raw=cc;var lc=Fe(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},dt);(mo.geo.azimuthalEquidistant=function(){return xe(lc)}).raw=lc,(mo.geo.conicConformal=function(){return oe(Pe)}).raw=Pe,(mo.geo.conicEquidistant=function(){return oe(Oe)}).raw=Oe;var sc=Fe(function(n){return 1/n},Math.atan);(mo.geo.gnomonic=function(){return xe(sc)}).raw=sc,Re.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Jo]},(mo.geo.mercator=function(){return Ye(Re)}).raw=Re;var fc=Fe(function(){return 1},Math.asin);(mo.geo.orthographic=function(){return xe(fc)}).raw=fc;var hc=Fe(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(mo.geo.stereographic=function(){return xe(hc)}).raw=hc,Ie.invert=function(n,t){return[Math.atan2(R(n),Math.cos(t)),O(Math.sin(t)/Y(n))]},(mo.geo.transverseMercator=function(){return Ye(Ie)}).raw=Ie,mo.geom={},mo.svg={},mo.svg.line=function(){return Ue(dt)};var gc=mo.map({linear:Xe,"linear-closed":$e,step:Be,"step-before":We,"step-after":Je,basis:er,"basis-open":rr,"basis-closed":ur,bundle:ir,cardinal:Qe,"cardinal-open":Ge,"cardinal-closed":Ke,monotone:fr});gc.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var pc=[0,2/3,1/3,0],dc=[0,1/3,2/3,0],vc=[0,1/6,2/3,1/6];mo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u,i,o,a,c,l,s,f,h,g,p,d=pt(e),v=pt(r),m=n.length,y=m-1,M=[],x=[],b=0;if(d===Ze&&r===Ve)t=n;else for(i=0,t=[];m>i;++i)t.push([+d.call(this,u=n[i],i),+v.call(this,u,i)]);for(i=1;m>i;++i)(t[i][1]i;++i)i!==b&&(c=t[i][1]-t[b][1],a=t[i][0]-t[b][0],M.push({angle:Math.atan2(c,a),index:i}));for(M.sort(function(n,t){return n.angle-t.angle}),g=M[0].angle,h=M[0].index,f=0,i=1;y>i;++i){if(o=M[i].index,g==M[i].angle){if(a=t[h][0]-t[b][0],c=t[h][1]-t[b][1],l=t[o][0]-t[b][0],s=t[o][1]-t[b][1],a*a+c*c>=l*l+s*s){M[i].index=-1;continue}M[f].index=-1}g=M[i].angle,f=i,h=o}for(x.push(b),i=0,o=0;2>i;++o)M[o].index>-1&&(x.push(M[o].index),i++);for(p=x.length;y>o;++o)if(!(M[o].index<0)){for(;!hr(x[p-2],x[p-1],M[o].index,t);)--p;x[p++]=M[o].index}var _=[];for(i=p-1;i>=0;--i)_.push(n[x[i]]);return _}var e=Ze,r=Ve;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},mo.geom.polygon=function(n){return Lo(n,mc),n};var mc=mo.geom.polygon.prototype=[];mc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++ta;a++)e.push([u,t[a],t[a+1]])}),e},mo.geom.voronoi=function(n){function t(n){var t,i,o,a=n.map(function(){return[]}),c=pt(e),l=pt(r),s=n.length,f=1e6;if(c===Ze&&l===Ve)t=n;else for(t=new Array(s),o=0;s>o;++o)t[o]=[+c.call(this,i=n[o],o),+l.call(this,i,o)];if(vr(t,function(n){var t,e,r,u,i,o;1===n.a&&n.b>=0?(t=n.ep.r,e=n.ep.l):(t=n.ep.l,e=n.ep.r),1===n.a?(i=t?t.y:-f,r=n.c-n.b*i,o=e?e.y:f,u=n.c-n.b*o):(r=t?t.x:-f,i=n.c-n.a*r,u=e?e.x:f,o=n.c-n.a*u);var c=[r,i],l=[u,o];a[n.region.l.index].push(c,l),a[n.region.r.index].push(c,l)}),a=a.map(function(n,e){var r=t[e][0],u=t[e][1],i=n.map(function(n){return Math.atan2(n[0]-r,n[1]-u)}),o=mo.range(n.length).sort(function(n,t){return i[n]-i[t]});return o.filter(function(n,t){return!t||i[n]-i[o[t-1]]>Go}).map(function(t){return n[t]})}),a.forEach(function(n,e){var r=n.length;if(!r)return n.push([-f,-f],[-f,f],[f,f],[f,-f]);if(!(r>2)){var u=t[e],i=n[0],o=n[1],a=u[0],c=u[1],l=i[0],s=i[1],h=o[0],g=o[1],p=Math.abs(h-l),d=g-s;if(Math.abs(d)c?-f:f;n.push([-f,v],[f,v])}else if(Go>p){var m=l>a?-f:f;n.push([m,-f],[m,f])}else{var v=(l-a)*(g-s)>(h-l)*(s-c)?f:-f,y=Math.abs(d)-p;Math.abs(y)d?v:-v,v]):(y>0&&(v*=-1),n.push([-f,v],[f,v]))}}}),u)for(o=0;s>o;++o)u.clip(a[o]);for(o=0;s>o;++o)a[o].point=n[o];return a}var e=Ze,r=Ve,u=null;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.clipExtent=function(n){if(!arguments.length)return u&&[u[0],u[2]];if(null==n)u=null;else{var e=+n[0][0],r=+n[0][1],i=+n[1][0],o=+n[1][1];u=mo.geom.polygon([[e,r],[e,o],[i,o],[i,r]])}return t},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):u&&u[2]},t.links=function(n){var t,u,i,o=n.map(function(){return[]}),a=[],c=pt(e),l=pt(r),s=n.length;if(c===Ze&&l===Ve)t=n;else for(t=new Array(s),i=0;s>i;++i)t[i]=[+c.call(this,u=n[i],i),+l.call(this,u,i)];return vr(t,function(t){var e=t.region.l.index,r=t.region.r.index;o[e][r]||(o[e][r]=o[r][e]=!0,a.push({source:n[e],target:n[r]}))}),a},t.triangles=function(n){if(e===Ze&&r===Ve)return mo.geom.delaunay(n);for(var t,u=new Array(c),i=pt(e),o=pt(r),a=-1,c=n.length;++a=l,h=r>=s,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=Mr()),f?u=l:a=l,h?o=s:c=s,i(n,t,e,r,u,o,a,c)}var s,f,h,g,p,d,v,m,y,M=pt(a),x=pt(c);if(null!=t)d=t,v=e,m=r,y=u;else if(m=y=-(d=v=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)s=n[g],s.xm&&(m=s.x),s.y>y&&(y=s.y),f.push(s.x),h.push(s.y);else for(g=0;p>g;++g){var b=+M(s=n[g],g),_=+x(s,g);d>b&&(d=b),v>_&&(v=_),b>m&&(m=b),_>y&&(y=_),f.push(b),h.push(_)}var w=m-d,S=y-v;w>S?y=v+w:m=d+S;var E=Mr();if(E.add=function(n){i(E,n,+M(n,++g),+x(n,g),d,v,m,y)},E.visit=function(n){xr(n,E,d,v,m,y)},g=-1,null==t){for(;++g=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=bc.get(e)||xc,r=_c.get(r)||dt,Ar(r(e.apply(null,Array.prototype.slice.call(arguments,1))))},mo.interpolateHcl=Rr,mo.interpolateHsl=Yr,mo.interpolateLab=Ir,mo.interpolateRound=Ur,mo.transform=function(n){var t=xo.createElementNS(mo.ns.prefix.svg,"g");return(mo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Zr(e?e.matrix:wc)})(n)},Zr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var wc={a:1,b:0,c:0,d:1,e:0,f:0};mo.interpolateTransform=Br,mo.layout={},mo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e(u-e)*a){var c=t.charge*a*a;return n.px-=i*c,n.py-=o*c,!0}if(t.point&&isFinite(a)){var c=t.pointCharge*a*a;n.px-=i*c,n.py-=o*c}}return!t.charge}}function t(n){n.px=mo.event.x,n.py=mo.event.y,a.resume()}var e,r,u,i,o,a={},c=mo.dispatch("start","tick","end"),l=[1,1],s=.9,f=Sc,h=Ec,g=-30,p=.1,d=.8,v=[],m=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,d,y,M,x,b=v.length,_=m.length;for(e=0;_>e;++e)a=m[e],f=a.source,h=a.target,M=h.x-f.x,x=h.y-f.y,(d=M*M+x*x)&&(d=r*i[e]*((d=Math.sqrt(d))-u[e])/d,M*=d,x*=d,h.x-=M*(y=f.weight/(h.weight+f.weight)),h.y-=x*y,f.x+=M*(y=1-y),f.y+=x*y);if((y=r*p)&&(M=l[0]/2,x=l[1]/2,e=-1,y))for(;++e0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),mo.timer(a.tick)),a):r},a.start=function(){function n(n,r){for(var u,i=t(e),o=-1,a=i.length;++or;++r)c[r]=[];for(r=0;d>r;++r){var n=m[r];c[n.source.index].push(n.target),c[n.target.index].push(n.source)}}return c[e]}var e,r,c,s,p=v.length,d=m.length,y=l[0],M=l[1];for(e=0;p>e;++e)(s=v[e]).index=e,s.weight=0;for(e=0;d>e;++e)s=m[e],"number"==typeof s.source&&(s.source=v[s.source]),"number"==typeof s.target&&(s.target=v[s.target]),++s.source.weight,++s.target.weight;for(e=0;p>e;++e)s=v[e],isNaN(s.x)&&(s.x=n("x",y)),isNaN(s.y)&&(s.y=n("y",M)),isNaN(s.px)&&(s.px=s.x),isNaN(s.py)&&(s.py=s.y);if(u=[],"function"==typeof f)for(e=0;d>e;++e)u[e]=+f.call(this,m[e],e);else for(e=0;d>e;++e)u[e]=f;if(i=[],"function"==typeof h)for(e=0;d>e;++e)i[e]=+h.call(this,m[e],e);else for(e=0;d>e;++e)i[e]=h;if(o=[],"function"==typeof g)for(e=0;p>e;++e)o[e]=+g.call(this,v[e],e);else for(e=0;p>e;++e)o[e]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=mo.behavior.drag().origin(dt).on("dragstart.force",nu).on("drag.force",t).on("dragend.force",tu)),arguments.length?(this.on("mouseover.force",eu).on("mouseout.force",ru).call(e),void 0):e},mo.rebind(a,c,"on")};var Sc=20,Ec=1;mo.layout.hierarchy=function(){function n(t,o,a){var c=u.call(e,t,o);if(t.depth=o,a.push(t),c&&(l=c.length)){for(var l,s,f=-1,h=t.children=[],g=0,p=o+1;++fg;++g)for(u.call(n,l[0][g],p=d[g],s[0][g][1]),h=1;v>h;++h)u.call(n,l[h][g],p+=s[h-1][g][1],s[h][g][1]);return a}var t=dt,e=gu,r=pu,u=hu,i=su,o=fu;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:Ac.get(t)||gu,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:Nc.get(t)||pu,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var Ac=mo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(du),i=n.map(vu),o=mo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,l=[],s=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],l.push(e)):(c+=i[e],s.push(e));return s.reverse().concat(l)},reverse:function(n){return mo.range(n.length).reverse()},"default":gu}),Nc=mo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,l,s=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=l=0,e=1;h>e;++e){for(t=0,u=0;s>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];s>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,l>c&&(l=c)}for(e=0;h>e;++e)g[e]-=l;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:pu});mo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],l=n.map(e,this),s=r.call(this,l,i),f=u.call(this,s,l,i),i=-1,h=l.length,g=f.length-1,p=t?1:1/h;++i0)for(i=-1;++i=s[0]&&a<=s[1]&&(o=c[mo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=xu,u=yu;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=pt(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return Mu(n,t)}:pt(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},mo.layout.tree=function(){function n(n,i){function o(n,t){var r=n.children,u=n._tree;if(r&&(i=r.length)){for(var i,a,l,s=r[0],f=s,h=-1;++h0&&(qu(zu(a,n,r),n,u),l+=u,s+=u),f+=a._tree.mod,l+=i._tree.mod,h+=c._tree.mod,s+=o._tree.mod;a&&!wu(o)&&(o._tree.thread=a,o._tree.mod+=f-s),i&&!_u(c)&&(c._tree.thread=i,c._tree.mod+=l-h,r=n)}return r}var l=t.call(this,n,i),s=l[0];Nu(s,function(n,t){n._tree={ancestor:n,prelim:0,mod:0,change:0,shift:0,number:t?t._tree.number+1:0}}),o(s),a(s,-s._tree.prelim);var f=Su(s,ku),h=Su(s,Eu),g=Su(s,Au),p=f.x-e(f,h)/2,d=h.x+e(h,f)/2,v=g.depth||1;return Nu(s,u?function(n){n.x*=r[0],n.y=n.depth*r[1],delete n._tree}:function(n){n.x=(n.x-p)/(d-p)*r[0],n.y=n.depth/v*r[1],delete n._tree}),l}var t=mo.layout.hierarchy().sort(null).value(null),e=bu,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},iu(n,t)},mo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],l=u[1],s=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,Nu(a,function(n){n.r=+s(n.value)}),Nu(a,Hu),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/l))/2;Nu(a,function(n){n.r+=f}),Nu(a,Hu),Nu(a,function(n){n.r-=f})}return Ou(a,c/2,l/2,t?1:1/Math.max(2*a.r/c,2*a.r/l)),o}var t,e=mo.layout.hierarchy().sort(Cu),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},iu(n,e)},mo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],l=0;Nu(c,function(n){var t=n.children;t&&t.length?(n.x=Iu(t),n.y=Yu(t)):(n.x=o?l+=e(n,o):0,n.y=0,o=n)});var s=Uu(c),f=Zu(c),h=s.x-e(s,f)/2,g=f.x+e(f,s)/2;return Nu(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=mo.layout.hierarchy().sort(null).value(null),e=bu,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},iu(n,t)},mo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++ut?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,l=f(e),s=[],h=i.slice(),p=1/0,d="slice"===g?l.dx:"dice"===g?l.dy:"slice-dice"===g?1&e.depth?l.dy:l.dx:Math.min(l.dx,l.dy);for(n(h,l.dx*l.dy/e.value),s.area=0;(c=h.length)>0;)s.push(o=h[c-1]),s.area+=o.area,"squarify"!==g||(a=r(s,d))<=p?(h.pop(),p=a):(s.area-=s.pop().area,u(s,d,l,!1),d=Math.min(l.dx,l.dy),s.length=s.area=0,p=1/0);s.length&&(u(s,d,l,!0),s.length=s.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++oe&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,l=e.y,s=t?c(n.area/t):0;if(t==e.dx){for((r||s>e.dy)&&(s=e.dy);++ie.dx)&&(s=e.dx);++ie&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=mo.random.normal.apply(mo,arguments);return function(){return Math.exp(n())}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t/n}}},mo.scale={};var Tc={floor:dt,ceil:dt};mo.scale.linear=function(){return Qu([0,1],[0,1],Er,!1)},mo.scale.log=function(){return ii(mo.scale.linear().domain([0,1]),10,!0,[1,10])};var qc=mo.format(".0e"),zc={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};mo.scale.pow=function(){return oi(mo.scale.linear(),1,[0,1])},mo.scale.sqrt=function(){return mo.scale.pow().exponent(.5)},mo.scale.ordinal=function(){return ci([],{t:"range",a:[[]]})},mo.scale.category10=function(){return mo.scale.ordinal().range(Cc)},mo.scale.category20=function(){return mo.scale.ordinal().range(Dc)},mo.scale.category20b=function(){return mo.scale.ordinal().range(jc)},mo.scale.category20c=function(){return mo.scale.ordinal().range(Lc)};var Cc=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(it),Dc=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(it),jc=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(it),Lc=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(it);mo.scale.quantile=function(){return li([],[])},mo.scale.quantize=function(){return si(0,1,[0,1])},mo.scale.threshold=function(){return fi([.5],[0,1])},mo.scale.identity=function(){return hi([0,1])},mo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+Hc,a=u.apply(this,arguments)+Hc,c=(o>a&&(c=o,o=a,a=c),a-o),l=Bo>c?"0":"1",s=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a);return c>=Fc?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*s+","+i*f+"A"+i+","+i+" 0 "+l+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+l+",0 "+n*s+","+n*f+"Z":"M"+i*s+","+i*f+"A"+i+","+i+" 0 "+l+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=gi,e=pi,r=di,u=vi;return n.innerRadius=function(e){return arguments.length?(t=pt(e),n):t},n.outerRadius=function(t){return arguments.length?(e=pt(t),n):e},n.startAngle=function(t){return arguments.length?(r=pt(t),n):r},n.endAngle=function(t){return arguments.length?(u=pt(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+Hc;return[Math.cos(i)*n,Math.sin(i)*n]},n};var Hc=-Jo,Fc=Wo-Go;mo.svg.line.radial=function(){var n=Ue(mi);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},We.reverse=Je,Je.reverse=We,mo.svg.area=function(){return yi(dt)},mo.svg.area.radial=function(){var n=yi(mi);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},mo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),l=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,l)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,l.r,l.p0)+r(l.r,l.p1,l.a1-l.a0)+u(l.r,l.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+Hc,s=l.call(n,u,r)+Hc;return{r:i,a0:o,a1:s,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(s),i*Math.sin(s)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Bo)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=De,o=je,a=Mi,c=di,l=vi;return n.radius=function(t){return arguments.length?(a=pt(t),n):a},n.source=function(t){return arguments.length?(i=pt(t),n):i},n.target=function(t){return arguments.length?(o=pt(t),n):o},n.startAngle=function(t){return arguments.length?(c=pt(t),n):c},n.endAngle=function(t){return arguments.length?(l=pt(t),n):l},n},mo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=De,e=je,r=xi;return n.source=function(e){return arguments.length?(t=pt(e),n):t},n.target=function(t){return arguments.length?(e=pt(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},mo.svg.diagonal.radial=function(){var n=mo.svg.diagonal(),t=xi,e=n.projection;return n.projection=function(n){return arguments.length?e(bi(t=n)):t},n},mo.svg.symbol=function(){function n(n,r){return(Pc.get(t.call(this,n,r))||Si)(e.call(this,n,r))}var t=wi,e=_i;return n.type=function(e){return arguments.length?(t=pt(e),n):t},n.size=function(t){return arguments.length?(e=pt(t),n):e},n};var Pc=mo.map({circle:Si,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Ic)),e=t*Ic;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/Yc),e=t*Yc/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/Yc),e=t*Yc/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});mo.svg.symbolTypes=Pc.keys();var Oc,Rc,Yc=Math.sqrt(3),Ic=Math.tan(30*Qo),Uc=[],Zc=0;Uc.call=Ro.call,Uc.empty=Ro.empty,Uc.node=Ro.node,Uc.size=Ro.size,mo.transition=function(n){return arguments.length?Oc?n.transition():n:Uo.transition()},mo.transition.prototype=Uc,Uc.select=function(n){var t,e,r,u=this.id,i=[];n=d(n);for(var o=-1,a=this.length;++oi;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a)&&t.push(r)}return Ei(u,this.id)},Uc.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):N(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Uc.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n)) -})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Br:Er,a=mo.ns.qualify(n);return ki(this,"attr."+n,t,a.local?i:u)},Uc.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=mo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Uc.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=_o.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=Er(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return ki(this,"style."+n,t,u)},Uc.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,_o.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Uc.text=function(n){return ki(this,"text",n,Ai)},Uc.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Uc.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=mo.ease.apply(mo,arguments)),N(this,function(e){e.__transition__[t].ease=n}))},Uc.delay=function(n){var t=this.id;return N(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Uc.duration=function(n){var t=this.id;return N(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Uc.each=function(n,t){var e=this.id;if(arguments.length<2){var r=Rc,u=Oc;Oc=e,N(this,function(t,r,u){Rc=t.__transition__[e],n.call(t,t.__data__,r,u)}),Rc=r,Oc=u}else N(this,function(r){var u=r.__transition__[e];(u.event||(u.event=mo.dispatch("start","end"))).on(n,t)});return this},Uc.transition=function(){for(var n,t,e,r,u=this.id,i=++Zc,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],l=0,s=t.length;s>l;l++)(e=t[l])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,Ni(e,l,i,r)),n.push(e)}return Ei(o,i)},mo.svg.axis=function(){function n(n){n.each(function(){var n,l=mo.select(this),s=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):dt:t,p=l.selectAll(".tick").data(h,f),d=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Go),v=mo.transition(p.exit()).style("opacity",Go).remove(),m=mo.transition(p).style("opacity",1),y=Bu(f),M=l.selectAll(".domain").data([0]),x=(M.enter().append("path").attr("class","domain"),mo.transition(M));d.append("line"),d.append("text");var b=d.select("line"),_=m.select("line"),w=p.select("text").text(g),S=d.select("text"),E=m.select("text");switch(r){case"bottom":n=Ti,b.attr("y2",u),S.attr("y",Math.max(u,0)+o),_.attr("x2",0).attr("y2",u),E.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),x.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Ti,b.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),_.attr("x2",0).attr("y2",-u),E.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),x.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=qi,b.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),_.attr("x2",-u).attr("y2",0),E.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),x.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=qi,b.attr("x2",u),S.attr("x",Math.max(u,0)+o),_.attr("x2",u).attr("y2",0),E.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),x.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var k=f.rangeBand()/2,A=function(n){return f(n)+k};d.call(n,A),m.call(n,A)}else d.call(n,s),m.call(n,f),v.call(n,f)})}var t,e=mo.scale.linear(),r=Vc,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Xc?t+"":Vc,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Vc="bottom",Xc={top:1,right:1,bottom:1,left:1};mo.svg.brush=function(){function n(i){i.each(function(){var i=mo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(v,dt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return $c[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var s,f=mo.transition(i),h=mo.transition(o);c&&(s=Bu(c),h.attr("x",s[0]).attr("width",s[1]-s[0]),e(f)),l&&(s=Bu(l),h.attr("y",s[0]).attr("height",s[1]-s[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+s[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",s[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",s[1]-s[0])}function r(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function u(){function u(){32==mo.event.keyCode&&(N||(M=null,q[0]-=s[1],q[1]-=h[1],N=2),f())}function g(){32==mo.event.keyCode&&2==N&&(q[0]+=s[1],q[1]+=h[1],N=0,f())}function v(){var n=mo.mouse(b),u=!1;x&&(n[0]+=x[0],n[1]+=x[1]),N||(mo.event.altKey?(M||(M=[(s[0]+s[1])/2,(h[0]+h[1])/2]),q[0]=s[+(n[0]f?(u=r,r=f):u=f),g[0]!=r||g[1]!=u?(e?o=null:i=null,g[0]=r,g[1]=u,!0):void 0}function y(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),mo.select("body").style("cursor",null),z.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),T(),w({type:"brushend"})}var M,x,b=this,_=mo.select(mo.event.target),w=a.of(b,arguments),S=mo.select(b),E=_.datum(),k=!/^(n|s)$/.test(E)&&c,A=!/^(e|w)$/.test(E)&&l,N=_.classed("extent"),T=L(),q=mo.mouse(b),z=mo.select(_o).on("keydown.brush",u).on("keyup.brush",g);if(mo.event.changedTouches?z.on("touchmove.brush",v).on("touchend.brush",y):z.on("mousemove.brush",v).on("mouseup.brush",y),S.interrupt().selectAll("*").interrupt(),N)q[0]=s[0]-q[0],q[1]=h[0]-q[1];else if(E){var C=+/w$/.test(E),D=+/^n/.test(E);x=[s[1-C]-q[0],h[1-D]-q[1]],q[0]=s[C],q[1]=h[D]}else mo.event.altKey&&(M=q.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),mo.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=g(n,"brushstart","brush","brushend"),c=null,l=null,s=[0,0],h=[0,0],p=!0,d=!0,v=Bc[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:s,y:h,i:i,j:o},e=this.__chart__||t;this.__chart__=t,Oc?mo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,s=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=kr(s,t.x),r=kr(h,t.y);return i=o=null,function(u){s=t.x=e(u),h=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,v=Bc[!c<<1|!l],n):c},n.y=function(t){return arguments.length?(l=t,v=Bc[!c<<1|!l],n):l},n.clamp=function(t){return arguments.length?(c&&l?(p=!!t[0],d=!!t[1]):c?p=!!t:l&&(d=!!t),n):c&&l?[p,d]:c?p:l?d:null},n.extent=function(t){var e,r,u,a,f;return arguments.length?(c&&(e=t[0],r=t[1],l&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(f=e,e=r,r=f),(e!=s[0]||r!=s[1])&&(s=[e,r])),l&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],l.invert&&(u=l(u),a=l(a)),u>a&&(f=u,u=a,a=f),(u!=h[0]||a!=h[1])&&(h=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=s[0],r=s[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(f=e,e=r,r=f))),l&&(o?(u=o[0],a=o[1]):(u=h[0],a=h[1],l.invert&&(u=l.invert(u),a=l.invert(a)),u>a&&(f=u,u=a,a=f))),c&&l?[[e,u],[r,a]]:c?[e,r]:l&&[u,a])},n.clear=function(){return n.empty()||(s=[0,0],h=[0,0],i=o=null),n},n.empty=function(){return!!c&&s[0]==s[1]||!!l&&h[0]==h[1]},mo.rebind(n,a,"on")};var $c={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Bc=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Wc=mo.time={},Jc=Date,Gc=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];zi.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){Kc.setUTCDate.apply(this._,arguments)},setDay:function(){Kc.setUTCDay.apply(this._,arguments)},setFullYear:function(){Kc.setUTCFullYear.apply(this._,arguments)},setHours:function(){Kc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){Kc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){Kc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){Kc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){Kc.setUTCSeconds.apply(this._,arguments)},setTime:function(){Kc.setTime.apply(this._,arguments)}};var Kc=Date.prototype,Qc="%a %b %e %X %Y",nl="%m/%d/%Y",tl="%H:%M:%S",el=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],rl=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],ul=["January","February","March","April","May","June","July","August","September","October","November","December"],il=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];Wc.year=Ci(function(n){return n=Wc.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),Wc.years=Wc.year.range,Wc.years.utc=Wc.year.utc.range,Wc.day=Ci(function(n){var t=new Jc(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),Wc.days=Wc.day.range,Wc.days.utc=Wc.day.utc.range,Wc.dayOfYear=function(n){var t=Wc.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},Gc.forEach(function(n,t){n=n.toLowerCase(),t=7-t;var e=Wc[n]=Ci(function(n){return(n=Wc.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=Wc.year(n).getDay();return Math.floor((Wc.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});Wc[n+"s"]=e.range,Wc[n+"s"].utc=e.utc.range,Wc[n+"OfYear"]=function(n){var e=Wc.year(n).getDay();return Math.floor((Wc.dayOfYear(n)+(e+t)%7)/7)}}),Wc.week=Wc.sunday,Wc.weeks=Wc.sunday.range,Wc.weeks.utc=Wc.sunday.utc.range,Wc.weekOfYear=Wc.sundayOfYear,Wc.format=ji;var ol=Hi(el),al=Fi(el),cl=Hi(rl),ll=Fi(rl),sl=Hi(ul),fl=Fi(ul),hl=Hi(il),gl=Fi(il),pl=/^%/,dl={"-":"",_:" ",0:"0"},vl={a:function(n){return rl[n.getDay()]},A:function(n){return el[n.getDay()]},b:function(n){return il[n.getMonth()]},B:function(n){return ul[n.getMonth()]},c:ji(Qc),d:function(n,t){return Pi(n.getDate(),t,2)},e:function(n,t){return Pi(n.getDate(),t,2)},H:function(n,t){return Pi(n.getHours(),t,2)},I:function(n,t){return Pi(n.getHours()%12||12,t,2)},j:function(n,t){return Pi(1+Wc.dayOfYear(n),t,3)},L:function(n,t){return Pi(n.getMilliseconds(),t,3)},m:function(n,t){return Pi(n.getMonth()+1,t,2)},M:function(n,t){return Pi(n.getMinutes(),t,2)},p:function(n){return n.getHours()>=12?"PM":"AM"},S:function(n,t){return Pi(n.getSeconds(),t,2)},U:function(n,t){return Pi(Wc.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Pi(Wc.mondayOfYear(n),t,2)},x:ji(nl),X:ji(tl),y:function(n,t){return Pi(n.getFullYear()%100,t,2)},Y:function(n,t){return Pi(n.getFullYear()%1e4,t,4)},Z:ao,"%":function(){return"%"}},ml={a:Oi,A:Ri,b:Zi,B:Vi,c:Xi,d:no,e:no,H:eo,I:eo,j:to,L:io,m:Qi,M:ro,p:oo,S:uo,U:Ii,w:Yi,W:Ui,x:$i,X:Bi,y:Ji,Y:Wi,Z:Gi,"%":co},yl=/^\s*\d+/,Ml=mo.map({am:0,pm:1});ji.utc=lo;var xl=lo("%Y-%m-%dT%H:%M:%S.%LZ");ji.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?so:xl,so.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},so.toString=xl.toString,Wc.second=Ci(function(n){return new Jc(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),Wc.seconds=Wc.second.range,Wc.seconds.utc=Wc.second.utc.range,Wc.minute=Ci(function(n){return new Jc(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),Wc.minutes=Wc.minute.range,Wc.minutes.utc=Wc.minute.utc.range,Wc.hour=Ci(function(n){var t=n.getTimezoneOffset()/60;return new Jc(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),Wc.hours=Wc.hour.range,Wc.hours.utc=Wc.hour.utc.range,Wc.month=Ci(function(n){return n=Wc.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),Wc.months=Wc.month.range,Wc.months.utc=Wc.month.utc.range;var bl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],_l=[[Wc.second,1],[Wc.second,5],[Wc.second,15],[Wc.second,30],[Wc.minute,1],[Wc.minute,5],[Wc.minute,15],[Wc.minute,30],[Wc.hour,1],[Wc.hour,3],[Wc.hour,6],[Wc.hour,12],[Wc.day,1],[Wc.day,2],[Wc.week,1],[Wc.month,1],[Wc.month,3],[Wc.year,1]],wl=[[ji("%Y"),Vt],[ji("%B"),function(n){return n.getMonth()}],[ji("%b %d"),function(n){return 1!=n.getDate()}],[ji("%a %d"),function(n){return n.getDay()&&1!=n.getDate()}],[ji("%I %p"),function(n){return n.getHours()}],[ji("%I:%M"),function(n){return n.getMinutes()}],[ji(":%S"),function(n){return n.getSeconds()}],[ji(".%L"),function(n){return n.getMilliseconds()}]],Sl=go(wl);_l.year=Wc.year,Wc.scale=function(){return fo(mo.scale.linear(),_l,Sl)};var El={range:function(n,t,e){return mo.range(+n,+t,e).map(ho)}},kl=_l.map(function(n){return[n[0].utc,n[1]]}),Al=[[lo("%Y"),Vt],[lo("%B"),function(n){return n.getUTCMonth()}],[lo("%b %d"),function(n){return 1!=n.getUTCDate()}],[lo("%a %d"),function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],[lo("%I %p"),function(n){return n.getUTCHours()}],[lo("%I:%M"),function(n){return n.getUTCMinutes()}],[lo(":%S"),function(n){return n.getUTCSeconds()}],[lo(".%L"),function(n){return n.getUTCMilliseconds()}]],Nl=go(Al);return kl.year=Wc.year.utc,Wc.scale.utc=function(){return fo(mo.scale.linear(),kl,Nl)},mo.text=vt(function(n){return n.responseText}),mo.json=function(n,t){return mt(n,"application/json",po,t)},mo.html=function(n,t){return mt(n,"text/html",vo,t)},mo.xml=vt(function(n){return n.responseXML}),mo}(); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graph_util.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graph_util.js deleted file mode 100644 index 9b20afe4..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graph_util.js +++ /dev/null @@ -1,243 +0,0 @@ -var fromDate; -var toDate; - -// create a custom bar renderer that has no gaps -Rickshaw.Graph.Renderer.BarNoGap = Rickshaw.Class.create(Rickshaw.Graph.Renderer.Bar, { - name: 'bar_no_gap', - barWidth: function (series) { - var frequentInterval = this._frequentInterval(series.stack); - var barWidth = this.graph.x(series.stack[0].x + frequentInterval.magnitude * 1); - return barWidth; - } -}); - - -var currentDay = new Date(); -var startDate = new Date(currentDay.getTime() - (60 * 60 * 24 * 100)); -var endDate = new Date(currentDay.getTime()); - -var configObject = { - startOfWeek: 'monday', - separator: ' to ', - format: 'YYYY-MM-DD HH:mm', - autoClose: false, - time: { - enabled: true - }, - shortcuts: 'hide', - endDate: currentDay, - - getValue: function () { - return this.value; - }, - setValue: function (s) { - this.value = s; - } -}; - -var DateRange = convertDate(startDate) + " " + configObject.separator + " " + convertDate(endDate); - -$('#date-range').dateRangePicker(configObject) - .bind('datepicker-apply', function (event, dateRange) { - $(this).addClass('active'); - $(this).siblings().removeClass('active'); - fromDate = dateRange.date1 != "Invalid Date" ? dateRange.date1.getTime() / 1000 : null; - toDate = dateRange.date2 != "Invalid Date" ? dateRange.date2.getTime() / 1000 : null; - getStats(fromDate, toDate); - } -); - -$(document).ready(function () { - $('#date-range').html(DateRange); - $('#date-range').trigger('datepicker-apply', - { - 'value': DateRange, - 'date1': startDate, - 'date2': endDate - }); -}); - -//day picker -$('#today-btn').on('click', function () { - getDateTime(currentDay.getTime() - 86400000, currentDay.getTime()); -}); - -//hour picker -$('#hour-btn').on('click', function () { - getDateTime(currentDay.getTime() - 3600000, currentDay.getTime()); -}) - -//week picker -$('#week-btn').on('click', function () { - getDateTime(currentDay.getTime() - 604800000, currentDay.getTime()); -}) - -//month picker -$('#month-btn').on('click', function () { - getDateTime(currentDay.getTime() - (604800000 * 4), currentDay.getTime()); -}); - -$('body').on('click', '.btn-group button', function (e) { - $(this).addClass('active'); - $(this).siblings().removeClass('active'); -}); - -function getDateTime(from, to) { - startDate = new Date(from); - endDate = new Date(to); - DateRange = convertDate(startDate) + " " + configObject.separator + " " + convertDate(endDate); - console.log(DateRange); - $('#date-range').html(DateRange); - $('#date-range').trigger('datepicker-apply', - { - 'value': DateRange, - 'date1': startDate, - 'date2': endDate - } - ); - getStats(from / 1000, to / 1000); -} - -function getStats(from, to) { - var deviceId = getUrlParameter('deviceId'); - var deviceType = getUrlParameter('deviceType'); - - var requestData = new Object(); - - requestData['deviceId'] = deviceId; - requestData['deviceType'] = deviceType; - - if (from) { - requestData['from'] = from; - } - - if (to) { - requestData['to'] = to; - } - - var getStatsRequest = $.ajax({ - url: "api/stats", - method: "GET", - data: requestData - }); - - getStatsRequest.done(function (stats) { - updateGraphs(JSON.parse(stats)); - }); - - getStatsRequest.fail(function (jqXHR, textStatus) { - alert("Request failed: " + textStatus); - }); - -} - -function getUrlParameter(paramName) { - var pageURL = window.location.search.substring(1); - var urlVariables = pageURL.split('&'); - for (var i = 0; i < urlVariables.length; i++) { - var parameterName = urlVariables[i].split('='); - if (parameterName[0] == paramName) { - return parameterName[1]; - } - } -} - -function updateGraphs(stats) { - console.log(stats); - - var temperatureData = stats['temperatureData']; - updateTemperatureGraph(convertStatsToGraphData(temperatureData)); - - var lightData = stats['lightData']; - updateLightGraph(convertStatsToGraphData(lightData)); - - var motionData = stats['motionData']; - updateMotionGraph(convertStatsToGraphData(motionData)); - - var sonarData = stats['sonarData']; - updateSonarGraph(convertStatsToGraphData(sonarData)); - - var fanData = stats['fanData']; - updateFanGraph(convertStateStatsToGraphData(fanData)); - - var bulbData = stats['bulbData']; - updateBulbGraph(convertStateStatsToGraphData(bulbData)); - - scaleGraphs(); -} - -function scaleGraphs() { - var sliders = $('.right_handle'); - if (sliders.length == 0) { - return; - } - - var graphWidth = $('#canvas-wrapper1').width() - 50; - //Scale graphs - var sliderX = graphWidth * 60 * 60 / (toDate - fromDate); - if (sliderX < graphWidth) { - // fake handle move - if (sliderX < 100) { - sliderX = 100; - } - var edown = document.createEvent("HTMLEvents"); - edown.initEvent("mousedown", true, true); - edown.clientX = graphWidth; - var emove = document.createEvent("HTMLEvents"); - emove.initEvent("mousemove", true, true); - emove.clientX = sliderX; - var eup = document.createEvent("HTMLEvents"); - eup.initEvent("mouseup", true, true); - for (var slider in sliders) { - sliders[slider].dispatchEvent(edown); - document.dispatchEvent(emove); - document.dispatchEvent(eup); - } - } -} - -function convertStatsToGraphData(stats) { - - var graphData = new Array(); - if (!stats) { - return graphData; - } - for (var i = 0; i < stats.length; i++) { - graphData.push({x: parseInt(stats[i]['time']) * 1000, y: stats[i]['value']}) - } - - return graphData; -} - - -function convertStateStatsToGraphData(stats) { - - var graphData = new Array(); - if (!stats) { - return graphData; - } - var yValue; - for (var i = 0; i < stats.length; i++) { - yValue = -1; - - if (stats[i]['value'].toUpperCase() == 'ON') { - yValue = 1; - } else if (stats[i]['value'].toUpperCase() == 'OFF') { - yValue = 0; - } - - graphData.push({x: parseInt(stats[i]['time']) * 1000, y: yValue}) - } - - return graphData; -} - -function convertDate(date) { - var month = date.getMonth() + 1; - var day = date.getDate(); - var hour=date.getHours(); - var minute=date.getMinutes(); - return date.getFullYear() + '-' + (('' + month).length < 2 ? '0' : '') - + month + '-' + (('' + day).length < 2 ? '0' : '') + day +" "+ (('' + hour).length < 2 ? '0' : '') - + hour +":"+(('' + minute).length < 2 ? '0' : '')+ minute; -} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/bulb_graph.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/bulb_graph.js deleted file mode 100644 index f4a1c5a4..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/bulb_graph.js +++ /dev/null @@ -1,85 +0,0 @@ -function updateBulbGraph(bulbData) { - renderBulbChart(bulbData); -} - - -function renderBulbChart(chartDataRaw){ - var chartWrapperElmId = "#canvas-wrapper6"; - var graphWidth = $(chartWrapperElmId).width() - 50; - if (chartDataRaw.length == 0) { - $(chartWrapperElmId).html("No data available..."); - return; - } - - var chartData = [[], []]; - for (var i = 0; i < chartDataRaw.length; i++){ - chartData[0].push({x:parseInt(chartDataRaw[i].x), y:parseInt(chartDataRaw[i].y)}); - chartData[1].push({x:parseInt(chartDataRaw[i].x), y:Math.abs(parseInt(chartDataRaw[i].y) - 1)}); - } - - //var i = parseInt(fromDate); - //while (i < parseInt(toDate)) { - // var rnd = Math.round(Math.random()); - // chartData[0].push({x: i * 1000, y: rnd}); - // chartData[1].push({x: i * 1000, y: Math.abs(rnd - 1)}); - // i += 60 * 5; - //} - - var chartDiv = "chart6"; - var sliderDiv = "slider6"; - var x_axis = "x_axis6"; - var y_axis = "y_axis6"; - $(chartWrapperElmId).html("").html('
    '); - - var graph = new Rickshaw.Graph({ - element: document.getElementById(chartDiv), - width: graphWidth, - height: 150, - strokeWidth: 0.5, - renderer: 'bar_no_gap', - xScale: d3.time.scale(), - padding: {top: 0.2, left: 0.02, right: 0.02, bottom: 0}, - series: [ - {color: '#5E610B', data: chartData[0]}, - {color: 'white', data: chartData[1]} - ] - }); - - graph.registerRenderer(new Rickshaw.Graph.Renderer.BarNoGap({graph: graph})); - - graph.render(); - - var xAxis = new Rickshaw.Graph.Axis.X({ - graph: graph, - orientation: 'bottom', - element: document.getElementById(x_axis), - tickFormat: graph.x.tickFormat() - }); - - xAxis.render(); - - var yAxis = new Rickshaw.Graph.Axis.Y({ - graph: graph, - orientation: 'left', - element: document.getElementById(y_axis), - width: 40, - height: 160, - tickFormat: function (y) { - switch (y) { - case 1: - return 'ON'; - case 0: - return 'OFF'; - default : - return ''; - } - } - }); - - yAxis.render(); - - var slider = new Rickshaw.Graph.RangeSlider.Preview({ - graph: graph, - element: document.getElementById(sliderDiv) - }); -} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/fan_graph.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/fan_graph.js deleted file mode 100644 index 991a14d6..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/fan_graph.js +++ /dev/null @@ -1,84 +0,0 @@ -function updateFanGraph(fanData) { - renderFanChart(fanData); -} - -function renderFanChart(chartDataRaw) { - var chartWrapperElmId = "#canvas-wrapper5"; - var graphWidth = $(chartWrapperElmId).width() - 50; - if (chartDataRaw.length == 0) { - $(chartWrapperElmId).html("No data available..."); - return; - } - - var chartData = [[], []]; - for (var i = 0; i < chartDataRaw.length; i++){ - chartData[0].push({x:parseInt(chartDataRaw[i].x), y:parseInt(chartDataRaw[i].y)}); - chartData[1].push({x:parseInt(chartDataRaw[i].x), y:Math.abs(parseInt(chartDataRaw[i].y) - 1)}); - } - - //var i = parseInt(fromDate); - //while (i < parseInt(toDate)) { - // var rnd = Math.round(Math.random()); - // chartData[0].push({x: i * 1000, y: rnd}); - // chartData[1].push({x: i * 1000, y: Math.abs(rnd - 1)}); - // i += 60 * 5; - //} - - var chartDiv = "chart5"; - var sliderDiv = "slider5"; - var x_axis = "x_axis5"; - var y_axis = "y_axis5"; - $(chartWrapperElmId).html("").html('
    '); - - var graph = new Rickshaw.Graph({ - element: document.getElementById(chartDiv), - width: graphWidth, - height: 150, - strokeWidth: 0.5, - renderer: 'bar_no_gap', - xScale: d3.time.scale(), - padding: {top: 0.2, left: 0.02, right: 0.02, bottom: 0}, - series: [ - {color: '#2F0B3A', data: chartData[0]}, - {color: 'white', data: chartData[1]} - ] - }); - - graph.registerRenderer(new Rickshaw.Graph.Renderer.BarNoGap({graph: graph})); - - graph.render(); - - var xAxis = new Rickshaw.Graph.Axis.X({ - graph: graph, - orientation: 'bottom', - element: document.getElementById(x_axis), - tickFormat: graph.x.tickFormat() - }); - - xAxis.render(); - - var yAxis = new Rickshaw.Graph.Axis.Y({ - graph: graph, - orientation: 'left', - element: document.getElementById(y_axis), - width: 40, - height: 160, - tickFormat: function (y) { - switch (y) { - case 1: - return 'ON'; - case 0: - return 'OFF'; - default : - return ''; - } - } - }); - - yAxis.render(); - - var slider = new Rickshaw.Graph.RangeSlider.Preview({ - graph: graph, - element: document.getElementById(sliderDiv) - }); -} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/light_graph.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/light_graph.js deleted file mode 100644 index 1e91a758..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/light_graph.js +++ /dev/null @@ -1,85 +0,0 @@ -function updateLightGraph(lightData) { - renderLightChart(lightData); -} - - -function renderLightChart(chartDataRaw){ - var chartWrapperElmId = "#canvas-wrapper2"; - var graphWidth = $(chartWrapperElmId).width() - 50; - if (chartDataRaw.length == 0) { - $(chartWrapperElmId).html("No data available..."); - return; - } - - var chartData = [[], []]; - for (var i = 0; i < chartDataRaw.length; i++){ - chartData[0].push({x:parseInt(chartDataRaw[i].x), y:parseInt(chartDataRaw[i].y)}); - chartData[1].push({x:parseInt(chartDataRaw[i].x), y:Math.abs(parseInt(chartDataRaw[i].y) - 1)}); - } - - //var i = parseInt(fromDate); - //while (i < parseInt(toDate)) { - // var rnd = Math.round(Math.random()); - // chartData[0].push({x: i * 1000, y: rnd}); - // chartData[1].push({x: i * 1000, y: Math.abs(rnd - 1)}); - // i += 60 * 5; - //} - - var chartDiv = "chart2"; - var sliderDiv = "slider2"; - var x_axis = "x_axis2"; - var y_axis = "y_axis2"; - $(chartWrapperElmId).html("").html('
    '); - - var graph = new Rickshaw.Graph({ - element: document.getElementById(chartDiv), - width: graphWidth, - height: 150, - strokeWidth: 0.5, - renderer: 'bar_no_gap', - xScale: d3.time.scale(), - padding: {top: 0.2, left: 0.02, right: 0.02, bottom: 0}, - series: [ - {color: 'steelblue', data: chartData[0]}, - {color: 'white', data: chartData[1]} - ] - }); - - graph.registerRenderer(new Rickshaw.Graph.Renderer.BarNoGap({graph: graph})); - - graph.render(); - - var xAxis = new Rickshaw.Graph.Axis.X({ - graph: graph, - orientation: 'bottom', - element: document.getElementById(x_axis), - tickFormat: graph.x.tickFormat() - }); - - xAxis.render(); - - var yAxis = new Rickshaw.Graph.Axis.Y({ - graph: graph, - orientation: 'left', - element: document.getElementById(y_axis), - width: 40, - height: 160, - tickFormat: function (y) { - switch (y) { - case 1: - return 'ON'; - case 0: - return 'OFF'; - default : - return ''; - } - } - }); - - yAxis.render(); - - var slider = new Rickshaw.Graph.RangeSlider.Preview({ - graph: graph, - element: document.getElementById(sliderDiv) - }); -} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/motion_graph.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/motion_graph.js deleted file mode 100644 index 04fe84d6..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/motion_graph.js +++ /dev/null @@ -1,70 +0,0 @@ -function updateMotionGraph(motionData) { - renderMotionChart(motionData); -} - - -function renderMotionChart(chartDataRaw){ - var chartWrapperElmId = "#canvas-wrapper3"; - var graphWidth = $(chartWrapperElmId).width() - 50; - if (chartDataRaw.length == 0) { - $(chartWrapperElmId).html("No data available..."); - return; - } - - var chartData = []; - for (var i = 0; i < chartDataRaw.length; i++){ - chartData.push({x:parseInt(chartDataRaw[i].x), y:parseInt(chartDataRaw[i].y)}); - } - - //var i = parseInt(fromDate); - //while (i < parseInt(toDate)){ - // var rnd = Math.random() * (30 - 20) + 20; - // chartData.push({x:i * 1000, y:rnd}); - // i += 60 * 5; - //} - - var chartDiv = "chart3"; - var sliderDiv = "slider3"; - var x_axis = "x_axis3"; - var y_axis = "y_axis3"; - $(chartWrapperElmId).html("").html('
    '); - - var graph = new Rickshaw.Graph({ - element: document.getElementById(chartDiv), - width: graphWidth, - height: 400, - strokeWidth: 0.5, - renderer: 'line', - xScale: d3.time.scale(), - padding: {top: 0.2, left: 0.02, right: 0.02, bottom: 0}, - series:[ - { color: '#2F0B3A', data: chartData } - ] - }); - - graph.render(); - - var xAxis = new Rickshaw.Graph.Axis.X({ - graph: graph, - orientation: 'bottom', - element: document.getElementById(x_axis), - tickFormat: graph.x.tickFormat() - }); - - xAxis.render(); - - var yAxis = new Rickshaw.Graph.Axis.Y({ - graph: graph, - orientation: 'left', - element: document.getElementById(y_axis), - width: 40, - height: 410 - }); - - yAxis.render(); - - var slider = new Rickshaw.Graph.RangeSlider.Preview({ - graph: graph, - element: document.getElementById(sliderDiv) - }); -} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/sonar_graph.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/sonar_graph.js deleted file mode 100644 index c7bdf5c5..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/sonar_graph.js +++ /dev/null @@ -1,69 +0,0 @@ -function updateSonarGraph(sonarData) { - renderSonarChart(sonarData); -} - -function renderSonarChart(chartDataRaw){ - var chartWrapperElmId = "#canvas-wrapper4"; - var graphWidth = $(chartWrapperElmId).width() - 50; - if (chartDataRaw.length == 0) { - $(chartWrapperElmId).html("No data available..."); - return; - } - - var chartData = []; - for (var i = 0; i < chartDataRaw.length; i++){ - chartData.push({x:parseInt(chartDataRaw[i].x), y:parseInt(chartDataRaw[i].y)}); - } - - //var i = parseInt(fromDate); - //while (i < parseInt(toDate)){ - // var rnd = Math.random() * (30 - 20) + 20; - // chartData.push({x:i * 1000, y:rnd}); - // i += 60 * 5; - //} - - var chartDiv = "chart4"; - var sliderDiv = "slider4"; - var x_axis = "x_axis4"; - var y_axis = "y_axis4"; - $(chartWrapperElmId).html("").html('
    '); - - var graph = new Rickshaw.Graph({ - element: document.getElementById(chartDiv), - width: graphWidth, - height: 400, - strokeWidth: 1, - renderer: 'line', - xScale: d3.time.scale(), - padding: {top: 0.2, left: 0.02, right: 0.02, bottom: 0}, - series:[ - { color: '#170B3B', data: chartData } - ] - }); - - graph.render(); - - var xAxis = new Rickshaw.Graph.Axis.X({ - graph: graph, - orientation: 'bottom', - element: document.getElementById(x_axis), - tickFormat: graph.x.tickFormat() - }); - - xAxis.render(); - - var yAxis = new Rickshaw.Graph.Axis.Y({ - graph: graph, - orientation: 'left', - element: document.getElementById(y_axis), - width: 40, - height: 410 - }); - - yAxis.render(); - - var slider = new Rickshaw.Graph.RangeSlider.Preview({ - graph: graph, - element: document.getElementById(sliderDiv) - }); -} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/temperature_graph.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/temperature_graph.js deleted file mode 100644 index 3fed9611..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/graphs/temperature_graph.js +++ /dev/null @@ -1,70 +0,0 @@ -function updateTemperatureGraph(temperatureData) { - console.log("temperatureData"); - renderTemperatureChart(temperatureData); -} - -function renderTemperatureChart(chartDataRaw){ - var chartWrapperElmId = "#canvas-wrapper1"; - var graphWidth = $(chartWrapperElmId).width() - 50; - if (chartDataRaw.length == 0) { - $(chartWrapperElmId).html("No data available..."); - return; - } - - var chartData = []; - for (var i = 0; i < chartDataRaw.length; i++){ - chartData.push({x:parseInt(chartDataRaw[i].x), y:parseInt(chartDataRaw[i].y)}); - } - - //var i = parseInt(fromDate); - //while (i < parseInt(toDate)){ - // var rnd = Math.random() * (30 - 20) + 20; - // chartData.push({x:i * 1000, y:rnd}); - // i += 60 * 5; - //} - - var chartDiv = "chart1"; - var sliderDiv = "slider1"; - var x_axis = "x_axis1"; - var y_axis = "y_axis1"; - $(chartWrapperElmId).html("").html('
    '); - - var graph = new Rickshaw.Graph({ - element: document.getElementById(chartDiv), - width: graphWidth, - height: 400, - strokeWidth: 1, - renderer: 'line', - xScale: d3.time.scale(), - padding: {top: 0.2, left: 0.02, right: 0.02, bottom: 0}, - series:[ - { color: '#FF4000', data: chartData } - ] - }); - - graph.render(); - - var xAxis = new Rickshaw.Graph.Axis.X({ - graph: graph, - orientation: 'bottom', - element: document.getElementById(x_axis), - tickFormat: graph.x.tickFormat() - }); - - xAxis.render(); - - var yAxis = new Rickshaw.Graph.Axis.Y({ - graph: graph, - orientation: 'left', - element: document.getElementById(y_axis), - width: 40, - height: 410 - }); - - yAxis.render(); - - var slider = new Rickshaw.Graph.RangeSlider.Preview({ - graph: graph, - element: document.getElementById(sliderDiv) - }); -} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/jquery.daterangepicker.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/jquery.daterangepicker.js deleted file mode 100644 index 872bc597..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/jquery.daterangepicker.js +++ /dev/null @@ -1,1432 +0,0 @@ -// daterangepicker.js -// version : 0.0.5 -// author : Chunlong Liu -// last updated at: 2014-05-27 -// license : MIT -// www.jszen.com - -(function($) -{ - - $.dateRangePickerLanguages = - { - 'cn': - { - 'selected': '已选择:', - 'day':'天', - 'days': '天', - 'apply': '确定', - 'week-1' : '一', - 'week-2' : '二', - 'week-3' : '三', - 'week-4' : '四', - 'week-5' : '五', - 'week-6' : '六', - 'week-7' : '日', - 'month-name': ['一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'], - 'shortcuts' : '快捷选择', - 'past': '过去', - 'following':'将来', - 'previous' : '   ', - 'prev-week' : '上周', - 'prev-month' : '上个月', - 'prev-year' : '去年', - 'next': '   ', - 'next-week':'下周', - 'next-month':'下个月', - 'next-year':'明年', - 'less-than' : '所选日期范围不能大于%d天', - 'more-than' : '所选日期范围不能小于%d天', - 'default-more' : '请选择大于%d天的日期范围', - 'default-less' : '请选择小于%d天的日期范围', - 'default-range' : '请选择%d天到%d天的日期范围', - 'default-single':'请选择一个日期', - 'default-default': '请选择一个日期范围' - }, - 'cz': - { - 'selected': 'Vybráno:', - 'day':'Den', - 'days': 'Dny', - 'apply': 'Zavřít', - 'week-1' : 'Po', - 'week-2' : 'Út', - 'week-3' : 'St', - 'week-4' : 'Čt', - 'week-5' : 'Pá', - 'week-6' : 'So', - 'week-7' : 'Ne', - 'month-name': ['Leden','Únor','Březen','Duben','Květen','Červen','Červenec','Srpen','Září','Říjen','Listopad','Prosinec'], - 'shortcuts' : 'Zkratky', - 'past': 'po', - 'following':'následující', - 'previous' : 'předchozí', - 'prev-week' : 'týden', - 'prev-month' : 'měsíc', - 'prev-year' : 'rok', - 'next':'další', - 'next-week':'týden', - 'next-month':'měsíc', - 'next-year':'rok', - 'less-than' : 'Rozsah data by neměl být větší než %d dnů', - 'more-than' : 'Rozsah data by neměl být menší než %d dnů', - 'default-more' : 'Prosím zvolte rozsah data větší než %d dnů', - 'default-single' : 'Prosím zvolte datum', - 'default-less' : 'Prosím zvolte rozsah data menší než %d dnů', - 'default-range' : 'Prosím zvolte rozsah data mezi %d a %d dny', - 'default-default': 'Prosím zvolte rozsah data' - }, - 'en': - { - 'selected': 'Selected:', - 'day':'Day', - 'days': 'Days', - 'apply': 'Apply', - 'week-1' : 'MO', - 'week-2' : 'TU', - 'week-3' : 'WE', - 'week-4' : 'TH', - 'week-5' : 'FR', - 'week-6' : 'SA', - 'week-7' : 'SU', - 'month-name': ['JANUARY','FEBRUARY','MARCH','APRIL','MAY','JUNE','JULY','AUGUST','SEPTEMBER','OCTOBER','NOVEMBER','DECEMBER'], - 'shortcuts' : 'Shortcuts', - 'past': 'Past', - 'following':'Following', - 'previous' : 'Previous', - 'prev-week' : 'Week', - 'prev-month' : 'Month', - 'prev-year' : 'Year', - 'next':'Next', - 'next-week':'Week', - 'next-month':'Month', - 'next-year':'Year', - 'less-than' : 'Date range should not be more than %d days', - 'more-than' : 'Date range should not be less than %d days', - 'default-more' : 'Please select a date range longer than %d days', - 'default-single' : 'Please select a date', - 'default-less' : 'Please select a date range less than %d days', - 'default-range' : 'Please select a date range between %d and %d days', - 'default-default': 'Please select a date range' - }, - 'it': - { - 'selected': 'Selezionati:', - 'day':'Giorno', - 'days': 'Giorni', - 'apply': 'Chiudi', - 'week-1' : 'LU', - 'week-2' : 'MA', - 'week-3' : 'ME', - 'week-4' : 'GI', - 'week-5' : 'VE', - 'week-6' : 'SA', - 'week-7' : 'DO', - 'month-name': ['GENNAIO','FEBBRAIO','MARZO','APRILE','MAGGIO','GIUGNO','LUGLIO','AGOSTO','SETTEMBRE','OTTOBRE','NOVEMBRE','DICEMBRE'], - 'shortcuts' : 'Scorciatoie', - 'past': 'Scorso', - 'following':'Successivo', - 'previous' : 'Precedente', - 'prev-week' : 'Settimana', - 'prev-month' : 'Mese', - 'prev-year' : 'Anno', - 'next':'Prossimo', - 'next-week':'Settimana', - 'next-month':'Mese', - 'next-year':'Anno', - 'less-than' : 'L\'intervallo non dev\'essere maggiore di %d giorni', - 'more-than' : 'L\'intervallo non dev\'essere minore di %d giorni', - 'default-more' : 'Seleziona un intervallo maggiore di %d giorni', - 'default-single' : 'Seleziona una data', - 'default-less' : 'Seleziona un intervallo minore di %d giorni', - 'default-range' : 'Seleziona un intervallo compreso tra i %d e i %d giorni', - 'default-default': 'Seleziona un intervallo di date' - }, - 'es': - { - 'selected': 'Seleccionado:', - 'day':'Dia', - 'days': 'Dias', - 'apply': 'Cerrar', - 'week-1' : 'LU', - 'week-2' : 'MA', - 'week-3' : 'MI', - 'week-4' : 'JU', - 'week-5' : 'VI', - 'week-6' : 'SA', - 'week-7' : 'DO', - 'month-name': ['ENERO','FEBRERO','MARZO','ABRIL','MAYO','JUNIO','JULIO','AGOSTO','SEPTIEMBRE','OCTUBRE','NOVIEMBRE','DICIEMBRE'], - 'shortcuts' : 'Accesos directos', - 'past': 'Pasado', - 'following':'Siguiente', - 'previous' : 'Anterior', - 'prev-week' : 'Semana', - 'prev-month' : 'Mes', - 'prev-year' : 'Año', - 'next':'Siguiente', - 'next-week':'Semana', - 'next-month':'Mes', - 'next-year':'Año', - 'less-than' : 'El rango no deberia ser mayor de %d dias', - 'more-than' : 'El rango no deberia ser menor de %d dias', - 'default-more' : 'Por favor selecciona un rango mayor a %d dias', - 'default-single' : 'Por favor selecciona un dia', - 'default-less' : 'Por favor selecciona un rango menor a %d dias', - 'default-range' : 'Por favor selecciona un rango entre %d y %d dias', - 'default-default': 'Por favor selecciona un rango de fechas.' - }, - 'de': - { - 'selected': 'Auswahl:', - 'day':'Tag', - 'days': 'Tage', - 'apply': 'Schließen', - 'week-1' : 'MO', - 'week-2' : 'DI', - 'week-3' : 'MI', - 'week-4' : 'DO', - 'week-5' : 'FR', - 'week-6' : 'SA', - 'week-7' : 'SO', - 'month-name': ['JANUAR','FEBRUAR','MÄRZ','APRIL','MAI','JUNI','JULI','AUGUST','SEPTEMBER','OKTOBER','NOVEMBER','DEZEMBER'], - 'shortcuts' : 'Schnellwahl', - 'past': 'Vorherige', - 'following':'Folgende', - 'previous' : 'Vorherige', - 'prev-week' : 'Woche', - 'prev-month' : 'Monat', - 'prev-year' : 'Jahr', - 'next':'Nächste', - 'next-week':'Woche', - 'next-month':'Monat', - 'next-year':'Jahr', - 'less-than' : 'Datumsbereich darf nicht größer sein als %d Tage', - 'more-than' : 'Datumsbereich darf nicht kleiner sein als %d Tage', - 'default-more' : 'Bitte mindestens %d Tage auswählen', - 'default-single' : 'Bitte ein Datum auswählen', - 'default-less' : 'Bitte weniger als %d Tage auswählen', - 'default-range' : 'Bitte einen Datumsbereich zwischen %d und %d Tagen auswählen', - 'default-default': 'Bitte ein Start- und Enddatum auswählen' - }, - 'ru': - { - 'selected': 'Выбрано:', - 'day': 'День', - 'days': 'Дней', - 'apply': 'Закрыть', - 'week-1': 'ПН', - 'week-2': 'ВТ', - 'week-3': 'СР', - 'week-4': 'ЧТ', - 'week-5': 'ПТ', - 'week-6': 'СБ', - 'week-7': 'ВС', - 'month-name': ['ЯНВАРЬ','ФЕВРАЛЬ','МАРТ','АПРЕЛЬ','МАЙ','ИЮНЬ','ИЮЛЬ','АВГУСТ','СЕНТЯБРЬ','ОКТЯБРЬ','НОЯБРЬ','ДЕКАБРЬ'], - 'shortcuts': 'Быстрый выбор', - 'past': 'Прошедшие', - 'following': 'Следующие', - 'previous': '   ', - 'prev-week': 'Неделя', - 'prev-month': 'Месяц', - 'prev-year': 'Год', - 'next': '   ', - 'next-week': 'Неделя', - 'next-month': 'Месяц', - 'next-year': 'Год', - 'less-than': 'Диапазон не может быть больше %d дней', - 'more-than': 'Диапазон не может быть меньше %d дней', - 'default-more': 'Пожалуйста выберите диапазон больше %d дней', - 'default-single': 'Пожалуйста выберите дату', - 'default-less': 'Пожалуйста выберите диапазон меньше %d дней', - 'default-range': 'Пожалуйста выберите диапазон между %d и %d днями', - 'default-default': 'Пожалуйста выберите диапазон' - }, - 'fr': - { - 'selected': 'Sélection:', - 'day':'Jour', - 'days': 'Jours', - 'apply': 'Fermer', - 'week-1' : 'LU', - 'week-2' : 'MA', - 'week-3' : 'ME', - 'week-4' : 'JE', - 'week-5' : 'VE', - 'week-6' : 'SA', - 'week-7' : 'DI', - 'month-name': ['JANVIER','FÉVRIER','MARS','AVRIL','MAI','JUIN','JUILLET','AOÛT','SEPTEMBRE','OCTOBRE','NOVEMBRE','DÉCEMBRE'], - 'shortcuts' : 'Raccourcis', - 'past': 'Passé', - 'following':'Suivant', - 'previous' : 'Précédent', - 'prev-week' : 'Semaine', - 'prev-month' : 'Mois', - 'prev-year' : 'Année', - 'next':'Suivant', - 'next-week':'Semaine', - 'next-month':'Mois', - 'next-year':'Année', - 'less-than' : 'L\'intervalle ne doit pas être supérieure à %d jours', - 'more-than' : 'L\'intervalle ne doit pas être inférieure à %d jours', - 'default-more' : 'Merci de choisir une intervalle supérieure à %d jours', - 'default-single' : 'Merci de choisir une date', - 'default-less' : 'Merci de choisir une intervalle inférieure %d jours', - 'default-range' : 'Merci de choisir une intervalle comprise entre %d et %d jours', - 'default-default': 'Merci de choisir une date' - } - }; - - - if (window['moment'] === undefined) - { - if (window['console'] && console['warn']) console.warn('Please import moment.js before daterangepicker.js'); - return; - } - - $.fn.dateRangePicker = function(opt) - { - if (!opt) opt = {}; - opt = $.extend(true, - { - autoClose: false, - format: 'YYYY-MM-DD', - separator: ' to ', - language: 'auto', - startOfWeek: 'sunday',// or monday - getValue: function() - { - return $(this).val(); - }, - setValue: function(s) - { - if(!$(this).attr('readonly') && !$(this).is(':disabled')){ - $(this).val(s); - } - }, - startDate: false, - endDate: false, - time: { - enabled: false - }, - minDays: 0, - maxDays: 0, - showShortcuts: true, - shortcuts: - { - //'prev-days': [1,3,5,7], - 'next-days': [3,5,7], - //'prev' : ['week','month','year'], - 'next' : ['week','month','year'] - }, - customShortcuts : [], - inline:false, - container:'body', - alwaysOpen:false, - singleDate:false, - batchMode: false, - duration: 200 - },opt); - - opt.start = false; - opt.end = false; - - if (opt.startDate && typeof opt.startDate == 'string') opt.startDate = moment(opt.startDate,opt.format).toDate(); - if (opt.endDate && typeof opt.endDate == 'string') opt.endDate = moment(opt.endDate,opt.format).toDate(); - - var langs = getLanguages(); - var box; - var initiated = false; - var self = this; - var selfDom = $(self).get(0); - - $(this).unbind('.datepicker').bind('click.datepicker',function(evt) - { - var isOpen = box.is(':visible'); - $(document).trigger('click.datepicker'); - evt.stopPropagation(); - if(!isOpen) open(opt.duration); - }); - - init_datepicker.call(this); - - if (opt.alwaysOpen) - { - open(0); - } - - // expose some api - $(this).data('dateRangePicker', - { - setDateRange : function(d1,d2) - { - if (typeof d1 == 'string' && typeof d2 == 'string') - { - d1 = moment(d1,opt.format).toDate(); - d2 = moment(d2,opt.format).toDate(); - } - setDateRange(d1,d2); - }, - clear: clearSelection, - close: closeDatePicker, - open: open, - getDatePicker: getDatePicker, - destroy: function() - { - $(self).unbind('.datepicker'); - $(self).data('dateRangePicker',''); - box.remove(); - $(window).unbind('resize.datepicker',calcPosition); - $(document).unbind('click.datepicker',closeDatePicker); - } - }); - - $(window).bind('resize.datepicker',calcPosition); - - return this; - - - - - - - - - - - - function init_datepicker() - { - var self = this; - - if ($(this).data('date-picker-opened')) - { - closeDatePicker(); - return; - } - $(this).data('date-picker-opened',true); - - - - - - box = createDom().hide(); - $(opt.container).append(box); - - if (!opt.inline) - { - calcPosition(); - } - else - { - box.addClass("inline-wrapper").css({position:'static'}); - } - - if (opt.alwaysOpen) - { - box.find('.apply-btn').hide(); - } - - var defaultTime = opt.defaultTime ? opt.defaultTime : new Date(); - if (opt.startDate && compare_month(defaultTime,opt.startDate) < 0 ) defaultTime = moment(opt.startDate).toDate(); - if (opt.endDate && compare_month(nextMonth(defaultTime),opt.endDate) > 0 ) defaultTime = prevMonth(moment(opt.endDate).toDate()); - - - showMonth(defaultTime,'month1'); - showMonth(nextMonth(defaultTime),'month2'); - - if (opt.time.enabled) { - if ((opt.startDate && opt.endDate) || (opt.start && opt.end)) { - showTime(moment(opt.start || opt.startDate).toDate(),'time1'); - showTime(moment(opt.end || opt.endDate).toDate(),'time2'); - } else { - showTime(defaultTime,'time1'); - showTime(defaultTime,'time2'); - } - } - - //showSelectedInfo(); - - - - - var defaultTopText = ''; - if (opt.singleDate) - defaultTopText = lang('default-single'); - else if (opt.minDays && opt.maxDays) - defaultTopText = lang('default-range'); - else if (opt.minDays) - defaultTopText = lang('default-more'); - else if (opt.maxDays) - defaultTopText = lang('default-less'); - else - defaultTopText = lang('default-default'); - - box.find('.default-top').html( defaultTopText.replace(/\%d/,opt.minDays).replace(/\%d/,opt.maxDays)); - - - - - setTimeout(function() - { - initiated = true; - },0); - - box.click(function(evt) - { - evt.stopPropagation(); - }); - - $(document).bind('click.datepicker',closeDatePicker); - - box.find('.next').click(function() - { - var isMonth2 = $(this).parents('table').hasClass('month2'); - var month = isMonth2 ? opt.month2 : opt.month1; - month = nextMonth(month); - if (!opt.singleDate && !isMonth2 && compare_month(month,opt.month2) >= 0 || isMonthOutOfBounds(month)) return; - showMonth(month,isMonth2 ? 'month2' : 'month1'); - showGap(); - }); - - box.find('.prev').click(function() - { - var isMonth2 = $(this).parents('table').hasClass('month2'); - var month = isMonth2 ? opt.month2 : opt.month1; - month = prevMonth(month); - //if (isMonth2 && month.getFullYear()+''+month.getMonth() <= opt.month1.getFullYear()+''+opt.month1.getMonth()) return; - if (isMonth2 && compare_month(month,opt.month1) <= 0 || isMonthOutOfBounds(month)) return; - showMonth(month,isMonth2 ? 'month2' : 'month1'); - showGap(); - }); - - - box.bind('click',function(evt) - { - if ($(evt.target).hasClass('day')) - { - dayClicked($(evt.target)); - } - }); - - box.attr('unselectable', 'on') - .css('user-select', 'none') - .bind('selectstart', function(e) - { - e.preventDefault(); return false; - }); - - box.find('.apply-btn').click(function() - { - closeDatePicker(); - var dateRange = getDateString(new Date(opt.start))+ opt.separator +getDateString(new Date(opt.end)); - $(self).trigger('datepicker-apply', - { - 'value': dateRange, - 'date1' : new Date(opt.start), - 'date2' : new Date(opt.end) - }); - }); - - box.find('[shortcut]').click(function() - { - var shortcut = $(this).attr('shortcut'); - var end = new Date(),start = false; - if (shortcut.indexOf('day') != -1) - { - var day = parseInt(shortcut.split(',',2)[1],10); - start = new Date(new Date().getTime() + 86400000*day); - end = new Date(end.getTime() + 86400000*(day>0?1:-1) ); - } - else if (shortcut.indexOf('week')!= -1) - { - var dir = shortcut.indexOf('prev,') != -1 ? -1 : 1; - - if (dir == 1) - var stopDay = opt.startOfWeek == 'monday' ? 1 : 0; - else - var stopDay = opt.startOfWeek == 'monday' ? 0 : 6; - - end = new Date(end.getTime() - 86400000); - while(end.getDay() != stopDay) end = new Date(end.getTime() + dir*86400000); - start = new Date(end.getTime() + dir*86400000*6); - } - else if (shortcut.indexOf('month') != -1) - { - var dir = shortcut.indexOf('prev,') != -1 ? -1 : 1; - if (dir == 1) - start = nextMonth(end); - else - start = prevMonth(end); - start.setDate(1); - end = nextMonth(start); - end.setDate(1); - end = new Date(end.getTime() - 86400000); - } - else if (shortcut.indexOf('year') != -1) - { - var dir = shortcut.indexOf('prev,') != -1 ? -1 : 1; - start = new Date(); - start.setFullYear(end.getFullYear() + dir); - start.setMonth(0); - start.setDate(1); - end.setFullYear(end.getFullYear() + dir); - end.setMonth(11); - end.setDate(31); - } - else if (shortcut == 'custom') - { - var name = $(this).html(); - if (opt.customShortcuts && opt.customShortcuts.length > 0) - { - for(var i=0;i=2)) - { - var ___format = opt.format; - if (___format.match(/Do/)) - { - - ___format = ___format.replace(/Do/,'D'); - defaults[0] = defaults[0].replace(/(\d+)(th|nd|st)/,'$1'); - if(defaults.length >= 2){ - defaults[1] = defaults[1].replace(/(\d+)(th|nd|st)/,'$1'); - } - } - // set initiated to avoid triggerring datepicker-change event - initiated = false; - if(defaults.length >= 2){ - setDateRange(moment(defaults[0], ___format).toDate(),moment(defaults[1], ___format).toDate()); - } - else if(defaults.length==1 && opt.singleDate){ - setSingleDate(moment(defaults[0], ___format).toDate()); - } - - initiated = true; - } - box.slideDown(animationTime); - } - - - - function renderTime (name, date) { - box.find("." + name + " input[type=range].hour-range").val(moment(date).hours()); - box.find("." + name + " input[type=range].minute-range").val(moment(date).minutes()); - setTime(name, moment(date).format("HH"), moment(date).format("mm")); - } - - function changeTime (name, date) { - opt[name] = parseInt( - moment(parseInt(date)) - .startOf('day') - .add('h', moment(opt[name + "Time"]).format("HH")) - .add('m', moment(opt[name + "Time"]).format("mm")).valueOf() - ); - } - - function swapTime () { - renderTime("time1", opt.start); - renderTime("time2", opt.end); - } - - function setTime (name, hour, minute) { - hour && (box.find("." + name + " .hour-val").text(hour)); - minute && (box.find("." + name + " .minute-val").text(minute)); - switch (name) { - case "time1": - if (opt.start) { - setRange("start", moment(opt.start)); - } - setRange("startTime", moment(opt.startTime || moment().valueOf())); - break; - case "time2": - if (opt.end) { - setRange("end", moment(opt.end)); - } - setRange("endTime", moment(opt.endTime || moment().valueOf())); - break; - } - function setRange(name, timePoint) { - var h = timePoint.format("HH"), - m = timePoint.format("mm"); - opt[name] = timePoint - .startOf('day') - .add("h", hour || h) - .add("m", minute || m) - .valueOf(); - } - checkSelectionValid(); - showSelectedInfo(); - showSelectedDays(); - } - - function clearSelection() - { - opt.start = false; - opt.end = false; - box.find('.day.checked').removeClass('checked'); - opt.setValue.call(selfDom, ''); - checkSelectionValid(); - showSelectedInfo(); - showSelectedDays(); - } - - function handleStart(time) - { - var r = time; - if (opt.batchMode === 'week-range') { - if (opt.startOfWeek === 'monday') { - r = moment(parseInt(time)).startOf('isoweek').valueOf(); - } else { - r = moment(parseInt(time)).startOf('week').valueOf(); - } - } else if (opt.batchMode === 'month-range') { - r = moment(parseInt(time)).startOf('month').valueOf(); - } - - return r; - } - - function handleEnd(time) - { - var r = time; - if (opt.batchMode === 'week-range') { - if (opt.startOfWeek === 'monday') { - r = moment(parseInt(time)).endOf('isoweek').valueOf(); - } else { - r = moment(parseInt(time)).endOf('week').valueOf(); - } - } else if (opt.batchMode === 'month') { - r = moment(parseInt(time)).endOf('month').valueOf(); - } - - return r; - } - - - function dayClicked(day) - { - if (day.hasClass('invalid')) return; - var time = day.attr('time'); - day.addClass('checked'); - if ( opt.singleDate ) - { - opt.start = time; - opt.end = false; - if (opt.time.enabled) { - changeTime("start", opt.start); - } - } - else if (opt.batchMode === 'week') - { - if (opt.startOfWeek === 'monday') { - opt.start = moment(parseInt(time)).startOf('isoweek').valueOf(); - opt.end = moment(parseInt(time)).endOf('isoweek').valueOf(); - } else { - opt.end = moment(parseInt(time)).endOf('week').valueOf(); - opt.start = moment(parseInt(time)).startOf('week').valueOf(); - } - } - else if (opt.batchMode === 'month') - { - opt.start = moment(parseInt(time)).startOf('month').valueOf(); - opt.end = moment(parseInt(time)).endOf('month').valueOf(); - } - else if ((opt.start && opt.end) || (!opt.start && !opt.end) ) - { - opt.start = handleStart(time); - opt.end = false; - if (opt.time.enabled) { - changeTime("start", opt.start); - } - } - else if (opt.start) - { - opt.end = handleEnd(time); - if (opt.time.enabled) { - changeTime("end", opt.end); - } - } - - if (!opt.singleDate && opt.start && opt.end && opt.start > opt.end) - { - var tmp = opt.end; - opt.end = handleEnd(opt.start); - opt.start = handleStart(tmp); - if (opt.time.enabled) { - swapTime(); - } - } - - opt.start = parseInt(opt.start); - opt.end = parseInt(opt.end); - - checkSelectionValid(); - showSelectedInfo(); - showSelectedDays(); - autoclose(); - } - - function autoclose () { - if (opt.singleDate === true) { - if (initiated && opt.start ) - { - if (opt.autoClose) closeDatePicker(); - } - } else { - if (initiated && opt.start && opt.end) - { - if (opt.autoClose) closeDatePicker(); - } - } - } - - function checkSelectionValid() - { - var days = Math.ceil( (opt.end - opt.start) / 86400000 ) + 1; - if (opt.singleDate) { // Validate if only start is there - if (opt.start && !opt.end) - box.find('.drp_top-bar').removeClass('error').addClass('normal'); - else - box.find('.drp_top-bar').removeClass('error').removeClass('normal'); - } - else if ( opt.maxDays && days > opt.maxDays) - { - opt.start = false; - opt.end = false; - box.find('.day').removeClass('checked'); - box.find('.drp_top-bar').removeClass('normal').addClass('error').find('.error-top').html( lang('less-than').replace('%d',opt.maxDays) ); - } - else if ( opt.minDays && days < opt.minDays) - { - opt.start = false; - opt.end = false; - box.find('.day').removeClass('checked'); - box.find('.drp_top-bar').removeClass('normal').addClass('error').find('.error-top').html( lang('more-than').replace('%d',opt.minDays) ); - } - else - { - if (opt.start || opt.end) - box.find('.drp_top-bar').removeClass('error').addClass('normal'); - else - box.find('.drp_top-bar').removeClass('error').removeClass('normal'); - } - - if ( (opt.singleDate && opt.start && !opt.end) || (!opt.singleDate && opt.start && opt.end) ) - { - box.find('.apply-btn').removeClass('disabled'); - } - else - { - box.find('.apply-btn').addClass('disabled'); - } - - if (opt.batchMode) - { - if ( (opt.start && opt.startDate && compare_day(opt.start, opt.startDate) < 0) - || (opt.end && opt.endDate && compare_day(opt.end, opt.endDate) > 0) ) - { - opt.start = false; - opt.end = false; - box.find('.day').removeClass('checked'); - } - } - } - - function showSelectedInfo() - { - box.find('.start-day').html('...'); - box.find('.end-day').html('...'); - box.find('.selected-days').hide(); - if (opt.start) - { - box.find('.start-day').html(getDateString(new Date(parseInt(opt.start)))); - } - if (opt.end) - { - box.find('.end-day').html(getDateString(new Date(parseInt(opt.end)))); - } - - if (opt.start && opt.singleDate) - { - box.find('.apply-btn').removeClass('disabled'); - var dateRange = getDateString(new Date(opt.start)); - opt.setValue.call(selfDom, dateRange, getDateString(new Date(opt.start)), getDateString(new Date(opt.end))); - - if (initiated) - { - $(self).trigger('datepicker-change', - { - 'value': dateRange, - 'date1' : new Date(opt.start) - }); - } - } - else if (opt.start && opt.end) - { - box.find('.selected-days').show().find('.selected-days-num').html(Math.round((opt.end-opt.start)/86400000)+1); - box.find('.apply-btn').removeClass('disabled'); - var dateRange = getDateString(new Date(opt.start))+ opt.separator +getDateString(new Date(opt.end)); - opt.setValue.call(selfDom,dateRange, getDateString(new Date(opt.start)), getDateString(new Date(opt.end))); - if (initiated) - { - $(self).trigger('datepicker-change', - { - 'value': dateRange, - 'date1' : new Date(opt.start), - 'date2' : new Date(opt.end) - }); - } - } - else - { - box.find('.apply-btn').addClass('disabled'); - } - } - - function setDateRange(date1,date2) - { - if (date1.getTime() > date2.getTime()) - { - var tmp = date2; - date2 = date1; - date1 = tmp; - tmp = null; - } - var valid = true; - if (opt.startDate && compare_day(date1,opt.startDate) < 0) valid = false; - if (opt.endDate && compare_day(date2,opt.endDate) > 0) valid = false; - if (!valid) - { - showMonth(opt.startDate,'month1'); - showMonth(nextMonth(opt.startDate),'month2'); - showGap(); - return; - } - - opt.start = date1.getTime(); - opt.end = date2.getTime(); - if (compare_day(date1,date2) > 0 && compare_month(date1,date2) == 0) - { - date2 = nextMonth(date1); - } - if (opt.time.enabled) { - renderTime("time1", date1); - renderTime("time2", date2); - } - showMonth(date1,'month1'); - showMonth(date2,'month2'); - showGap(); - showSelectedInfo(); - autoclose(); - } - - function setSingleDate(date1) - { - - var valid = true; - if (opt.startDate && compare_day(date1,opt.startDate) < 0) valid = false; - if (opt.endDate && compare_day(date1,opt.endDate) > 0) valid = false; - if (!valid) - { - showMonth(opt.startDate,'month1'); - - //showGap(); - return; - } - - opt.start = date1.getTime(); - - - if (opt.time.enabled) { - renderTime("time1", date1); - - } - showMonth(date1,'month1'); - //showMonth(date2,'month2'); - showGap(); - showSelectedInfo(); - autoclose(); - } - - function showSelectedDays() - { - if (!opt.start && !opt.end) return; - box.find('.day').each(function() - { - var time = parseInt($(this).attr('time')), - start = opt.start, - end = opt.end; - if (opt.time.enabled) { - time = moment(time).startOf('day').valueOf(); - start = moment(start || moment().valueOf()).startOf('day').valueOf(); - end = moment(end || moment().valueOf()).startOf('day').valueOf(); - } - if ( - (opt.start && opt.end && end >= time && start <= time ) - || ( opt.start && !opt.end && moment(start).format('YYYY-MM-DD') == moment(time).format('YYYY-MM-DD') ) - ) - { - $(this).addClass('checked'); - } - else - { - $(this).removeClass('checked'); - } - }); - } - - function showMonth(date,month) - { - date = moment(date).toDate(); - var monthName = nameMonth(date.getMonth()); - box.find('.'+month+' .month-name').html(monthName+' '+date.getFullYear()); - box.find('.'+month+' tbody').html(createMonthHTML(date)); - opt[month] = date; - } - - function showTime(date,name) - { - box.find('.' + name).append(getTimeHTML()); - renderTime(name, date); - } - - function nameMonth(m) - { - return lang('month-name')[m]; - } - - function getDateString(d) - { - return moment(d).format(opt.format); - } - - function showGap() - { - showSelectedDays(); - var m1 = parseInt(moment(opt.month1).format('YYYYMM')); - var m2 = parseInt(moment(opt.month2).format('YYYYMM')); - var p = Math.abs(m1 - m2); - var shouldShow = (p > 1 && p !=89); - if (shouldShow) - box.find('.gap').show(); - else - box.find('.gap').hide(); - } - - function closeDatePicker() - { - if (opt.alwaysOpen) return; - $(box).slideUp(opt.duration,function() - { - $(self).data('date-picker-opened',false); - }); - //$(document).unbind('.datepicker'); - $(self).trigger('datepicker-close'); - } - - function compare_month(m1,m2) - { - var p = parseInt(moment(m1).format('YYYYMM')) - parseInt(moment(m2).format('YYYYMM')); - if (p > 0 ) return 1; - if (p == 0) return 0; - return -1; - } - - function compare_day(m1,m2) - { - var p = parseInt(moment(m1).format('YYYYMMDD')) - parseInt(moment(m2).format('YYYYMMDD')); - if (p > 0 ) return 1; - if (p == 0) return 0; - return -1; - } - - function nextMonth(month) - { - month = moment(month).toDate(); - var toMonth = month.getMonth(); - while(month.getMonth() == toMonth) month = new Date(month.getTime()+86400000); - return month; - } - - function prevMonth(month) - { - month = moment(month).toDate(); - var toMonth = month.getMonth(); - while(month.getMonth() == toMonth) month = new Date(month.getTime()-86400000); - return month; - } - - function getTimeHTML() - { - var timeHtml = '
    ' - +'Time: 00:00' - +'
    ' - +'
    ' - +'' - +'
    ' - +'
    ' - +'' - +'
    '; - return timeHtml; - } - - function createDom() - { - var html = '
    ' - +'
    \ -
    \ - '+lang('selected')+' ...' - if ( ! opt.singleDate ) { - html += ' '+opt.separator+' ... (3 '+lang('days')+')' - } - html += '
    \ -
    error
    \ -
    default
    \ - \ -
    ' - +'
    ' - +''+getWeekHead()+'
    <January, 2011>
    ' - if ( ! opt.singleDate ) { - html += '
    '+getGapHTML()+'
    ' - +''+getWeekHead()+'
    <January, 2011>
    ' - } - //+'
    ' - html += '
    ' - +'
    ' - +'
    ' - if ( ! opt.singleDate ) { - html += '
    ' - } - html += '
    ' - +'
    ' - +'
    '; - - if (opt.showShortcuts) - { - html += ''; - } - html += '
    '; - - - return $(html); - } - - function getHideClass() - { - if (opt.autoClose === true) { - return 'hide'; - } - return ''; - } - - function getWeekHead() - { - if (opt.startOfWeek == 'monday') - { - return ''+lang('week-1')+'\ - '+lang('week-2')+'\ - '+lang('week-3')+'\ - '+lang('week-4')+'\ - '+lang('week-5')+'\ - '+lang('week-6')+'\ - '+lang('week-7')+''; - } - else - { - return ''+lang('week-7')+'\ - '+lang('week-1')+'\ - '+lang('week-2')+'\ - '+lang('week-3')+'\ - '+lang('week-4')+'\ - '+lang('week-5')+'\ - '+lang('week-6')+''; - } - } - function isMonthOutOfBounds(month) - { - var month = moment(month); - if (opt.startDate && month.endOf('month').isBefore(opt.startDate)) - { - return true; - } - if (opt.endDate && month.startOf('month').isAfter(opt.endDate)) - { - return true; - } - return false; - } - - function getGapHTML() - { - var html = ['
    ']; - for(var i=0;i<20;i++) - { - html.push('
    \ -
    \ -
    \ -
    \ -
    '); - } - html.push('
    '); - return html.join(''); - } - - function createMonthHTML(d) - { - var days = []; - d.setDate(1); - var lastMonth = new Date(d.getTime() - 86400000); - var now = new Date(); - - var dayOfWeek = d.getDay(); - if((dayOfWeek == 0) && (opt.startOfWeek == 'monday')) { - // add one week - dayOfWeek = 7; - } - - if (dayOfWeek > 0) - { - for (var i = dayOfWeek; i > 0; i--) - { - var day = new Date(d.getTime() - 86400000*i); - var valid = true; - if (opt.startDate && compare_day(day,opt.startDate) < 0) valid = false; - if (opt.endDate && compare_day(day,opt.endDate) > 0) valid = false; - days.push({type:'lastMonth',day: day.getDate(),time:day.getTime(), valid:valid }); - } - } - var toMonth = d.getMonth(); - for(var i=0; i<40; i++) - { - var today = moment(d).add(i,'days').toDate(); - var valid = true; - if (opt.startDate && compare_day(today,opt.startDate) < 0) valid = false; - if (opt.endDate && compare_day(today,opt.endDate) > 0) valid = false; - days.push({type: today.getMonth() == toMonth ? 'toMonth' : 'nextMonth',day: today.getDate(),time:today.getTime(), valid:valid }); - } - var html = []; - for(var week=0; week<6; week++) - { - if (days[week*7].type == 'nextMonth') break; - html.push(''); - for(var day = 0; day<7; day++) - { - var _day = (opt.startOfWeek == 'monday') ? day+1 : day; - var today = days[week*7+_day]; - var highlightToday = moment(today.time).format('L') == moment(now).format('L'); - today.extraClass = ''; - today.tooltip = ''; - if(opt.beforeShowDay && typeof opt.beforeShowDay == 'function') - { - var _r = opt.beforeShowDay(moment(today.time).toDate()); - today.valid = _r[0]; - today.extraClass = _r[1] || ''; - today.tooltip = _r[2] || ''; - if (today.tooltip != '') today.extraClass += ' has-tooltip '; - } - html.push('
    '+today.day+'
    '); - } - html.push(''); - } - return html.join(''); - } - - function getLanguages() - { - if (opt.language == 'auto') - { - var language = navigator.language ? navigator.language : navigator.browserLanguage; - if (!language) return $.dateRangePickerLanguages['en']; - var language = language.toLowerCase(); - for(var key in $.dateRangePickerLanguages) - { - if (language.indexOf(key) != -1) - { - return $.dateRangePickerLanguages[key]; - } - } - return $.dateRangePickerLanguages['en']; - } - else if ( opt.language && opt.language in $.dateRangePickerLanguages) - { - return $.dateRangePickerLanguages[opt.language]; - } - else - { - return $.dateRangePickerLanguages['en']; - } - } - - function lang(t) - { - return (t in langs)? langs[t] : t; - } - - - }; -})(jQuery); diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/moment.min.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/moment.min.js deleted file mode 100644 index d0b48f73..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/moment.min.js +++ /dev/null @@ -1,7 +0,0 @@ -//! moment.js -//! version : 2.10.2 -//! authors : Tim Wood, Iskren Chernev, Moment.js contributors -//! license : MIT -//! momentjs.com -!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return Ac.apply(null,arguments)}function b(a){Ac=a}function c(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function d(a){return"[object Array]"===Object.prototype.toString.call(a)}function e(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function f(a,b){var c,d=[];for(c=0;c0)for(c in Cc)d=Cc[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function m(b){l(this,b),this._d=new Date(+b._d),Dc===!1&&(Dc=!0,a.updateOffset(this),Dc=!1)}function n(a){return a instanceof m||null!=a&&g(a,"_isAMomentObject")}function o(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function p(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&o(a[d])!==o(b[d]))&&g++;return g+f}function q(){}function r(a){return a?a.toLowerCase().replace("_","-"):a}function s(a){for(var b,c,d,e,f=0;f0;){if(d=t(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&p(e,c,!0)>=b-1)break;b--}f++}return null}function t(a){var b=null;if(!Ec[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=Bc._abbr,require("./locale/"+a),u(b)}catch(c){}return Ec[a]}function u(a,b){var c;return a&&(c="undefined"==typeof b?w(a):v(a,b),c&&(Bc=c)),Bc._abbr}function v(a,b){return null!==b?(b.abbr=a,Ec[a]||(Ec[a]=new q),Ec[a].set(b),u(a),Ec[a]):(delete Ec[a],null)}function w(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return Bc;if(!d(a)){if(b=t(a))return b;a=[a]}return s(a)}function x(a,b){var c=a.toLowerCase();Fc[c]=Fc[c+"s"]=Fc[b]=a}function y(a){return"string"==typeof a?Fc[a]||Fc[a.toLowerCase()]:void 0}function z(a){var b,c,d={};for(c in a)g(a,c)&&(b=y(c),b&&(d[b]=a[c]));return d}function A(b,c){return function(d){return null!=d?(C(this,b,d),a.updateOffset(this,c),this):B(this,b)}}function B(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function C(a,b,c){return a._d["set"+(a._isUTC?"UTC":"")+b](c)}function D(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=y(a),"function"==typeof this[a])return this[a](b);return this}function E(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.lengthb;b++)d[b]=Jc[d[b]]?Jc[d[b]]:G(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function I(a,b){return a.isValid()?(b=J(b,a.localeData()),Ic[b]||(Ic[b]=H(b)),Ic[b](a)):a.localeData().invalidDate()}function J(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Hc.lastIndex=0;d>=0&&Hc.test(a);)a=a.replace(Hc,c),Hc.lastIndex=0,d-=1;return a}function K(a,b,c){Yc[a]="function"==typeof b?b:function(a){return a&&c?c:b}}function L(a,b){return g(Yc,a)?Yc[a](b._strict,b._locale):new RegExp(M(a))}function M(a){return a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function N(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=o(a)}),c=0;cd;d++){if(e=i([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function U(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),Q(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function V(b){return null!=b?(U(this,b),a.updateOffset(this,!0),this):B(this,"Month")}function W(){return Q(this.year(),this.month())}function X(a){var b,c=a._a;return c&&-2===a._pf.overflow&&(b=c[_c]<0||c[_c]>11?_c:c[ad]<1||c[ad]>Q(c[$c],c[_c])?ad:c[bd]<0||c[bd]>24||24===c[bd]&&(0!==c[cd]||0!==c[dd]||0!==c[ed])?bd:c[cd]<0||c[cd]>59?cd:c[dd]<0||c[dd]>59?dd:c[ed]<0||c[ed]>999?ed:-1,a._pf._overflowDayOfYear&&($c>b||b>ad)&&(b=ad),a._pf.overflow=b),a}function Y(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function Z(a,b){var c=!0;return h(function(){return c&&(Y(a),c=!1),b.apply(this,arguments)},b)}function $(a,b){hd[a]||(Y(b),hd[a]=!0)}function _(a){var b,c,d=a._i,e=id.exec(d);if(e){for(a._pf.iso=!0,b=0,c=jd.length;c>b;b++)if(jd[b][1].exec(d)){a._f=jd[b][0]+(e[6]||" ");break}for(b=0,c=kd.length;c>b;b++)if(kd[b][1].exec(d)){a._f+=kd[b][0];break}d.match(Vc)&&(a._f+="Z"),sa(a)}else a._isValid=!1}function aa(b){var c=ld.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(_(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function ba(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function ca(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function da(a){return ea(a)?366:365}function ea(a){return a%4===0&&a%100!==0||a%400===0}function fa(){return ea(this.year())}function ga(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=za(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ha(a){return ga(a,this._week.dow,this._week.doy).week}function ia(){return this._week.dow}function ja(){return this._week.doy}function ka(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function la(a){var b=ga(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function ma(a,b,c,d,e){var f,g,h=ca(a,0,1).getUTCDay();return h=0===h?7:h,c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:da(a-1)+g}}function na(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function oa(a,b,c){return null!=a?a:null!=b?b:c}function pa(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function qa(a){var b,c,d,e,f=[];if(!a._d){for(d=pa(a),a._w&&null==a._a[ad]&&null==a._a[_c]&&ra(a),a._dayOfYear&&(e=oa(a._a[$c],d[$c]),a._dayOfYear>da(e)&&(a._pf._overflowDayOfYear=!0),c=ca(e,0,a._dayOfYear),a._a[_c]=c.getUTCMonth(),a._a[ad]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[bd]&&0===a._a[cd]&&0===a._a[dd]&&0===a._a[ed]&&(a._nextDay=!0,a._a[bd]=0),a._d=(a._useUTC?ca:ba).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[bd]=24)}}function ra(a){var b,c,d,e,f,g,h;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=oa(b.GG,a._a[$c],ga(za(),1,4).year),d=oa(b.W,1),e=oa(b.E,1)):(f=a._locale._week.dow,g=a._locale._week.doy,c=oa(b.gg,a._a[$c],ga(za(),f,g).year),d=oa(b.w,1),null!=b.d?(e=b.d,f>e&&++d):e=null!=b.e?b.e+f:f),h=ma(c,d,e,g,f),a._a[$c]=h.year,a._dayOfYear=h.dayOfYear}function sa(b){if(b._f===a.ISO_8601)return void _(b);b._a=[],b._pf.empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=J(b._f,b._locale).match(Gc)||[],c=0;c0&&b._pf.unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),Jc[f]?(d?b._pf.empty=!1:b._pf.unusedTokens.push(f),P(f,d,b)):b._strict&&!d&&b._pf.unusedTokens.push(f);b._pf.charsLeftOver=i-j,h.length>0&&b._pf.unusedInput.push(h),b._pf.bigHour===!0&&b._a[bd]<=12&&(b._pf.bigHour=void 0),b._a[bd]=ta(b._locale,b._a[bd],b._meridiem),qa(b),X(b)}function ta(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function ua(a){var b,d,e,f,g;if(0===a._f.length)return a._pf.invalidFormat=!0,void(a._d=new Date(0/0));for(f=0;fg)&&(e=g,d=b));h(a,d||b)}function va(a){if(!a._d){var b=z(a._i);a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],qa(a)}}function wa(a){var b,c=a._i,e=a._f;return a._locale=a._locale||w(a._l),null===c||void 0===e&&""===c?k({nullInput:!0}):("string"==typeof c&&(a._i=c=a._locale.preparse(c)),n(c)?new m(X(c)):(d(e)?ua(a):e?sa(a):xa(a),b=new m(X(a)),b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b))}function xa(b){var c=b._i;void 0===c?b._d=new Date:e(c)?b._d=new Date(+c):"string"==typeof c?aa(b):d(c)?(b._a=f(c.slice(0),function(a){return parseInt(a,10)}),qa(b)):"object"==typeof c?va(b):"number"==typeof c?b._d=new Date(c):a.createFromInputFallback(b)}function ya(a,b,d,e,f){var g={};return"boolean"==typeof d&&(e=d,d=void 0),g._isAMomentObject=!0,g._useUTC=g._isUTC=f,g._l=d,g._i=a,g._f=b,g._strict=e,g._pf=c(),wa(g)}function za(a,b,c,d){return ya(a,b,c,d,!1)}function Aa(a,b){var c,e;if(1===b.length&&d(b[0])&&(b=b[0]),!b.length)return za();for(c=b[0],e=1;ea&&(a=-a,c="-"),c+E(~~(a/60),2)+b+E(~~a%60,2)})}function Ga(a){var b=(a||"").match(Vc)||[],c=b[b.length-1]||[],d=(c+"").match(qd)||["-",0,0],e=+(60*d[1])+o(d[2]);return"+"===d[0]?e:-e}function Ha(b,c){var d,f;return c._isUTC?(d=c.clone(),f=(n(b)||e(b)?+b:+za(b))-+d,d._d.setTime(+d._d+f),a.updateOffset(d,!1),d):za(b).local();return c._isUTC?za(b).zone(c._offset||0):za(b).local()}function Ia(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Ja(b,c){var d,e=this._offset||0;return null!=b?("string"==typeof b&&(b=Ga(b)),Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ia(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?Za(this,Ua(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ia(this)}function Ka(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function La(a){return this.utcOffset(0,a)}function Ma(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ia(this),"m")),this}function Na(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ga(this._i)),this}function Oa(a){return a=a?za(a).utcOffset():0,(this.utcOffset()-a)%60===0}function Pa(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Qa(){if(this._a){var a=this._isUTC?i(this._a):za(this._a);return this.isValid()&&p(this._a,a.toArray())>0}return!1}function Ra(){return!this._isUTC}function Sa(){return this._isUTC}function Ta(){return this._isUTC&&0===this._offset}function Ua(a,b){var c,d,e,f=a,h=null;return Ea(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(f={},b?f[b]=a:f.milliseconds=a):(h=rd.exec(a))?(c="-"===h[1]?-1:1,f={y:0,d:o(h[ad])*c,h:o(h[bd])*c,m:o(h[cd])*c,s:o(h[dd])*c,ms:o(h[ed])*c}):(h=sd.exec(a))?(c="-"===h[1]?-1:1,f={y:Va(h[2],c),M:Va(h[3],c),d:Va(h[4],c),h:Va(h[5],c),m:Va(h[6],c),s:Va(h[7],c),w:Va(h[8],c)}):null==f?f={}:"object"==typeof f&&("from"in f||"to"in f)&&(e=Xa(za(f.from),za(f.to)),f={},f.ms=e.milliseconds,f.M=e.months),d=new Da(f),Ea(a)&&g(a,"_locale")&&(d._locale=a._locale),d}function Va(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function Wa(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function Xa(a,b){var c;return b=Ha(b,a),a.isBefore(b)?c=Wa(a,b):(c=Wa(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function Ya(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||($(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Ua(c,d),Za(this,e,a),this}}function Za(b,c,d,e){var f=c._milliseconds,g=c._days,h=c._months;e=null==e?!0:e,f&&b._d.setTime(+b._d+f*d),g&&C(b,"Date",B(b,"Date")+g*d),h&&U(b,B(b,"Month")+h*d),e&&a.updateOffset(b,g||h)}function $a(a){var b=a||za(),c=Ha(b,this).startOf("day"),d=this.diff(c,"days",!0),e=-6>d?"sameElse":-1>d?"lastWeek":0>d?"lastDay":1>d?"sameDay":2>d?"nextDay":7>d?"nextWeek":"sameElse";return this.format(this.localeData().calendar(e,this,za(b)))}function _a(){return new m(this)}function ab(a,b){var c;return b=y("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=n(a)?a:za(a),+this>+a):(c=n(a)?+a:+za(a),c<+this.clone().startOf(b))}function bb(a,b){var c;return b=y("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=n(a)?a:za(a),+a>+this):(c=n(a)?+a:+za(a),+this.clone().endOf(b)a?Math.ceil(a):Math.floor(a)}function fb(a,b,c){var d,e,f=Ha(a,this),g=6e4*(f.utcOffset()-this.utcOffset());return b=y(b),"year"===b||"month"===b||"quarter"===b?(e=gb(this,f),"quarter"===b?e/=3:"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:eb(e)}function gb(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function hb(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function ib(){var a=this.clone().utc();return 0b;b++)if(this._weekdaysParse[b]||(c=za([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b}function Jb(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Eb(a,this.localeData()),this.add(a-b,"d")):b}function Kb(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Lb(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)}function Mb(a,b){F(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function Nb(a,b){return b._meridiemParse}function Ob(a){return"p"===(a+"").toLowerCase().charAt(0)}function Pb(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Qb(a){F(0,[a,3],0,"millisecond")}function Rb(){return this._isUTC?"UTC":""}function Sb(){return this._isUTC?"Coordinated Universal Time":""}function Tb(a){return za(1e3*a)}function Ub(){return za.apply(null,arguments).parseZone()}function Vb(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.call(b,c):d}function Wb(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b}function Xb(){return this._invalidDate}function Yb(a){return this._ordinal.replace("%d",a)}function Zb(a){return a}function $b(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)}function _b(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)}function ac(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function bc(a,b,c,d){var e=w(),f=i().set(d,b);return e[c](f,a)}function cc(a,b,c,d,e){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return bc(a,b,c,e);var f,g=[];for(f=0;d>f;f++)g[f]=bc(a,f,c,e);return g}function dc(a,b){return cc(a,b,"months",12,"month")}function ec(a,b){return cc(a,b,"monthsShort",12,"month")}function fc(a,b){return cc(a,b,"weekdays",7,"day")}function gc(a,b){return cc(a,b,"weekdaysShort",7,"day")}function hc(a,b){return cc(a,b,"weekdaysMin",7,"day")}function ic(){var a=this._data;return this._milliseconds=Od(this._milliseconds),this._days=Od(this._days),this._months=Od(this._months),a.milliseconds=Od(a.milliseconds),a.seconds=Od(a.seconds),a.minutes=Od(a.minutes),a.hours=Od(a.hours),a.months=Od(a.months),a.years=Od(a.years),this}function jc(a,b,c,d){var e=Ua(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function kc(a,b){return jc(this,a,b,1)}function lc(a,b){return jc(this,a,b,-1)}function mc(){var a,b,c,d=this._milliseconds,e=this._days,f=this._months,g=this._data,h=0;return g.milliseconds=d%1e3,a=eb(d/1e3),g.seconds=a%60,b=eb(a/60),g.minutes=b%60,c=eb(b/60),g.hours=c%24,e+=eb(c/24),h=eb(nc(e)),e-=eb(oc(h)),f+=eb(e/30),e%=30,h+=eb(f/12),f%=12,g.days=e,g.months=f,g.years=h,this}function nc(a){return 400*a/146097}function oc(a){return 146097*a/400}function pc(a){var b,c,d=this._milliseconds;if(a=y(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+12*nc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(oc(this._months/12)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 24*b*60+d/6e4;case"second":return 24*b*60*60+d/1e3;case"millisecond":return Math.floor(24*b*60*60*1e3)+d;default:throw new Error("Unknown unit "+a)}}function qc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*o(this._months/12)}function rc(a){return function(){return this.as(a)}}function sc(a){return a=y(a),this[a+"s"]()}function tc(a){return function(){return this._data[a]}}function uc(){return eb(this.days()/7)}function vc(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function wc(a,b,c){var d=Ua(a).abs(),e=ce(d.as("s")),f=ce(d.as("m")),g=ce(d.as("h")),h=ce(d.as("d")),i=ce(d.as("M")),j=ce(d.as("y")),k=e0,k[4]=c,vc.apply(null,k)}function xc(a,b){return void 0===de[a]?!1:void 0===b?de[a]:(de[a]=b,!0)}function yc(a){var b=this.localeData(),c=wc(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function zc(){var a=ee(this.years()),b=ee(this.months()),c=ee(this.days()),d=ee(this.hours()),e=ee(this.minutes()),f=ee(this.seconds()+this.milliseconds()/1e3),g=this.asSeconds();return g?(0>g?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"}var Ac,Bc,Cc=a.momentProperties=[],Dc=!1,Ec={},Fc={},Gc=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,Hc=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Ic={},Jc={},Kc=/\d/,Lc=/\d\d/,Mc=/\d{3}/,Nc=/\d{4}/,Oc=/[+-]?\d{6}/,Pc=/\d\d?/,Qc=/\d{1,3}/,Rc=/\d{1,4}/,Sc=/[+-]?\d{1,6}/,Tc=/\d+/,Uc=/[+-]?\d+/,Vc=/Z|[+-]\d\d:?\d\d/gi,Wc=/[+-]?\d+(\.\d{1,3})?/,Xc=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Yc={},Zc={},$c=0,_c=1,ad=2,bd=3,cd=4,dd=5,ed=6;F("M",["MM",2],"Mo",function(){return this.month()+1}),F("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),F("MMMM",0,0,function(a){return this.localeData().months(this,a)}),x("month","M"),K("M",Pc),K("MM",Pc,Lc),K("MMM",Xc),K("MMMM",Xc),N(["M","MM"],function(a,b){b[_c]=o(a)-1}),N(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[_c]=e:c._pf.invalidMonth=a});var fd="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),gd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),hd={};a.suppressDeprecationWarnings=!1;var id=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,jd=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],kd=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],ld=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=Z("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),F(0,["YY",2],0,function(){return this.year()%100}),F(0,["YYYY",4],0,"year"),F(0,["YYYYY",5],0,"year"),F(0,["YYYYYY",6,!0],0,"year"),x("year","y"),K("Y",Uc),K("YY",Pc,Lc),K("YYYY",Rc,Nc),K("YYYYY",Sc,Oc),K("YYYYYY",Sc,Oc),N(["YYYY","YYYYY","YYYYYY"],$c),N("YY",function(b,c){c[$c]=a.parseTwoDigitYear(b)}),a.parseTwoDigitYear=function(a){return o(a)+(o(a)>68?1900:2e3)};var md=A("FullYear",!1);F("w",["ww",2],"wo","week"),F("W",["WW",2],"Wo","isoWeek"),x("week","w"),x("isoWeek","W"),K("w",Pc),K("ww",Pc,Lc),K("W",Pc),K("WW",Pc,Lc),O(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=o(a)});var nd={dow:0,doy:6};F("DDD",["DDDD",3],"DDDo","dayOfYear"),x("dayOfYear","DDD"),K("DDD",Qc),K("DDDD",Mc),N(["DDD","DDDD"],function(a,b,c){c._dayOfYear=o(a)}),a.ISO_8601=function(){};var od=Z("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=za.apply(null,arguments);return this>a?this:a}),pd=Z("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=za.apply(null,arguments);return a>this?this:a});Fa("Z",":"),Fa("ZZ",""),K("Z",Vc),K("ZZ",Vc),N(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ga(a)});var qd=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var rd=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,sd=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;Ua.fn=Da.prototype;var td=Ya(1,"add"),ud=Ya(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";var vd=Z("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});F(0,["gg",2],0,function(){return this.weekYear()%100}),F(0,["GG",2],0,function(){return this.isoWeekYear()%100}),xb("gggg","weekYear"),xb("ggggg","weekYear"),xb("GGGG","isoWeekYear"),xb("GGGGG","isoWeekYear"),x("weekYear","gg"),x("isoWeekYear","GG"),K("G",Uc),K("g",Uc),K("GG",Pc,Lc),K("gg",Pc,Lc),K("GGGG",Rc,Nc),K("gggg",Rc,Nc),K("GGGGG",Sc,Oc),K("ggggg",Sc,Oc),O(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=o(a)}),O(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),F("Q",0,0,"quarter"),x("quarter","Q"),K("Q",Kc),N("Q",function(a,b){b[_c]=3*(o(a)-1)}),F("D",["DD",2],"Do","date"),x("date","D"),K("D",Pc),K("DD",Pc,Lc),K("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),N(["D","DD"],ad),N("Do",function(a,b){b[ad]=o(a.match(Pc)[0],10)});var wd=A("Date",!0);F("d",0,"do","day"),F("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),F("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),F("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),F("e",0,0,"weekday"),F("E",0,0,"isoWeekday"),x("day","d"),x("weekday","e"),x("isoWeekday","E"),K("d",Pc),K("e",Pc),K("E",Pc),K("dd",Xc),K("ddd",Xc),K("dddd",Xc),O(["dd","ddd","dddd"],function(a,b,c){var d=c._locale.weekdaysParse(a);null!=d?b.d=d:c._pf.invalidWeekday=a}),O(["d","e","E"],function(a,b,c,d){b[d]=o(a)});var xd="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),yd="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),zd="Su_Mo_Tu_We_Th_Fr_Sa".split("_");F("H",["HH",2],0,"hour"),F("h",["hh",2],0,function(){return this.hours()%12||12}),Mb("a",!0),Mb("A",!1),x("hour","h"),K("a",Nb),K("A",Nb),K("H",Pc),K("h",Pc),K("HH",Pc,Lc),K("hh",Pc,Lc),N(["H","HH"],bd),N(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),N(["h","hh"],function(a,b,c){b[bd]=o(a),c._pf.bigHour=!0});var Ad=/[ap]\.?m?\.?/i,Bd=A("Hours",!0);F("m",["mm",2],0,"minute"),x("minute","m"),K("m",Pc),K("mm",Pc,Lc),N(["m","mm"],cd);var Cd=A("Minutes",!1);F("s",["ss",2],0,"second"),x("second","s"),K("s",Pc),K("ss",Pc,Lc),N(["s","ss"],dd);var Dd=A("Seconds",!1);F("S",0,0,function(){return~~(this.millisecond()/100)}),F(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),Qb("SSS"),Qb("SSSS"),x("millisecond","ms"),K("S",Qc,Kc),K("SS",Qc,Lc),K("SSS",Qc,Mc),K("SSSS",Tc),N(["S","SS","SSS","SSSS"],function(a,b){b[ed]=o(1e3*("0."+a))});var Ed=A("Milliseconds",!1);F("z",0,0,"zoneAbbr"),F("zz",0,0,"zoneName");var Fd=m.prototype;Fd.add=td,Fd.calendar=$a,Fd.clone=_a,Fd.diff=fb,Fd.endOf=pb,Fd.format=jb,Fd.from=kb,Fd.fromNow=lb,Fd.get=D,Fd.invalidAt=wb,Fd.isAfter=ab,Fd.isBefore=bb,Fd.isBetween=cb,Fd.isSame=db,Fd.isValid=ub,Fd.lang=vd,Fd.locale=mb,Fd.localeData=nb,Fd.max=pd,Fd.min=od,Fd.parsingFlags=vb,Fd.set=D,Fd.startOf=ob,Fd.subtract=ud,Fd.toArray=tb,Fd.toDate=sb,Fd.toISOString=ib,Fd.toJSON=ib,Fd.toString=hb,Fd.unix=rb,Fd.valueOf=qb,Fd.year=md,Fd.isLeapYear=fa,Fd.weekYear=zb,Fd.isoWeekYear=Ab,Fd.quarter=Fd.quarters=Db,Fd.month=V,Fd.daysInMonth=W,Fd.week=Fd.weeks=ka,Fd.isoWeek=Fd.isoWeeks=la,Fd.weeksInYear=Cb,Fd.isoWeeksInYear=Bb,Fd.date=wd,Fd.day=Fd.days=Jb,Fd.weekday=Kb,Fd.isoWeekday=Lb,Fd.dayOfYear=na,Fd.hour=Fd.hours=Bd,Fd.minute=Fd.minutes=Cd,Fd.second=Fd.seconds=Dd,Fd.millisecond=Fd.milliseconds=Ed,Fd.utcOffset=Ja,Fd.utc=La,Fd.local=Ma,Fd.parseZone=Na,Fd.hasAlignedHourOffset=Oa,Fd.isDST=Pa,Fd.isDSTShifted=Qa,Fd.isLocal=Ra,Fd.isUtcOffset=Sa,Fd.isUtc=Ta,Fd.isUTC=Ta,Fd.zoneAbbr=Rb,Fd.zoneName=Sb,Fd.dates=Z("dates accessor is deprecated. Use date instead.",wd),Fd.months=Z("months accessor is deprecated. Use month instead",V),Fd.years=Z("years accessor is deprecated. Use year instead",md),Fd.zone=Z("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Ka);var Gd=Fd,Hd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Id={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM D, YYYY LT"},Jd="Invalid date",Kd="%d",Ld=/\d{1,2}/,Md={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Nd=q.prototype;Nd._calendar=Hd,Nd.calendar=Vb,Nd._longDateFormat=Id,Nd.longDateFormat=Wb,Nd._invalidDate=Jd,Nd.invalidDate=Xb,Nd._ordinal=Kd,Nd.ordinal=Yb,Nd._ordinalParse=Ld, -Nd.preparse=Zb,Nd.postformat=Zb,Nd._relativeTime=Md,Nd.relativeTime=$b,Nd.pastFuture=_b,Nd.set=ac,Nd.months=R,Nd._months=fd,Nd.monthsShort=S,Nd._monthsShort=gd,Nd.monthsParse=T,Nd.week=ha,Nd._week=nd,Nd.firstDayOfYear=ja,Nd.firstDayOfWeek=ia,Nd.weekdays=Fb,Nd._weekdays=xd,Nd.weekdaysMin=Hb,Nd._weekdaysMin=zd,Nd.weekdaysShort=Gb,Nd._weekdaysShort=yd,Nd.weekdaysParse=Ib,Nd.isPM=Ob,Nd._meridiemParse=Ad,Nd.meridiem=Pb,u("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===o(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=Z("moment.lang is deprecated. Use moment.locale instead.",u),a.langData=Z("moment.langData is deprecated. Use moment.localeData instead.",w);var Od=Math.abs,Pd=rc("ms"),Qd=rc("s"),Rd=rc("m"),Sd=rc("h"),Td=rc("d"),Ud=rc("w"),Vd=rc("M"),Wd=rc("y"),Xd=tc("milliseconds"),Yd=tc("seconds"),Zd=tc("minutes"),$d=tc("hours"),_d=tc("days"),ae=tc("months"),be=tc("years"),ce=Math.round,de={s:45,m:45,h:22,d:26,M:11},ee=Math.abs,fe=Da.prototype;fe.abs=ic,fe.add=kc,fe.subtract=lc,fe.as=pc,fe.asMilliseconds=Pd,fe.asSeconds=Qd,fe.asMinutes=Rd,fe.asHours=Sd,fe.asDays=Td,fe.asWeeks=Ud,fe.asMonths=Vd,fe.asYears=Wd,fe.valueOf=qc,fe._bubble=mc,fe.get=sc,fe.milliseconds=Xd,fe.seconds=Yd,fe.minutes=Zd,fe.hours=$d,fe.days=_d,fe.weeks=uc,fe.months=ae,fe.years=be,fe.humanize=yc,fe.toISOString=zc,fe.toString=zc,fe.toJSON=zc,fe.locale=mb,fe.localeData=nb,fe.toIsoString=Z("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",zc),fe.lang=vd,F("X",0,0,"unix"),F("x",0,0,"valueOf"),K("x",Uc),K("X",Wc),N("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),N("x",function(a,b,c){c._d=new Date(o(a))}),a.version="2.10.2",b(za),a.fn=Gd,a.min=Ba,a.max=Ca,a.utc=i,a.unix=Tb,a.months=dc,a.isDate=e,a.locale=u,a.invalid=k,a.duration=Ua,a.isMoment=n,a.weekdays=fc,a.parseZone=Ub,a.localeData=w,a.isDuration=Ea,a.monthsShort=ec,a.weekdaysMin=hc,a.defineLocale=v,a.weekdaysShort=gc,a.normalizeUnits=y,a.relativeTimeThreshold=xc;var ge=a;return ge}); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/nv.d3.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/nv.d3.js deleted file mode 100644 index 949a04d5..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/nv.d3.js +++ /dev/null @@ -1,13435 +0,0 @@ -/* nvd3 version 1.8.1 (https://github.com/novus/nvd3) 2015-06-17 */ -(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: - callback: - }) - - or - - nv.addGraph(, ) - - 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 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 . 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 container, - it will actually trigger it for all the child elements (like , , 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 += ""; - 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
    with scrollbars, subtract the scroll offsets. - //You need to also add any offset between the element and its containing
    - //Finally, add any offset of the containing
    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 = true //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','') - .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 '' + - '

    ' + data.value + '

    ' + - '' + - '' + - '' + - '' + - '' + - '
    open:' + chart.yAxis.tickFormat()(d.open) + '
    close:' + chart.yAxis.tickFormat()(d.close) + '
    high' + chart.yAxis.tickFormat()(d.high) + '
    low:' + chart.yAxis.tickFormat()(d.low) + '
    '; - }); - 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 '' + - '

    ' + data.value + '

    ' + - '' + - '' + - '' + - '' + - '' + - '
    open:' + chart.yAxis.tickFormat()(d.open) + '
    close:' + chart.yAxis.tickFormat()(d.close) + '
    high' + chart.yAxis.tickFormat()(d.high) + '
    low:' + chart.yAxis.tickFormat()(d.low) + '
    '; - }); - 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','') - .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); - // We don't want any points emitted for the focus chart's scatter graph. - lines2.pointActive(function(d) { return 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; - }}, - focusMargin: {get: function(){return margin2;}, set: function(_){ - margin2.top = _.top !== undefined ? _.top : margin2.top; - margin2.right = _.right !== undefined ? _.right : margin2.right; - margin2.bottom = _.bottom !== undefined ? _.bottom : margin2.bottom; - margin2.left = _.left !== undefined ? _.left : margin2.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); - // We don't want any points emitted for the focus chart's scatter graph. - lines2.pointActive(function(d) { return 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; - }}, - focusMargin: {get: function(){return margin2;}, set: function(_){ - margin2.top = _.top !== undefined ? _.top : margin2.top; - margin2.right = _.right !== undefined ? _.right : margin2.right; - margin2.bottom = _.bottom !== undefined ? _.bottom : margin2.bottom; - margin2.left = _.left !== undefined ? _.left : margin2.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', 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), - - scatters1 = nv.models.scatter().yScale(yScale1), - scatters2 = nv.models.scatter().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 dataScatters1 = data.filter(function(d) {return d.type == 'scatter' && d.yAxis == 1}); - var dataScatters2 = data.filter(function(d) {return d.type == 'scatter' && 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', 'scatters1Wrap'); - gEnter.append('g').attr('class', 'scatters2Wrap'); - 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'})); - scatters1 - .width(availableWidth) - .height(availableHeight) - .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'scatter'})); - scatters2 - .width(availableWidth) - .height(availableHeight) - .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'scatter'})); - 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 scatters1Wrap = g.select('.scatters1Wrap') - .datum(dataScatters1.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 scatters2Wrap = g.select('.scatters2Wrap') - .datum(dataScatters2.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()); - scatters1.yDomain(yScale1.domain()); - bars1.yDomain(yScale1.domain()); - stack1.yDomain(yScale1.domain()); - - lines2.yDomain(yScale2.domain()); - scatters2.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);} - - if(dataScatters1.length){d3.transition(scatters1Wrap).call(scatters1);} - if(dataScatters2.length){d3.transition(scatters2Wrap).call(scatters2);} - - 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_scatter(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) - }); - - scatters1.dispatch.on('elementMouseover.tooltip', mouseover_scatter); - scatters2.dispatch.on('elementMouseover.tooltip', mouseover_scatter); - scatters1.dispatch.on('elementMouseout.tooltip', function(evt) { - tooltip.hidden(true) - }); - scatters2.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.scatters1 = scatters1; - chart.scatters2 = scatters2; - 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(_); - scatters1.x(_); - scatters2.x(_); - bars1.x(_); - bars2.x(_); - stack1.x(_); - stack2.x(_); - }}, - y: {get: function(){return getY;}, set: function(_){ - getY = _; - lines1.y(_); - lines2.y(_); - scatters1.y(_); - scatters2.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-"+id+"-"+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-"+id+"-"+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) { - d.color = d.color || color(d, i); - return d.color; - }).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() { container.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(); - } - - 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/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/rickshaw.min.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/rickshaw.min.js deleted file mode 100644 index bd576991..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/rickshaw.min.js +++ /dev/null @@ -1,3 +0,0 @@ -(function(root,factory){if(typeof define==="function"&&define.amd){define(["d3"],function(d3){return root.Rickshaw=factory(d3)})}else if(typeof exports==="object"){module.exports=factory(require("d3"))}else{root.Rickshaw=factory(d3)}})(this,function(d3){var Rickshaw={namespace:function(namespace,obj){var parts=namespace.split(".");var parent=Rickshaw;for(var i=1,length=parts.length;i0){var x=s.data[0].x;var y=s.data[0].y;if(typeof x!="number"||typeof y!="number"&&y!==null){throw"x and y properties of points should be numbers instead of "+typeof x+" and "+typeof y}}if(s.data.length>=3){if(s.data[2].xthis.window.xMax)isInRange=false;return isInRange}return true};this.onUpdate=function(callback){this.updateCallbacks.push(callback)};this.onConfigure=function(callback){this.configureCallbacks.push(callback)};this.registerRenderer=function(renderer){this._renderers=this._renderers||{};this._renderers[renderer.name]=renderer};this.configure=function(args){this.config=this.config||{};if(args.width||args.height){this.setSize(args)}Rickshaw.keys(this.defaults).forEach(function(k){this.config[k]=k in args?args[k]:k in this?this[k]:this.defaults[k]},this);Rickshaw.keys(this.config).forEach(function(k){this[k]=this.config[k]},this);if("stack"in args)args.unstack=!args.stack;var renderer=args.renderer||this.renderer&&this.renderer.name||"stack";this.setRenderer(renderer,args);this.configureCallbacks.forEach(function(callback){callback(args)})};this.setRenderer=function(r,args){if(typeof r=="function"){this.renderer=new r({graph:self});this.registerRenderer(this.renderer)}else{if(!this._renderers[r]){throw"couldn't find renderer "+r}this.renderer=this._renderers[r]}if(typeof args=="object"){this.renderer.configure(args)}};this.setSize=function(args){args=args||{};if(typeof window!==undefined){var style=window.getComputedStyle(this.element,null);var elementWidth=parseInt(style.getPropertyValue("width"),10);var elementHeight=parseInt(style.getPropertyValue("height"),10)}this.width=args.width||elementWidth||400;this.height=args.height||elementHeight||250;this.vis&&this.vis.attr("width",this.width).attr("height",this.height)};this.initialize(args)};Rickshaw.namespace("Rickshaw.Fixtures.Color");Rickshaw.Fixtures.Color=function(){this.schemes={};this.schemes.spectrum14=["#ecb796","#dc8f70","#b2a470","#92875a","#716c49","#d2ed82","#bbe468","#a1d05d","#e7cbe6","#d8aad6","#a888c2","#9dc2d3","#649eb9","#387aa3"].reverse();this.schemes.spectrum2000=["#57306f","#514c76","#646583","#738394","#6b9c7d","#84b665","#a7ca50","#bfe746","#e2f528","#fff726","#ecdd00","#d4b11d","#de8800","#de4800","#c91515","#9a0000","#7b0429","#580839","#31082b"];this.schemes.spectrum2001=["#2f243f","#3c2c55","#4a3768","#565270","#6b6b7c","#72957f","#86ad6e","#a1bc5e","#b8d954","#d3e04e","#ccad2a","#cc8412","#c1521d","#ad3821","#8a1010","#681717","#531e1e","#3d1818","#320a1b"];this.schemes.classic9=["#423d4f","#4a6860","#848f39","#a2b73c","#ddcb53","#c5a32f","#7d5836","#963b20","#7c2626","#491d37","#2f254a"].reverse();this.schemes.httpStatus={503:"#ea5029",502:"#d23f14",500:"#bf3613",410:"#efacea",409:"#e291dc",403:"#f457e8",408:"#e121d2",401:"#b92dae",405:"#f47ceb",404:"#a82a9f",400:"#b263c6",301:"#6fa024",302:"#87c32b",307:"#a0d84c",304:"#28b55c",200:"#1a4f74",206:"#27839f",201:"#52adc9",202:"#7c979f",203:"#a5b8bd",204:"#c1cdd1"};this.schemes.colorwheel=["#b5b6a9","#858772","#785f43","#96557e","#4682b4","#65b9ac","#73c03a","#cb513a"].reverse();this.schemes.cool=["#5e9d2f","#73c03a","#4682b4","#7bc3b8","#a9884e","#c1b266","#a47493","#c09fb5"];this.schemes.munin=["#00cc00","#0066b3","#ff8000","#ffcc00","#330099","#990099","#ccff00","#ff0000","#808080","#008f00","#00487d","#b35a00","#b38f00","#6b006b","#8fb300","#b30000","#bebebe","#80ff80","#80c9ff","#ffc080","#ffe680","#aa80ff","#ee00cc","#ff8080","#666600","#ffbfff","#00ffcc","#cc6699","#999900"]};Rickshaw.namespace("Rickshaw.Fixtures.RandomData");Rickshaw.Fixtures.RandomData=function(timeInterval){var addData;timeInterval=timeInterval||1;var lastRandomValue=200;var timeBase=Math.floor((new Date).getTime()/1e3);this.addData=function(data){var randomValue=Math.random()*100+15+lastRandomValue;var index=data[0].length;var counter=1;data.forEach(function(series){var randomVariance=Math.random()*20;var v=randomValue/25+counter++ +(Math.cos(index*counter*11/960)+2)*15+(Math.cos(index/7)+2)*7+(Math.cos(index/17)+2)*1;series.push({x:index*timeInterval+timeBase,y:v+randomVariance})});lastRandomValue=randomValue*.85};this.removeData=function(data){data.forEach(function(series){series.shift()});timeBase+=timeInterval}};Rickshaw.namespace("Rickshaw.Fixtures.Time");Rickshaw.Fixtures.Time=function(){var self=this;this.months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];this.units=[{name:"decade",seconds:86400*365.25*10,formatter:function(d){return parseInt(d.getUTCFullYear()/10,10)*10}},{name:"year",seconds:86400*365.25,formatter:function(d){return d.getUTCFullYear()}},{name:"month",seconds:86400*30.5,formatter:function(d){return self.months[d.getUTCMonth()]}},{name:"week",seconds:86400*7,formatter:function(d){return self.formatDate(d)}},{name:"day",seconds:86400,formatter:function(d){return d.getUTCDate()}},{name:"6 hour",seconds:3600*6,formatter:function(d){return self.formatTime(d)}},{name:"hour",seconds:3600,formatter:function(d){return self.formatTime(d)}},{name:"15 minute",seconds:60*15,formatter:function(d){return self.formatTime(d)}},{name:"minute",seconds:60,formatter:function(d){return d.getUTCMinutes()}},{name:"15 second",seconds:15,formatter:function(d){return d.getUTCSeconds()+"s"}},{name:"second",seconds:1,formatter:function(d){return d.getUTCSeconds()+"s"}},{name:"decisecond",seconds:1/10,formatter:function(d){return d.getUTCMilliseconds()+"ms"}},{name:"centisecond",seconds:1/100,formatter:function(d){return d.getUTCMilliseconds()+"ms"}}];this.unit=function(unitName){return this.units.filter(function(unit){return unitName==unit.name}).shift()};this.formatDate=function(d){return d3.time.format("%b %e")(d)};this.formatTime=function(d){return d.toUTCString().match(/(\d+:\d+):/)[1]};this.ceil=function(time,unit){var date,floor,year;if(unit.name=="month"){date=new Date(time*1e3);floor=Date.UTC(date.getUTCFullYear(),date.getUTCMonth())/1e3;if(floor==time)return time;year=date.getUTCFullYear();var month=date.getUTCMonth();if(month==11){month=0;year=year+1}else{month+=1}return Date.UTC(year,month)/1e3}if(unit.name=="year"){date=new Date(time*1e3);floor=Date.UTC(date.getUTCFullYear(),0)/1e3;if(floor==time)return time;year=date.getUTCFullYear()+1;return Date.UTC(year,0)/1e3}return Math.ceil(time/unit.seconds)*unit.seconds}};Rickshaw.namespace("Rickshaw.Fixtures.Time.Local");Rickshaw.Fixtures.Time.Local=function(){var self=this;this.months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];this.units=[{name:"decade",seconds:86400*365.25*10,formatter:function(d){return parseInt(d.getFullYear()/10,10)*10}},{name:"year",seconds:86400*365.25,formatter:function(d){return d.getFullYear()}},{name:"month",seconds:86400*30.5,formatter:function(d){return self.months[d.getMonth()]}},{name:"week",seconds:86400*7,formatter:function(d){return self.formatDate(d)}},{name:"day",seconds:86400,formatter:function(d){return d.getDate()}},{name:"6 hour",seconds:3600*6,formatter:function(d){return self.formatTime(d)}},{name:"hour",seconds:3600,formatter:function(d){return self.formatTime(d)}},{name:"15 minute",seconds:60*15,formatter:function(d){return self.formatTime(d)}},{name:"minute",seconds:60,formatter:function(d){return d.getMinutes()}},{name:"15 second",seconds:15,formatter:function(d){return d.getSeconds()+"s"}},{name:"second",seconds:1,formatter:function(d){return d.getSeconds()+"s"}},{name:"decisecond",seconds:1/10,formatter:function(d){return d.getMilliseconds()+"ms"}},{name:"centisecond",seconds:1/100,formatter:function(d){return d.getMilliseconds()+"ms"}}];this.unit=function(unitName){return this.units.filter(function(unit){return unitName==unit.name}).shift()};this.formatDate=function(d){return d3.time.format("%b %e")(d)};this.formatTime=function(d){return d.toString().match(/(\d+:\d+):/)[1]};this.ceil=function(time,unit){var date,floor,year;if(unit.name=="day"){var nearFuture=new Date((time+unit.seconds-1)*1e3);var rounded=new Date(0);rounded.setMilliseconds(0);rounded.setSeconds(0);rounded.setMinutes(0);rounded.setHours(0);rounded.setDate(nearFuture.getDate());rounded.setMonth(nearFuture.getMonth());rounded.setFullYear(nearFuture.getFullYear());return rounded.getTime()/1e3}if(unit.name=="month"){date=new Date(time*1e3);floor=new Date(date.getFullYear(),date.getMonth()).getTime()/1e3;if(floor==time)return time;year=date.getFullYear();var month=date.getMonth();if(month==11){month=0;year=year+1}else{month+=1}return new Date(year,month).getTime()/1e3}if(unit.name=="year"){date=new Date(time*1e3);floor=new Date(date.getUTCFullYear(),0).getTime()/1e3;if(floor==time)return time;year=date.getFullYear()+1;return new Date(year,0).getTime()/1e3}return Math.ceil(time/unit.seconds)*unit.seconds}};Rickshaw.namespace("Rickshaw.Fixtures.Number");Rickshaw.Fixtures.Number.formatKMBT=function(y){var abs_y=Math.abs(y);if(abs_y>=1e12){return y/1e12+"T"}else if(abs_y>=1e9){return y/1e9+"B"}else if(abs_y>=1e6){return y/1e6+"M"}else if(abs_y>=1e3){return y/1e3+"K"}else if(abs_y<1&&y>0){return y.toFixed(2)}else if(abs_y===0){return""}else{return y}};Rickshaw.Fixtures.Number.formatBase1024KMGTP=function(y){var abs_y=Math.abs(y);if(abs_y>=0x4000000000000){return y/0x4000000000000+"P"}else if(abs_y>=1099511627776){return y/1099511627776+"T"}else if(abs_y>=1073741824){return y/1073741824+"G"}else if(abs_y>=1048576){return y/1048576+"M"}else if(abs_y>=1024){return y/1024+"K"}else if(abs_y<1&&y>0){return y.toFixed(2)}else if(abs_y===0){return""}else{return y}};Rickshaw.namespace("Rickshaw.Color.Palette");Rickshaw.Color.Palette=function(args){var color=new Rickshaw.Fixtures.Color;args=args||{};this.schemes={};this.scheme=color.schemes[args.scheme]||args.scheme||color.schemes.colorwheel;this.runningIndex=0;this.generatorIndex=0;if(args.interpolatedStopCount){var schemeCount=this.scheme.length-1;var i,j,scheme=[];for(i=0;iself.graph.x.range()[1]){if(annotation.element){annotation.line.classList.add("offscreen");annotation.element.style.display="none"}annotation.boxes.forEach(function(box){if(box.rangeElement)box.rangeElement.classList.add("offscreen")});return}if(!annotation.element){var element=annotation.element=document.createElement("div");element.classList.add("annotation");this.elements.timeline.appendChild(element);element.addEventListener("click",function(e){element.classList.toggle("active");annotation.line.classList.toggle("active");annotation.boxes.forEach(function(box){if(box.rangeElement)box.rangeElement.classList.toggle("active")})},false)}annotation.element.style.left=left+"px";annotation.element.style.display="block";annotation.boxes.forEach(function(box){var element=box.element;if(!element){element=box.element=document.createElement("div");element.classList.add("content");element.innerHTML=box.content;annotation.element.appendChild(element);annotation.line=document.createElement("div");annotation.line.classList.add("annotation_line");self.graph.element.appendChild(annotation.line);if(box.end){box.rangeElement=document.createElement("div");box.rangeElement.classList.add("annotation_range");self.graph.element.appendChild(box.rangeElement)}}if(box.end){var annotationRangeStart=left;var annotationRangeEnd=Math.min(self.graph.x(box.end),self.graph.x.range()[1]);if(annotationRangeStart>annotationRangeEnd){annotationRangeEnd=left;annotationRangeStart=Math.max(self.graph.x(box.end),self.graph.x.range()[0])}var annotationRangeWidth=annotationRangeEnd-annotationRangeStart;box.rangeElement.style.left=annotationRangeStart+"px";box.rangeElement.style.width=annotationRangeWidth+"px";box.rangeElement.classList.remove("offscreen")}annotation.line.classList.remove("offscreen");annotation.line.style.left=left+"px"})},this)};this.graph.onUpdate(function(){self.update()})};Rickshaw.namespace("Rickshaw.Graph.Axis.Time");Rickshaw.Graph.Axis.Time=function(args){var self=this;this.graph=args.graph;this.elements=[];this.ticksTreatment=args.ticksTreatment||"plain";this.fixedTimeUnit=args.timeUnit;var time=args.timeFixture||new Rickshaw.Fixtures.Time;this.appropriateTimeUnit=function(){var unit;var units=time.units;var domain=this.graph.x.domain();var rangeSeconds=domain[1]-domain[0];units.forEach(function(u){if(Math.floor(rangeSeconds/u.seconds)>=2){unit=unit||u}});return unit||time.units[time.units.length-1]};this.tickOffsets=function(){var domain=this.graph.x.domain();var unit=this.fixedTimeUnit||this.appropriateTimeUnit();var count=Math.ceil((domain[1]-domain[0])/unit.seconds);var runningTick=domain[0];var offsets=[];for(var i=0;iself.graph.x.range()[1])return;var element=document.createElement("div");element.style.left=self.graph.x(o.value)+"px";element.classList.add("x_tick");element.classList.add(self.ticksTreatment);var title=document.createElement("div");title.classList.add("title");title.innerHTML=o.unit.formatter(new Date(o.value*1e3));element.appendChild(title);self.graph.element.appendChild(element);self.elements.push(element)})};this.graph.onUpdate(function(){self.render()})};Rickshaw.namespace("Rickshaw.Graph.Axis.X");Rickshaw.Graph.Axis.X=function(args){var self=this;var berthRate=.1;this.initialize=function(args){this.graph=args.graph;this.orientation=args.orientation||"top";this.pixelsPerTick=args.pixelsPerTick||75;if(args.ticks)this.staticTicks=args.ticks;if(args.tickValues)this.tickValues=args.tickValues;this.tickSize=args.tickSize||4;this.ticksTreatment=args.ticksTreatment||"plain";if(args.element){this.element=args.element;this._discoverSize(args.element,args);this.vis=d3.select(args.element).append("svg:svg").attr("height",this.height).attr("width",this.width).attr("class","rickshaw_graph x_axis_d3");this.element=this.vis[0][0];this.element.style.position="relative";this.setSize({width:args.width,height:args.height})}else{this.vis=this.graph.vis}this.graph.onUpdate(function(){self.render()})};this.setSize=function(args){args=args||{};if(!this.element)return;this._discoverSize(this.element.parentNode,args);this.vis.attr("height",this.height).attr("width",this.width*(1+berthRate));var berth=Math.floor(this.width*berthRate/2);this.element.style.left=-1*berth+"px"};this.render=function(){if(this._renderWidth!==undefined&&this.graph.width!==this._renderWidth)this.setSize({auto:true});var axis=d3.svg.axis().scale(this.graph.x).orient(this.orientation);axis.tickFormat(args.tickFormat||function(x){return x});if(this.tickValues)axis.tickValues(this.tickValues);this.ticks=this.staticTicks||Math.floor(this.graph.width/this.pixelsPerTick);var berth=Math.floor(this.width*berthRate/2)||0;var transform;if(this.orientation=="top"){var yOffset=this.height||this.graph.height;transform="translate("+berth+","+yOffset+")"}else{transform="translate("+berth+", 0)"}if(this.element){this.vis.selectAll("*").remove()}this.vis.append("svg:g").attr("class",["x_ticks_d3",this.ticksTreatment].join(" ")).attr("transform",transform).call(axis.ticks(this.ticks).tickSubdivide(0).tickSize(this.tickSize));var gridSize=(this.orientation=="bottom"?1:-1)*this.graph.height;this.graph.vis.append("svg:g").attr("class","x_grid_d3").call(axis.ticks(this.ticks).tickSubdivide(0).tickSize(gridSize)).selectAll("text").each(function(){this.parentNode.setAttribute("data-x-value",this.textContent)});this._renderHeight=this.graph.height};this._discoverSize=function(element,args){if(typeof window!=="undefined"){var style=window.getComputedStyle(element,null);var elementHeight=parseInt(style.getPropertyValue("height"),10);if(!args.auto){var elementWidth=parseInt(style.getPropertyValue("width"),10)}}this.width=(args.width||elementWidth||this.graph.width)*(1+berthRate);this.height=args.height||elementHeight||40};this.initialize(args)};Rickshaw.namespace("Rickshaw.Graph.Axis.Y");Rickshaw.Graph.Axis.Y=Rickshaw.Class.create({initialize:function(args){this.graph=args.graph;this.orientation=args.orientation||"right";this.pixelsPerTick=args.pixelsPerTick||75;if(args.ticks)this.staticTicks=args.ticks;if(args.tickValues)this.tickValues=args.tickValues;this.tickSize=args.tickSize||4;this.ticksTreatment=args.ticksTreatment||"plain";this.tickFormat=args.tickFormat||function(y){return y};this.berthRate=.1;if(args.element){this.element=args.element;this.vis=d3.select(args.element).append("svg:svg").attr("class","rickshaw_graph y_axis");this.element=this.vis[0][0];this.element.style.position="relative";this.setSize({width:args.width,height:args.height})}else{this.vis=this.graph.vis}var self=this;this.graph.onUpdate(function(){self.render()})},setSize:function(args){args=args||{};if(!this.element)return;if(typeof window!=="undefined"){var style=window.getComputedStyle(this.element.parentNode,null);var elementWidth=parseInt(style.getPropertyValue("width"),10);if(!args.auto){var elementHeight=parseInt(style.getPropertyValue("height"),10)}}this.width=args.width||elementWidth||this.graph.width*this.berthRate;this.height=args.height||elementHeight||this.graph.height;this.vis.attr("width",this.width).attr("height",this.height*(1+this.berthRate));var berth=this.height*this.berthRate;if(this.orientation=="left"){this.element.style.top=-1*berth+"px"}},render:function(){if(this._renderHeight!==undefined&&this.graph.height!==this._renderHeight)this.setSize({auto:true});this.ticks=this.staticTicks||Math.floor(this.graph.height/this.pixelsPerTick);var axis=this._drawAxis(this.graph.y);this._drawGrid(axis);this._renderHeight=this.graph.height},_drawAxis:function(scale){var axis=d3.svg.axis().scale(scale).orient(this.orientation);axis.tickFormat(this.tickFormat);if(this.tickValues)axis.tickValues(this.tickValues);if(this.orientation=="left"){var berth=this.height*this.berthRate;var transform="translate("+this.width+", "+berth+")"}if(this.element){this.vis.selectAll("*").remove()}this.vis.append("svg:g").attr("class",["y_ticks",this.ticksTreatment].join(" ")).attr("transform",transform).call(axis.ticks(this.ticks).tickSubdivide(0).tickSize(this.tickSize));return axis},_drawGrid:function(axis){var gridSize=(this.orientation=="right"?1:-1)*this.graph.width;this.graph.vis.append("svg:g").attr("class","y_grid").call(axis.ticks(this.ticks).tickSubdivide(0).tickSize(gridSize)).selectAll("text").each(function(){this.parentNode.setAttribute("data-y-value",this.textContent) -})}});Rickshaw.namespace("Rickshaw.Graph.Axis.Y.Scaled");Rickshaw.Graph.Axis.Y.Scaled=Rickshaw.Class.create(Rickshaw.Graph.Axis.Y,{initialize:function($super,args){if(typeof args.scale==="undefined"){throw new Error("Scaled requires scale")}this.scale=args.scale;if(typeof args.grid==="undefined"){this.grid=true}else{this.grid=args.grid}$super(args)},_drawAxis:function($super,scale){var domain=this.scale.domain();var renderDomain=this.graph.renderer.domain().y;var extents=[Math.min.apply(Math,domain),Math.max.apply(Math,domain)];var extentMap=d3.scale.linear().domain([0,1]).range(extents);var adjExtents=[extentMap(renderDomain[0]),extentMap(renderDomain[1])];var adjustment=d3.scale.linear().domain(extents).range(adjExtents);var adjustedScale=this.scale.copy().domain(domain.map(adjustment)).range(scale.range());return $super(adjustedScale)},_drawGrid:function($super,axis){if(this.grid){$super(axis)}}});Rickshaw.namespace("Rickshaw.Graph.Behavior.Series.Highlight");Rickshaw.Graph.Behavior.Series.Highlight=function(args){this.graph=args.graph;this.legend=args.legend;var self=this;var colorSafe={};var activeLine=null;var disabledColor=args.disabledColor||function(seriesColor){return d3.interpolateRgb(seriesColor,d3.rgb("#d8d8d8"))(.8).toString()};this.addHighlightEvents=function(l){l.element.addEventListener("mouseover",function(e){if(activeLine)return;else activeLine=l;self.legend.lines.forEach(function(line){if(l===line){if(self.graph.renderer.unstack&&(line.series.renderer?line.series.renderer.unstack:true)){var seriesIndex=self.graph.series.indexOf(line.series);line.originalIndex=seriesIndex;var series=self.graph.series.splice(seriesIndex,1)[0];self.graph.series.push(series)}return}colorSafe[line.series.name]=colorSafe[line.series.name]||line.series.color;line.series.color=disabledColor(line.series.color)});self.graph.update()},false);l.element.addEventListener("mouseout",function(e){if(!activeLine)return;else activeLine=null;self.legend.lines.forEach(function(line){if(l===line&&line.hasOwnProperty("originalIndex")){var series=self.graph.series.pop();self.graph.series.splice(line.originalIndex,0,series);delete line.originalIndex}if(colorSafe[line.series.name]){line.series.color=colorSafe[line.series.name]}});self.graph.update()},false)};if(this.legend){this.legend.lines.forEach(function(l){self.addHighlightEvents(l)})}};Rickshaw.namespace("Rickshaw.Graph.Behavior.Series.Order");Rickshaw.Graph.Behavior.Series.Order=function(args){this.graph=args.graph;this.legend=args.legend;var self=this;if(typeof window.jQuery=="undefined"){throw"couldn't find jQuery at window.jQuery"}if(typeof window.jQuery.ui=="undefined"){throw"couldn't find jQuery UI at window.jQuery.ui"}jQuery(function(){jQuery(self.legend.list).sortable({containment:"parent",tolerance:"pointer",update:function(event,ui){var series=[];jQuery(self.legend.list).find("li").each(function(index,item){if(!item.series)return;series.push(item.series)});for(var i=self.graph.series.length-1;i>=0;i--){self.graph.series[i]=series.shift()}self.graph.update()}});jQuery(self.legend.list).disableSelection()});this.graph.onUpdate(function(){var h=window.getComputedStyle(self.legend.element).height;self.legend.element.style.height=h})};Rickshaw.namespace("Rickshaw.Graph.Behavior.Series.Toggle");Rickshaw.Graph.Behavior.Series.Toggle=function(args){this.graph=args.graph;this.legend=args.legend;var self=this;this.addAnchor=function(line){var anchor=document.createElement("a");anchor.innerHTML="✔";anchor.classList.add("action");line.element.insertBefore(anchor,line.element.firstChild);anchor.onclick=function(e){if(line.series.disabled){line.series.enable();line.element.classList.remove("disabled")}else{if(this.graph.series.filter(function(s){return!s.disabled}).length<=1)return;line.series.disable();line.element.classList.add("disabled")}self.graph.update()}.bind(this);var label=line.element.getElementsByTagName("span")[0];label.onclick=function(e){var disableAllOtherLines=line.series.disabled;if(!disableAllOtherLines){for(var i=0;idomainX){dataIndex=Math.abs(domainX-data[i].x)0){alignables.forEach(function(el){el.classList.remove("left");el.classList.add("right")});var rightAlignError=this._calcLayoutError(alignables);if(rightAlignError>leftAlignError){alignables.forEach(function(el){el.classList.remove("right");el.classList.add("left")})}}if(typeof this.onRender=="function"){this.onRender(args)}},_calcLayoutError:function(alignables){var parentRect=this.element.parentNode.getBoundingClientRect();var error=0;var alignRight=alignables.forEach(function(el){var rect=el.getBoundingClientRect();if(!rect.width){return}if(rect.right>parentRect.right){error+=rect.right-parentRect.right}if(rect.left=self.previewWidth){frameAfterDrag[0]-=frameAfterDrag[1]-self.previewWidth;frameAfterDrag[1]=self.previewWidth}}self.graphs.forEach(function(graph){var domainScale=d3.scale.linear().interpolate(d3.interpolateNumber).domain([0,self.previewWidth]).range(graph.dataDomain());var windowAfterDrag=[domainScale(frameAfterDrag[0]),domainScale(frameAfterDrag[1])];self.slideCallbacks.forEach(function(callback){callback(graph,windowAfterDrag[0],windowAfterDrag[1])});if(frameAfterDrag[0]===0){windowAfterDrag[0]=undefined}if(frameAfterDrag[1]===self.previewWidth){windowAfterDrag[1]=undefined}graph.window.xMin=windowAfterDrag[0];graph.window.xMax=windowAfterDrag[1];graph.update()})}function onMousedown(){drag.target=d3.event.target;drag.start=self._getClientXFromEvent(d3.event,drag);self.frameBeforeDrag=self.currentFrame.slice();d3.event.preventDefault?d3.event.preventDefault():d3.event.returnValue=false;d3.select(document).on("mousemove.rickshaw_range_slider_preview",onMousemove);d3.select(document).on("mouseup.rickshaw_range_slider_preview",onMouseup);d3.select(document).on("touchmove.rickshaw_range_slider_preview",onMousemove);d3.select(document).on("touchend.rickshaw_range_slider_preview",onMouseup);d3.select(document).on("touchcancel.rickshaw_range_slider_preview",onMouseup)}function onMousedownLeftHandle(datum,index){drag.left=true;onMousedown()}function onMousedownRightHandle(datum,index){drag.right=true;onMousedown()}function onMousedownMiddleHandle(datum,index){drag.left=true;drag.right=true;drag.rigid=true;onMousedown()}function onMouseup(datum,index){d3.select(document).on("mousemove.rickshaw_range_slider_preview",null);d3.select(document).on("mouseup.rickshaw_range_slider_preview",null);d3.select(document).on("touchmove.rickshaw_range_slider_preview",null);d3.select(document).on("touchend.rickshaw_range_slider_preview",null);d3.select(document).on("touchcancel.rickshaw_range_slider_preview",null);delete self.frameBeforeDrag;drag.left=false;drag.right=false;drag.rigid=false}element.select("rect.left_handle").on("mousedown",onMousedownLeftHandle);element.select("rect.right_handle").on("mousedown",onMousedownRightHandle);element.select("rect.middle_handle").on("mousedown",onMousedownMiddleHandle);element.select("rect.left_handle").on("touchstart",onMousedownLeftHandle);element.select("rect.right_handle").on("touchstart",onMousedownRightHandle);element.select("rect.middle_handle").on("touchstart",onMousedownMiddleHandle)},_getClientXFromEvent:function(event,drag){switch(event.type){case"touchstart":case"touchmove":var touchList=event.changedTouches;var touch=null;for(var touchIndex=0;touchIndexyMax)yMax=y});if(!series.length)return;if(series[0].xxMax)xMax=series[series.length-1].x});xMin-=(xMax-xMin)*this.padding.left;xMax+=(xMax-xMin)*this.padding.right;yMin=this.graph.min==="auto"?yMin:this.graph.min||0;yMax=this.graph.max===undefined?yMax:this.graph.max;if(this.graph.min==="auto"||yMin<0){yMin-=(yMax-yMin)*this.padding.bottom}if(this.graph.max===undefined){yMax+=(yMax-yMin)*this.padding.top}return{x:[xMin,xMax],y:[yMin,yMax]}},render:function(args){args=args||{};var graph=this.graph;var series=args.series||graph.series;var vis=args.vis||graph.vis;vis.selectAll("*").remove();var data=series.filter(function(s){return!s.disabled}).map(function(s){return s.stack});var pathNodes=vis.selectAll("path.path").data(data).enter().append("svg:path").classed("path",true).attr("d",this.seriesPathFactory());if(this.stroke){var strokeNodes=vis.selectAll("path.stroke").data(data).enter().append("svg:path").classed("stroke",true).attr("d",this.seriesStrokeFactory())}var i=0;series.forEach(function(series){if(series.disabled)return;series.path=pathNodes[0][i];if(this.stroke)series.stroke=strokeNodes[0][i];this._styleSeries(series);i++},this)},_styleSeries:function(series){var fill=this.fill?series.color:"none";var stroke=this.stroke?series.color:"none";series.path.setAttribute("fill",fill);series.path.setAttribute("stroke",stroke);series.path.setAttribute("stroke-width",this.strokeWidth);if(series.className){d3.select(series.path).classed(series.className,true)}if(series.className&&this.stroke){d3.select(series.stroke).classed(series.className,true)}},configure:function(args){args=args||{};Rickshaw.keys(this.defaults()).forEach(function(key){if(!args.hasOwnProperty(key)){this[key]=this[key]||this.graph[key]||this.defaults()[key];return}if(typeof this.defaults()[key]=="object"){Rickshaw.keys(this.defaults()[key]).forEach(function(k){this[key][k]=args[key][k]!==undefined?args[key][k]:this[key][k]!==undefined?this[key][k]:this.defaults()[key][k]},this)}else{this[key]=args[key]!==undefined?args[key]:this[key]!==undefined?this[key]:this.graph[key]!==undefined?this.graph[key]:this.defaults()[key]}},this)},setStrokeWidth:function(strokeWidth){if(strokeWidth!==undefined){this.strokeWidth=strokeWidth}},setTension:function(tension){if(tension!==undefined){this.tension=tension}}});Rickshaw.namespace("Rickshaw.Graph.Renderer.Line");Rickshaw.Graph.Renderer.Line=Rickshaw.Class.create(Rickshaw.Graph.Renderer,{name:"line",defaults:function($super){return Rickshaw.extend($super(),{unstack:true,fill:false,stroke:true})},seriesPathFactory:function(){var graph=this.graph;var factory=d3.svg.line().x(function(d){return graph.x(d.x)}).y(function(d){return graph.y(d.y)}).interpolate(this.graph.interpolation).tension(this.tension);factory.defined&&factory.defined(function(d){return d.y!==null});return factory}});Rickshaw.namespace("Rickshaw.Graph.Renderer.Stack");Rickshaw.Graph.Renderer.Stack=Rickshaw.Class.create(Rickshaw.Graph.Renderer,{name:"stack",defaults:function($super){return Rickshaw.extend($super(),{fill:true,stroke:false,unstack:false})},seriesPathFactory:function(){var graph=this.graph;var factory=d3.svg.area().x(function(d){return graph.x(d.x)}).y0(function(d){return graph.y(d.y0)}).y1(function(d){return graph.y(d.y+d.y0)}).interpolate(this.graph.interpolation).tension(this.tension);factory.defined&&factory.defined(function(d){return d.y!==null});return factory}});Rickshaw.namespace("Rickshaw.Graph.Renderer.Bar");Rickshaw.Graph.Renderer.Bar=Rickshaw.Class.create(Rickshaw.Graph.Renderer,{name:"bar",defaults:function($super){var defaults=Rickshaw.extend($super(),{gapSize:.05,unstack:false});delete defaults.tension;return defaults},initialize:function($super,args){args=args||{};this.gapSize=args.gapSize||this.gapSize;$super(args)},domain:function($super){var domain=$super();var frequentInterval=this._frequentInterval(this.graph.stackedData.slice(-1).shift());domain.x[1]+=Number(frequentInterval.magnitude);return domain},barWidth:function(series){var frequentInterval=this._frequentInterval(series.stack);var barWidth=this.graph.x.magnitude(frequentInterval.magnitude)*(1-this.gapSize);return barWidth},render:function(args){args=args||{};var graph=this.graph;var series=args.series||graph.series;var vis=args.vis||graph.vis;vis.selectAll("*").remove();var barWidth=this.barWidth(series.active()[0]);var barXOffset=0;var activeSeriesCount=series.filter(function(s){return!s.disabled}).length;var seriesBarWidth=this.unstack?barWidth/activeSeriesCount:barWidth;var transform=function(d){var matrix=[1,0,0,d.y<0?-1:1,0,d.y<0?graph.y.magnitude(Math.abs(d.y))*2:0];return"matrix("+matrix.join(",")+")"};series.forEach(function(series){if(series.disabled)return;var barWidth=this.barWidth(series);var nodes=vis.selectAll("path").data(series.stack.filter(function(d){return d.y!==null})).enter().append("svg:rect").attr("x",function(d){return graph.x(d.x)+barXOffset}).attr("y",function(d){return graph.y(d.y0+Math.abs(d.y))*(d.y<0?-1:1)}).attr("width",seriesBarWidth).attr("height",function(d){return graph.y.magnitude(Math.abs(d.y))}).attr("transform",transform);Array.prototype.forEach.call(nodes[0],function(n){n.setAttribute("fill",series.color)});if(this.unstack)barXOffset+=seriesBarWidth},this)},_frequentInterval:function(data){var intervalCounts={};for(var i=0;i0){this[0].data.forEach(function(plot){item.data.push({x:plot.x,y:0})})}else if(item.data.length===0){item.data.push({x:this.timeBase-(this.timeInterval||0),y:0})}this.push(item);if(this.legend){this.legend.addLine(this.itemByName(item.name))}},addData:function(data,x){var index=this.getIndex();Rickshaw.keys(data).forEach(function(name){if(!this.itemByName(name)){this.addItem({name:name})}},this);this.forEach(function(item){item.data.push({x:x||(index*this.timeInterval||1)+this.timeBase,y:data[item.name]||0})},this)},getIndex:function(){return this[0]&&this[0].data&&this[0].data.length?this[0].data.length:0},itemByName:function(name){for(var i=0;i1;i--){this.currentSize+=1;this.currentIndex+=1;this.forEach(function(item){item.data.unshift({x:((i-1)*this.timeInterval||1)+this.timeBase,y:0,i:i})},this)}}},addData:function($super,data,x){$super(data,x);this.currentSize+=1;this.currentIndex+=1;if(this.maxDataPoints!==undefined){while(this.currentSize>this.maxDataPoints){this.dropData()}}},dropData:function(){this.forEach(function(item){item.data.splice(0,1)});this.currentSize-=1},getIndex:function(){return this.currentIndex}});return Rickshaw}); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/stream_layers.js b/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/stream_layers.js deleted file mode 100644 index 43d7cfe0..00000000 --- a/modules/distribution/src/repository/jaggeryapps/iot/units/mydevice/public/js/stream_layers.js +++ /dev/null @@ -1,35 +0,0 @@ - -/* Inspired by Lee Byron's test data generator. */ -function stream_layers(n, m, o) { - if (arguments.length < 3) o = 0; - function bump(a) { - var x = 1 / (.1 + Math.random()), - y = 2 * Math.random() - .5, - z = 10 / (.1 + Math.random()); - for (var i = 0; i < m; i++) { - var w = (i / m - y) * z; - a[i] += x * Math.exp(-w * w); - } - } - return d3.range(n).map(function() { - var a = [], i; - for (i = 0; i < m; i++) a[i] = o + o * Math.random(); - for (i = 0; i < 5; i++) bump(a); - return a.map(stream_index); - }); -} - -/* Another layer generator using gamma distributions. */ -function stream_waves(n, m) { - return d3.range(n).map(function(i) { - return d3.range(m).map(function(j) { - var x = 20 * j / m - i / 3; - return 2 * x * Math.exp(-.5 * x); - }).map(stream_index); - }); -} - -function stream_index(d, i) { - return {x: i, y: Math.max(0, d)}; -} - diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/showcase/public/images/RaspberryPi.png b/modules/distribution/src/repository/jaggeryapps/iot/units/showcase/public/images/RaspberryPi.png deleted file mode 100644 index eb0e28cb26fd12e71a6645a8f35be731e2e268a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8006 zcmaJ`byQUSx+WYEq(PJrM!JTsp&RLjp_BoJj&T@5KsqEOhDN%Zp^-*P8UYFE2I&$h zy?oy}-?{gXv+iDN?_ccqdEQ=o?Y+abG?WPNsPHf_FbI@i%In;Z%J--7qlfp`b6)S= z`+*Xv072@ySR*~42pEQpm5T)osO$u_f$6}YR&U=7z{D{yu!HUNAV`S1ny96V6BqO^ z87@yJ_&pi}LtM%e4z+ZEA%PY!8#`wS`lFT(dZ3+^1ihi4I*&SB4rXij(hC98_0rI@ z^m4ESThU8N0>wQ=?+Kh>NGQUFqn&1P)Hao%n9VXUvu+_aP#qic)+59{GvR3z<(d~_u3Fv)}lJ{ zivQMizmlN0MIzy%+}s`>9$X&$TrLP3ZeB1L%+15c&Bq72mjJoGbw)xxLC&rW|1ikI zTrClHaHO4!Gw?4)sD+CgQiA^8(to+&1Xox853#fBzXNq2GHy>OoST=6hug{NFTehl zc17yI{@0BED($NG77pXqfw{W4AuR9nVa@Ol_&#?3zoNec@2wHlMA+RY1?nj8V(I1t zb4Du5OVHon;j*%`5*6WrT8Mx}1V92j)=-eOuz(;4%+JFE;^(mz5P zczz*4AzlSx9z_{mMP6P70U2370R=t*Ua+7rpBz8G&_7sZXICWD*%J1TZo7Nk|H29> z{=ZmJIRp%fbV2C3xH$e(1zNT)NEcUI7dTK(?(eJvSq<%+tz0}@+5Sq?zr2=*A?(~? zR*DE0C*a?47Pb2?HbD8Ud3j+1LLe}YwI#@kUqA!|wFX;&U@$%*7}QdbUr5A){@-}3 z{}aD|)#?4ty&v#@%n{|YZp*x(n8j9nPGr1TE}4}`T6aJX2B$>sGjk8&PyJu}sg3wx%eCl6o>l%~i1 zVh^OojenOhjG9YcYT3&;IVoP07Buc9=D8|;rG249Z)YZGcsKl6RuBuM(o`Lw#V?^Gl*xgcmWb$#KomopyH zY?M@E`sI{;$T~@Z^8=@!g&k~e%mUZP6!}liqQbL5%VABEmMAlK@Q*hOX?f^g1SIG<|{gT^G#|q3YYvf-o4%P?u~1 zBV8Jkl54e^)fM>=tsnzEVY2!q`P`u6)qw=YR)ub6sK|^F%zN3Q}POh#^y_oEra<6wV@(ydQS7 z_Oq1vkr~7 zcwXNxPe~d;GvKQvm-6VNnt`Ee0-^Kc_iKZtrgiHf&R$#XiV+HK6Z?$ueU^bY8GWQQ zr6}Ja#Ad#3q&%+(n2@^+5j$C;Y;#O$1!V2!J%Q*zwdykbE~i7ee%MAG1L-Z?26L0x zTctU4xr~JETR&2m>AaY3JSWQo>^ZuBWR+X*@RBXsf0M(FD@hmue=G1w(l=}mdTLtU zd7bQSd)E!}NpDxceCG*d0-vsQaou{@D*211F$kPRk>UZ?5ML7z0=Zpi+Wx`Ul0wm` zg#C7Xxfa?G#&X^DC1Sw?+z*>o?F41|Qa60$4|>~=`1J*xam$s^PP9LVa?%Hd2^Vm#_SaNBEl#*Q&>!Ddtq)bC?i6R4Tgwi?V?SSJh z`H#pUPVn2l`=`qTW4VD>9g5q&_EERd^S$f{{Td$%y5ZN_8j}>i0Dnjascg|JWeE(& zo!h};z4Ue*{qn2XW>x1}dpT%GS_G;#tdtSS7AoU9mAg3;^@OQFv?Lz+V5`MXmF~c+ zUI_!07v2Q%l|=Of4-{S5O&gh$Z&+WwuPLnVtOh*QN7plfUSyqqeJafHJn0?Wgzj6% zgnCAlvQP^sh@!KmFl)6))wvS7KQ;A|RY;F1;Pvez?uLq^+~?eGaeca|RbwA7!YhGY zy)5%?)tLH;(B*n9O_K!i{Y!Xq7i)TD;OW99Z0#XlXH`7f%biVss;P(cp@UXL%NH(# zwyRGXUWWnJ_TXo^C;ad9BzooCy$b_*11iE8&e!rPNPYCq7mSG4N9{3#lATrwqiBzE zPHJ1DICjgho)Q~rNY(~3r|Zan%-YTFHx$%5Kyrgxn^4k}xvTke+lVI+6%bJ|qBSz@ zGPHB0-x7#M%li;Fu64D%b8qMqX*-E=|K3~~&)&}@;H^oe(%%YJO04Td$s5 zX)F0=fYBH5k~iiAYLUUcJ&eV%BFfblSj$DHp1h!^DswpO;vy!!M{8dw?GYv3 z3kR5tF7xf?*L)qFvS}w3`;fV#^9&WVh?vEZ`u?*@!|QnKt}f&Wa=Kq}vRC-qcrmVX z-+;UnfD*F9;X01u=+n|x9+V_}n%)8v3|@WROCO%-;J3(mZcccX?`e8e<&FKt2n^HL zXg;5QQ+IRm%IoKE#qU3To`Rs8-#{FR*a4Q52CzJQ8tnE?eSY{$O~eb&Fp_lJJG?T=dv@{NX;U7vE^q?RSr(fp=R;cjs9w^P8?>99<^+*%?(Aj~IlhcpTTIL{n6mK!fXz zuI!}QO6_lAe~}d5kR~S1 zy3Nf_phMXMMx4)4ru^>%K1*c&>LL+!7g2LvHsrEbBpFLfvca{ihe}M(igXljRu=*(nC5 zh6)9iX5@z-;x|b@Wg;mVd;RWylZfij#S$+MT_xl7f=vKQ{n2^a4dT>h!_$v6p0IB; zCom>I+jfX){2J*e`cSPWYS{1p&?0S{b*XC}QYy*v0H#Zy+agS#tUknQy<~QCqHj zN}Z8No|}aIV(+=q+c=yXX0lOB9JwTJJoBaF7R&S_CKSn7Zj#r0UesHeRe0%()Vtio z_d@BXpzp|}WsWS0^tWTM#JcnKybvj9gXJo6%ZahO6M(ZmC?s?xDCLmw$iViax9_J1 z1XE@HmQ6{YT7J>M{T&YGW>x=~fB(AljF)V^%xF3W`C;DHJjAeOAyRl<wq1Tt)37sBdgPGBln?Buxx;N_Hs3^kf3_U}68-Cu3jNK=pL|6`bIL2UmS+jgOE*xJ?gmhMSby5A>7cArRT4U>??jwWrpJiAOhen(G<@~so0 zwxcY-LnA~1OU-5}!tLvk?9FbytqGNPQw&V#>FZeCC*{=Dn{GeuA|iR~A6|BFYIc~Y zTnEEVT^ z3iwWrJIvQzh9@s9=w^4OtL^k!aT&k4Qy)}yLbNT?6ORT@zZhH~I~pkND-OS{WM`x( zXY40FIrB=&!k}e0dhz;LBk!zf@|jlf4arP=MwskvS`h6TrmT$ZpUn*UnX5u=ItF`g zlL)8riDIsP5s2B$bs;Kj?9XJU#`msiw?vN`h;d+*er3)heR)+g%VLw53D-DgZCi)a zG>C93*@oG-(Z|km)%mapj<@y)lFens(bly?=kV>d+!Q27HP}u)Kj84kBG^}o5IPWS+g8@vkcW_qeg9#mZL)m(IV}vinm4E)?~K( zZ|R&QJ=RoCeTt0$ti$6h*;<-{sRAXd=@C5k%_CuXlbyr%#(|fNrTetB{%z&}N`sIc z!|meO%S(X!x90NYSOKnk)|EgR`4|U05YHh?(14=Sy0N4- zSvic)sQ!bB0LvZ6gqp{BdvA6I;kKB?;#B8sKq@V}uDu$gD!W#n#Jh_+=7r7~*YJW= z6C#sY&x-f$J0F$p1P2-YoEQ`JdJuqD=I%>Jm7B$+dsRS#PTkc!r1!GW8yQz@t_r*< zT^oA(%Hp_sAm%ZS1cc5m=V{)^ZZp~Z%q5oC&ew67)9S=I_3hg5++5^C-6(#uypf`A z+F)FUf_!l36SI}l90XyPHW`Ka7j*2hYuJ$$J|2Peqt~#*+L~9^ijYHoh`f_4hV_vp}&s^BKg=&Tf#DXutQ0|gCYBomlIpII0rG81H68Z>2kWmF&2%HeCpG;fyum?t#~6N z?~W&{hHGh`+n9oDvm1%Z)nS(9My1XH< zRhTJkSKuL-c&u z*RXY=CdLC@-dP;%Dp0(BgJ<#rD`c*di58-V(&sbEH=x+Eh&_HYZ0wHg_IUj>LoJz4 z3yUll`&`D5q%6wpssCez3-0l`9Sy$>h!&2CYUVpqtnbeT&EC0um16i%ay00fn^djf z^uc}N5ZN54KYyu(*j{=wuo(Msu^XW-`C)lDePcZ{KG^gJg+RZA4&F;1DHGharX)fIhXA75SNb0&`Jc!nqIc~P3C>5lDkonjN%6s({7 zo^@->_0`}ZsyNAD>0ZU|M9T}N$s?Egl0U}oU9TPXut|h zs=$oE!+>+uS>ZTfr9OB`O+Zo?Wg{unvjI4_3TZLsTz+4-BbMM>;7$6jY==CDxpc$; zoMBLm+TvismHHHfNj{Bjh z2Tv!{+1R%y@fwDZy%@6sx=`ZNcEEU0L7fY20wsrvo+$6s1di`~F%H-a*V-SPQtO&>i9@N6$$*h^K>EvQ zn=?^-DnGKoAW>ip9h(}ZbbPdbOv7_9`S`fk!U)hPOBHeT(!8Z+keyq}1n{TsMOJFm zDaczkxW%WpD;K7p*70CTIjpn zg^HagD3A_o_s84U3a&|9d^&A)m{(aS9yvM%(Vt)qGQk%(mSf)&I>t6?E0ew**9WW) zz_Gvew;+7~n8T~&88ib9@oDS0zbfIZ4>0+WU&$s!W}*dQKj&fk%Dmk)wQ^|fJv+5v zzS1B~*UAk>Zy7vU0w3>k-RY@^_N*bdJX+lGFgH?vIrO*`4pD)vGBpQPm(ozF>Dr&n zVNiRsK9e%nWW{GRs0(9AU-p`(F56W$ zFF)8uxcj&gyUU?G4On$6w*$P(cd?Obh~7k;fe-K+e=_k=@HLuLu*fKjVrMwX<%j(6 z*(}jvrN9lKTcznCQE3aWJsR^WLZtC2J}TB;s%KN6HNSi-?i2i*)}Gj~vz*%|4O7w} z?gEicK4L}%h*L^t+fb8*ATgB12PLUou z!mpoHJ|p9-nN$@wYT=*RoHnjtc~O1$bm%jc^+X4|5zvi}LDc*W&udBx`fU}+djIR& zhg^W$l5H6rJpy}Nj#J|!a*cFV#z0v+TnRI`o(AV*D^?G)x^Q3GStgm!rqu!qMB9!d z$dBnHM~7>layMQ{vLqlMn`{s5{$O?XFzdM%G4DmKV0Q$gqM5Pk(gH3V+Ko159BcHf zax}WN3pA~=e?rGRuSvHx(mp@VsPTBV7yO}K#(-vF&0aXS8Ez_I{afN!nG$MTo> zMH$@#n`Y@edFux877SF*5%rTJ5-x*WC?BVQTG=F2tf8!ogJ)p%TI7#TtBRE0+;#n? z5ttOv$J)9%iOLI?5%W_l)GsDQPTR!CDe=*8B6E_TB=ti4r3u+57szm4{n%0#w`A0;V?op@&HTW_s3a% zq;BqPr}GtK(1|6D7k1F_sW)X9^Xc%Y@^Bd;UBW? zoQOF<$<-e_Mzy)hczzY$?^$7d=k#iBQyN{SU}#34uLS?t?KUoElqq?J9X z+*ebnPLtHT^>xHjopriI(=21N%pdk6lsdXQ#k=FKOtH!%@LBT4hOZ`A17;d;ws{u6 zZ1;&OiE7v$P^x%^z=q(7^7n5au*2pMS#i@f>UMDMl%8zyUN=JUOmG;`tm(y44KUnT z6jX}v1M|mt8Borl6VLgW=-$g#ctL#Tg&3^xz*gS!V~Lq$TN>S-#)1eFi7 ze*?p=Bqglh1OW4}@aQiM%VtJq(0QxsIr%4OR_R)vc?={R6^{1>sxYQx61s`t>LcHX z7qcAj*^?^=mX|_Gsw^$K(@*GB&%_x|)%#VIn@KRyU`#MM22a+yIlV`mc(s zlWxx;I|Gf_{S3F2eS-6=;4czmWUJi0uH1;{hVe8Z{6n1ggt ze2UXWxqSR-K8i@fYu`=c9Op{ynp~YyjJU&w-F9p1=vBMyZd8Fm{#d7=t7m(!UuujH zWV9vnAA1=H{gCc0ypEOo_8wKwQpCDSlpdA)dn#$EgxSH*Ko};SdWmzXrAieO+eugZ zDzb4Y_IM4fl$>kpu9^MHJ)tXwA*ejbwx+7N!}WLAWKg38HNY^oQq88%5yFx%-!~gT zjs-(4R%iMG_u~Or@3d$TU!DU94aS{I%%3^nC)jXb!V?~d^|NoYz4VQfg4S+*SlX4{ zvGS0-=qRDWJ{)&l&S$Ns@56n>p2U+`1L+u%V;%A?cO#0^1yC(kX7NKPaDOknVlLNfuhRkv5VNV7_ka4L z!&TWVU5?8VLxnnMF&fZ#lG?z4EoUy(7XGZZtyu2~B2IzE`*Dj{<(~E-eygL+W1q~D zhn#J^ZI(}Oa-_yil%o$bMQWdeVscseSpNImfn{XHPnlG^~0mxRs!FS1jQ9xdr389U6!ADk=~s z3Nea~^kRro#un^AV2Z;Y#)KuJ@7^x!r9ruw7F;MvRy4XB)Op<)3w}iwySu=j9z?l) zR9^L~y^TY8IMFr!bY>f{oxKbObWVOK|NXAgzS;lN6X$U@9U5iBdKNvZxagHasReUe zi{+a{v8w0c8twBcveXrv>~0>ID5I&OBGCw#;KQ~6hl8j~E5~9jg0bS>!WlD$Z(TW( z3U3*|hp}F@Hi^I_S3QAq<WM z`c-1wZibf5D-W@+ikU1KS`)ZT8MfFBf1a9SB%?yyCrCV0S1^LgH3P=?rwqLkl->TKyV4}nh*#M1HnDm z@bTWgcfb8(YrCrZCw00Y;IxgW7-r>MkG$umKok=j%QUmO?>64~H0;c$sKxN!UVNctQWj z@cOv8J!zw$NXh!Rfoz??UH}`g1H@ID@wlyv5dg81W;7Pj=GS&p1Uo|1{5-&hemX|B zeonUHc8szz04X1dCjb|)7YN|v;_T`v;UmrXFI4Eey}fz8g?OPJ4txUQ;^KV#f_#F4JWmolp1!VLARiuAPp1DM zD1kj~Js@sg5U4BQA4HH16y_z(_{8+TTySyI*8Xo`SI>V3>M3M=J|H(f0bYJS7ngth z`j@n)mjU?y)A(PdJ&k7U2;W;^*fP;w>h>HLP6@`RE|D&t!>gfe?wFUpjHss0n zzjej`PhAN`4=~6J>R|+hI{&8%^c}px&Mw|D@@^yjB8x zK;D7vR6L+AfPckV0`k9b014R(2!Mq}dBpkcZF%g3gvEG3_Tn}?V6dPl7-TCVBr0aZ z_-}o?{}I3cs?(>PCqLZ&Lq|f;mY*Li1bzY%28#0h1I!~176J0ufbBryAYlQZn6Nk_ z-xEc?e@f?nl+u5;p6c_T>3=uI)8fBd3+(#TPaaQ=L*T{Gg@VGEt*#_*dA;o(gN_$chhDuGE; zcUj85Mw!?shu_SY>qev=R;e3@%#Pl;{Z?y!qHhm`MKMA~jI~wD>`8DMl4fGU05hfQ2Tff2vnS7N1--lvBST(3{ zIbTWBsQA)>DMlnx*EL8NG|Qd1SV*6b*z2=#!fdfR^XZAM9ehj*&QlI%g1^*DNmx?zr!a@oq@8Hv|{UmL=wEjv>RXw$+T+m;B;# z_6@HX&V$u2Y%vb>UhTfqQtAXH(nULK$7sskjH0H4sh6E`*+3W?IkAsfGgBu9bJAKa zE<|W*-fQTf6a2WX2w+X(KZWJxLu zv!{Pz85N7bitdJZ(f5$!u(EA*pFc>tC})mqEbRP*M#HHhQ)QAl()~~li+B30p16Oc zNr-)@y}RPh)DnQ?_XI#>qB-Fd;?6WyV?o+?7kl* z4~XH^lC3C*)PlnZntN{=2V=9CgDy;UOZ+^Uu5#7pgt@g6Iuuh}G%<2uaN>C#`{}|j zTj<;aj3tN#=4?LPBOwtYFP~K$fU{jCcl28W$`z`&8979yH@EHw5GOQW*JW-7!plB} zKGv$JPAs#gTQO+V6Yd#OU)Z2*SzK&RQ~I(qDCDgQihjS6xx&&4#)ZJC4sxnMC0hgr zKd3X#5OkYyl2A7c{!75b8S&tOyzP5@L20B%u>F?3ms47Qjx96)oDw-Vb#%XOJ zrIvGvcoQfdmQMFB_?|OdlWw*FJueEEQS5@fNZ+!TC{>pN-Sb1^u*Ps+Y}(w}paw0$ z?oVDLukJt@tN11Xq%9MLE2)!Rbjjnc-ANo5Ni=MXSRi#|YHJ&PsEHrFMGM7sq_Dyq zjx*u&!tSgL>2&8P@G--Cgig2T`QYN-8wGkY$$9Fu?(Edz=jr1|M8od1a|~_nr=P^7j`FcK7<%SS!8SIz=9^8P&(!w= zH+^hzjBd!NX_}J}T^hByMb5u1U0*-89T{%*6cF|c!`IVNrSQ;KJ0RgW5=4`p!bg83 zhy=R3LJ>$0S_AE3qRGtzm2`i7tej*(;FbiRp^j7{ZjeS(8=a9*R`F$wC2?bjBkOm`U|-->uoHSu+OB1C?$4NrFI0wCp4syhqeKF{x z7UNU=IYWlk=96!=`k$}t$yppu(m1f6IhvX&zX_SWLr`sW*l5s=4WWj&nvuq+Vhp@0 z5v<1>mtjkMMLzdNA7z(Ho2}&qmqUUW)Nk4otAt3H#UwDNcL!>@Z{e58-&t@NSO!g1 z=;(fcoJ%&NpUr)u=LoLy5}Y0vBgzfw2`KN4o5s%a1KD3_K^mwFe!c&EV#4WnsIaBaD*m1G*mc_6xz*l$_1+-Q_E7UD1n$86{uBh^LwWnYtA4=SH_qVQ4dnBZ= z?yAO4nbQ8qKocxh#TzK|U8#KTNTZO4V7H;9{FVF;o%9AUo&y7p=ilHdxASZtaLi7r zds7nN=f@B(5nPleIdqn?!#2oQ$2^^SNEj4v20#57-m#{>SuI5dC66%uzBsW3&N%ud zesHWPi4G~B*aFHOAlQ|3=gKx5Q~(|4mayUV8&bv_+}(|1y%J~Ar9Z`;NZskmuWv5S zoOpH)nwWKOc;r=Ai^STIr-3Nf13BpSYlK95du{B65#=E?wW@|RKW&4!=)=~+J%<|T zQ1&lczxQ-uuJ4gU{X{)#C=G|<4Md+#L-GL^L z@B~lsng9sNK|EOGS<0%eL*|T{y_JR3ikV%VX-3H1IqI&Je!WjObmdQCSx4UABjhl!i@H4j#Is<%y0Y{-i#ZKQp8>G9@PVGoWU@8DsuDP;=2#wxsjfiR3_@88g83)Ia^R-p^|!Wk#ydKw=Wfcnk%1 zzX9X{NFSV$diVqQy~w3N?bHP7Brb_h#5|a@QV7D=K}J#@ylv5qp()nR)%=l`M5Tzh ziA=_8l<%aB$Pf5n=k_xH#@Il}CavMN?=o2rk(RYuOq@zH-I|#IZrc5@TS?YQ0iv(s zu-}N!5=(vahBGT^&l;UJK1DHg-!m?Q>IY*V)*NEIJTR<_7q+@o~%WDqk~zr^Id&ww{6FB z4Bgo^>+cUJ{jH}9jIGt$s+&^WZmsNUMK9a}#lCN<4)ACT*LPu;oOHs2Jm2ck_V&hz zzP4~!&BP5NeR+FA{0z`W+4QZhlkAoIrWA5|6DVa3{I79i&}h^lT0Dy0fV&J7-M{ZcCtxQ|(pRPRG$`C#lHUq^}w1 zmZ}(+^2Ta%(e?FyBaTb_;YZCh+2x#g2BqjxV``exrYkE0(T;ZV?27r|rILy75Bwtm zG<2NOqrryVaa0R%X|t^0e*9E7u1yV@+pIb#HnlxhSv#&#f%wr13&ZFsz(o6i-SQ*^u+tt@4MqM~8}WcSCu-92-H9TLlRqS4X5rJ5kJYIKOop@s4*?u#I_D?ng3t_X%TKGsuw6cp3 zTM+5SbvbKq8z$AR*Tv1tpD3~%0@X1K!!+w=^2XHjq%?i*!Rd`$(QD%5`M7if_4Z>A z?pm?^(a1K3xp4H@tMw&~L4ULi`pD^at{Gw%IlY~B@dOk>e~XNq!EYkC7sZccnm2&8=2ndG^w|F zk|U)rep({)bg{A$dVPgNo7mq5jDcUG)^Fj+eBnKy}a`A+DRP{V=*$>r<%r7UFcFl5DV7R}ArsMbg zEc3D^JDV2DlPdq(_U$t>O(<@2;{Gz4ujg(Qsw9^4zgrg;_VY=|s2y-ihoUy|eaUR3 zJLN>VziXZJkxx~brK;$6oV6~rm!^Z+2<$)qJ&u)z!&VQM|D*O=mn~zQYZsr0PVo0~ zFlO0oTyAu~XOntxpgD>QK>~Nl56j2mna|u4zP*ge5#(iNV-j|~g-M0?R3lJ|Q)3#w ze!b4}Be>?C-s*zpy8jaFnUz?V%AOMsTryR0tMxkJLl(VaX{fPe5b-2Up3D6Ty9bQ$ zi_TxXfI}v#Skj=*g>!BK8y#^ePLc|x!qJac;?eCwxo&^X$ju5q=>>e{KpWlRE1jMj z7M7?)eDI|=k9G_Ih3X??6L;L{_PfOZ6=%*jO9+&Asv<@XAf$Zi4P~1p^s0f#NA_#K zERmw4${QyyW*8aF&Jx=uzsM!9e(opyk}Un8HIhb&-ph_Bm<@32iPBCNeuoOT9sFUB z+9>t6e;x>0F6o{`=Pccmm^Z05y`G@Xl$WMB3sOt26RDnSC}092hkRbWwgrsm4Y#_B zz+fw;1#RD7#ftUObTz_F$jB0v&8|63 z6G_r|IP8(ByrHBb(THce^o59_Skfo`XKyc%HfrU^n|Twh8@c-j2loy+GM5B@_87%l@p(w&nuvi+(;d@i?{v09t8oj<-)uVZaH5(_8 ziAP0r@|HbuC*$!-R!^HufU`El5%hpPAsZ$TN9l24bg_L`e!9fjJLlM$)8CNQ7VqbO z{P{y;OsaYq3I+BW$JC1)1uSSB$h5ggZgo@%uVO*@ca|ZqKX&~1Z<-g`sSdwt%PgjJ zE7~Wp-g3Z=J1}z3e0Pt4@Bc1qqs)|OGul&PxiLxjNY<`EY&OX*>(c6}d@9Bs*5JB8 z=_T7|U+7j0SkdBCUM`maT5!MLFR^kE1Qzm@xaBXsOruHC@em`7cpgeHaP-Nfx9OP0 zct!bH{=y{;Qt|$ErxdHUJQ58~+9k(^5MEblDBjez(Rr2oUG0{t{TdDTt{{v+=`|3E zsA(h&-44PcAnd5~wN+CuU6oh03iY1-0*hOzbfO;k)VzqF`|y|&6gxOsVsb4_jj+@v zJvE46A71jG`pwRzzfyUqOGRYKBVm{jg+lalRhIXK@|5R^T_+9)fGww+gN8?r7#IXS z7+1Ozbn8ESTUCCl(ruB|9P^jVYiD##uP7SNlo0!NoXi^sY~7YTB1y?1~=6i?NO8M9k-KkqeNGY9yi2dsW2ilPVk8 z$vmH^tH3XC7La=4V5Zdz>Klu&imsE$K%8ZY1`q3so9V^Bm^xF^ZMHr;$ zakrQGCw|kE6xa=irLu}j3*ZJ3zLL+0{@VZX7%kMv-!T~FUN*MtQK{@gp z%O+&Q)w#YdO}NORUqe|Qn3yZrdOvh4PATbXSWU{9GbBht30hW-GYBJuKLrG}G3639 z)%zaT$4#YVHKWVn1~Y`|NTQ?sMSEo*R{qz$eAa7eDdv;*Y{ZX3fsOfhDXu)Oh%(vW z1c5wliLZ{5Ztz%LsVXC;XH5*2b(PowX@2b}pC*^C92@pu<=s~OMjXPr2;y$#NqM0e zcOa2B<(YqC7tkWSE!CP<)hjM)TJ!@cHMecNPcA;^Q}VPVx0gW2oNar182O+BjFk;j zhZ#v`DNV!l4@i80>)yY(Qklcv@+8V=})n zxesm_*0D7jF(6b2snniulSSmf$ov*(e%eY$Uy=eg-`z{22Hi!SuC-NOyIX{9E`C>K z$0@>kSY7vXfekPo3Z7X_^6@<1z>G9CR>d@rbRMj6eFaBjKVk+{^5g`Qp!lWOOvs|i z`FCeX&`fgo2>EXU^QAQnE+L`4r7)~;ILQ#&Y4l@nUX;L)NDI(HOS2M-`l>?wQF2EV z=*`Qt7@-AdDhKn|C_Eaki~GF13gXwvTDw(CR|fQcNQpMvHo*;!(mL4|zjzc_z9CpU z$HIY@a?Y~rOwdU7#kP2o$+EHz#PzX9%j#l}+Rbwhp-S~uXj_O;{*K&-kpF5+#__#j zw2~|z5yhgf3X{iomcG>TO~Z=np3bcE)$858hZFaQ9p-r<1KqyB@9# zN5u}MfBhZtlNZLiR8a?||Fsfv@d?HKGF4CHhCDVNj#}*|E%BA&c)L8ilX-;2fS3}l zqK{rVOhoq8O>`JifgDCPcGvIBQ1YTwGsMgSS=2i1dRIdFhYnJTtJ+n%*Xk{=(uOm{ z*1H3XKn#!~9g$}t)m-zRP9iM+DhwoCObxzdNi7Q~+WRXfz%iR-x4E%<*xwQ}zIyHO{B(kPDzuRsL!%WNbjTAZZV8AlYi*Z|&Ms+`> zMr;|sJ9Ym30D3}e7pg)!dym>EjOkI_Rz_P|7z zglIr(h%Ou+Kkp)e z*4|dPdhVa(9(2j+2E(Br6|IhZs|C-e^p(!G@o{62wXjLn2!Jan0X8)Vwt=cetC%VySdB%{&O^X6~=) z4-%iij%if9Joqu`<{cFAN?LS;$5AN0E~$u5xA-FU%W;3likfbna#Uw+0Z(WyaEgbU z4N14{$u^C|4#lwEl)g4V!$5lLkva5|7DQazs-$B8B85vgY&qBEqbXp9Wvn}Xi}OmC z&)mx1ytaa-e1uK4H-~KNT$oA4n-5cIn#3{{)4V^$nm6v5`k%LXKz`M{Q~xF5hT^j5hwBTd zzd3*UQC^omxrEQe&qxHyEm)tjD z-GVb2*7hz3>)VPfB`_lR=o zN<$W>7sd!2-!7|R?HE(|i6O-mimSHZk2DTuk z%Sf(a;Ns#-E+O4FrdfyGdy}Tv7unYaFiZMW187RQ_(}H+uh7$37aG8X#h!tDiLpD-F4~dw%LqlBao@PI_9N4RU(3Ei+}qv1%?hbYN5NNGkRKDB{@$0f!AYgo z=npmMQ6Hu@wgRb54beo?PO_OEAS#e1yt`5jGg>?=-DA3=L%KyAYZT;lUHU8u0m7ig zEO50dyusBBA0rs|pMSL~xCa21H8k=wlo!9vLL%A>AxR_? z{K2$iejUGhfN4coc++?e9MT{3vWMZRpT;S<>GI~Li+-z97p3~>ic-;GhJUYDX< zY~#V8m6-R|e|lEVnXimeou8$f834}aeKf;&n=%_sX{)3q8)?gBvGVpr(pzKTH-qU% zy9YiPIP@X|+L9r`MU^Z z_qAyTE(%HN#b*~0;-`Zn==z$ODy!;&<||Ri1WM0S>YgygdKIav?C`xi`pe7xJfd}L zcJ*$RkJiA~T4FEC1>nBs8oUjns(gC_f}>vx29_kwglq@;h(+ogzxFP^JnEV1n608w zM?=s0LfS=;AtQ_P2KtNv)~Vcw?j|OhNs9lL4j<)JZ?;E=l7Ng%rEL3o*V@uryO`cg z*zTy1iXdw_&#AtTSmWsO!t>bx>Z~9P%RK&0?#r0Bub$rhZ^LMuxnB2`xkT*0vilIG zW`?b@9K%80%v)+PQA7asvp3U?qvPw6y|LlLFa6~}iB&N!jvn--+i||MQx|#x}G~v zQieuqZRtVBQ^pAt0+j<`YLm(HB>RCyvz2i(3OYQs$AqDj&_ctXROZo&?lNuUG^dHm z-w5R%uv+%~@EsphbFS0U)o4|vJL2!%s`0>k*7Cgmm_d^imq}C>)uHxHhQY;UQvw4H z#Pl^5Jq8wQ>K!7mHC4BJd)|sO zHKMb{9e>-*Nv=qdCaf>y3cB>k_wVWIO*{Mz9MBN?i_nO&=2bj9hSI+2mu-D~O_Ym` z_MS0@=1WDDsDcE_LTm#;3Nc+V?#wPnh@?2ZVEJ&AD306?4+aEugXk!h7i`vY|$hxCimvtL`Flv^ae`e~+ylGpMG zwfy!%Mv1nfm{Cm9J!Y5rTW$ll3=xLdj9+T6=(UJk7SG&AK55?g-x9IGCU`BQkbLG` z14~Ok1y>?wJ}AavDJ^$U$$>Y=I6uFonEqwX^pWuW?k~(R+GvuB zHq%&-XHvNEq}1FCPPC-N518-_9lTH`j$Bin#O&8we<9MV7;BbA1P`>ItrTmAdMmZr zA4O|qAOh8B@~Or)u_e<{+bOios`@dejXYwVfrW%8Zp2}PRn*-e)-6ab3eltz!7C9) zQ_OgqQ4c&UQlO(O@?&7P=)X1-~qLsQFRoH~64HmQ&_pfNwoB!JGWoiI7 zh@uWFy_r!a$Fi?p(a=~HH5IUTYaDB`p6mn1s3iazR8^Re?a=_R>F?f+`b}|(t7?UM zwnF&k^vVN8Xq5Ne9Xu6s51Larc$0l|qO>vi#c}=XADR7w6^^8t?lm&vltIoU(C7lw z^h)5=UR4Ga;5#bGJbyGVQV-KX_zY3`K^Un3Xmhg}t6l;ReDyS{ww&7Aoh5r^*BT#v z0n}ej;_u`$jt;EYIRdvtmY$Wt#!oi#??AC>M6G{m4^UdPw@^XTN> zW>VTVwG%bD)RolMD!ffxxs&|fqIlO68_;G*F*ABEzgWZ#&et|fdkFouw=$&ZBJ8sB zZB9C(>yPa#V!OT8t=4Ll0vSA_wMHMyyHAbQT+AO|;X_8Di(VOCTO^4rx)6@Ix( z?I6ME9t~lrvks;2`*zBywVtg`JUHgo&q%4`Us`t>o!7&V)q$s0bB~00;{jEKGT0`SHw)oANb}k!B@5p!>Qf$?Oz3@C`q(H2hGzh+3If1h96yfln^-JP%}_pvZVf7e``3Zv)6GO`V|RXCt~ z!!ypzW6PgwF1&N!m2;DYP*wsrBsiSjQbQhTv}_eA>OGIMrVAXFiQktkDmf07Ffj%B z<5!sS$)A@a>G$xvf<$zAV+|{`T7<^@_eG4UI(_8$P}hyq++;%czxY|r9AD~kqDLK{ zCK7io;9>sd8hGokg?0A2dk5I!O$DgBmL(WOXbD@u+s^-Xd74Pd*OM(uCglyS_#P-- qP1v%*z3C-WI?jK}4?g1Xqh!^hCQX6w@&5TUOkG(=saC-{^#1{tX>q~; diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/showcase/public/images/banner-img-3.png b/modules/distribution/src/repository/jaggeryapps/iot/units/showcase/public/images/banner-img-3.png deleted file mode 100644 index ce6d43d3b5a604e8df6ecfa24d4c90d5861a076a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17519 zcmZ5nWmH>D*KN_@!Civ86?cNWySo>6Yaw`WC{o5({z?Zkrw~&>yaxWhKQa@JQdJTE5GVDtchpUg2@`{-!3p_2esg`B%;UP+Q#O$ zv1CebimH}(qeR|frtwoR}BIT zsm71vh^L(YUi80PR`g)Ns7{QHN~9Q$szVR3#8K=CJq~-2^9RPF)^Q2M3mZ70c&cWp z4<({+ix^YeY{+4V>v|7j#tvKP-vIpgwhkug8@^?70@}#oXbb&l{UoCQF1T5w#oXr| z=hv(x|5q3pGRE@p4^vmL^u>Ns*pLDSw3w*B{F4Q%ma8WSZtSpnt3KAkZiw^LONK~F z`>4PqQW*7|e-zeiXdndev10yxoxGZQv<4_N5UTZ;lYDT->2$GZuQcPVB?)LnP+C! zOpQc=?J4|1mXh{3z6$2`x=;A?_$y0NKe;+_rJUj#d=hI^roR#jmDkxoZHwC8tlDLj zMNd_#8&e`cD*%&G;p_#B(7yP)o(hBCu2%#9yo57M&AiZ`?!T<##(X45eN11uUj3rb z$g22Pf8i-y)0%Yop%K=pl?wxti>o+0`-$pY7=^5UME=JK$B7JQWGFaoUn>uh;cafOUG?ZwEhESHV4#eSQxse_48& zl(oiqjv6GN{v2luTa!LA3YYRuuyLHaf&Rjwb7tQOX_^jFb8@o)Aynps&cUh}q}_!o z;|!vnn54_|Jlk0J#ULlU%dyJeMmo)Np{Fu~n41cL2Z#kKV8Df1vW(yFa!-D_ zSmmykV`29}KzWpt$xRM9F<*58^Vx4A3h(}Mw7Jt)9Oo{Tc8$GY-D2a2WVvtnzr{Bi zom?t=w0H7EL-!eKd~#zyCEGz=)3s9amk9xb*lTGYsY|S>Qpt#VMUnmMN2gBJB<1Z} zq4O>o{YFUW)_?6o0G3}FdB`%TV&PzjZnT%0tMeiPFcFx-5$4)Ys+1`Jk3V5e2K^Jt z41wQ}BMYh^o6^$wZ*$-h>Cz-b;u^S(MUt|r?#Ym8BJHc_4S!tLOViLp0C5wf@rF4F zutxH*L_a0KcJavR-zo#1_AgT2wix9&6vgtvXY~X_cr?mP76d7SI{_$jIU`!lLPi@u z7otr0f?vOPIu%DMshoc!`ft^0*(>Wpf$W_wgQO1b@45n2X`9{-iY5Bkx7!p{O^M(smxBy_{wuuTSA3JUned3Gkvih?gyYNCm4ajU z>HI4NIs#wVo^ttGvTrh&D}I}h zM?R=iKk=TpbBgMyCc>QOg6c?C;l}G$O4XGdanCU2FCslRW#OivjLX2kn7w~Z{|4)F z>Z+{pau>I^T%@tF?!>`rYkzkIq|r6T9h0ogisGe-S!Am9V2UMDlDB%torc8$7IR7)XRPw<0lY6Q0n8APn#qw+H;cOxD zFr0dlwyY12{!d~7eRs6M?hnVCL5c5QdF?1+U7S2eK(U1QyB~5NM>-DKWms!Ov#NzV zl_sp0G$Oi}2Xm^L-^)8?{7Xm*S% zT1hn~@)Hk!ad|)5&`;Ub*+KthYUg9c=Jt{t^Wsx$3odmrv{w#qJiNFihU1F;x7c#o z6{fDj5AdIvyud&Cut73Z$?5qkAreMViRkOiF8x$I+m%hOgNQ*d^waz#c8rbzj5kjNjXz9$zs5%_N=iUhpJyxeB!DfEP& zlc<^$)M~L^T7T(NL8EM36uh_sJkPMJzdG%h(f#KJrwH|wClWaI49diC70|Bw8U^vc zYSyJUqO8Jv)ufyL*}}^|l92z5Rr@G8;+Vg}J7A&E>n*JBk?w@)J2hEuPQUSCI|qGR z%omS#ZxRyM9OxtSzvs1+X1=e88YA;Jr}VM?x6W5FkoNy{bgQC7?ftKOpYUASw}wip z^sAxp|4KAa*%(EW+^_r>07N1(k(!GWd;|Vhcj{mm?U&)So(mCj&1eChQOh*ldDpM>tK!Z84ud7S=@0SgQyztvawN2Fib=vhfj+#iE93a#} zGu}Q)>hfbeT9prj=QD*rmx1J9X2`%_2o?Cqg&iz#O0O7Y^( zQ>~24NIBRiWH**a#-b=$>+-EG@7CNwT_!HYO7sFd%{92RmpFbTF{TmH|2HmPb{n

    qhZTA+HR+<9BaqDAxleuaT4V67S;o}ecMS2$+!v5c()w-6+YWDU)o<6g z;)~@&Fu0qfG*ghf6O^OD_{V7?gQL8xtSs})tiyxOWxYG=_H3hmZL9G!crzhP_4W1S z5K1Lo%hYsXt35taEi#YnGfqe76u)ca>VlQot;?2I|K%vtL}pX%fIrZ*n}czEk6%Fk zS>WriQysB4`%t;^l03eom(TIg_}jy@?H0E+`QN*z;@T~`sJr+T4d@)3H0n*QtzlBy z7(!8W$*ZG(-s1;ZgC+eOkCtaipYc)qW~T`GbbzFX^&k_1#0?i!nif+3=XnPgm-r*U z$iY0(z-E~@VmEcA4ECG!w6yynm-OHK(INxVY~al77>ks57X0nxEFy2uS9PLTK6u5- z0F72eCi*#E#1g5?0k#9vx-aZiKhC?0G|oDQ0*p%C1gj)U(EB8fUw{Q)z7YIrc1WcM zF2g0DJ$*t1jP5Y8vE9_`Hx6(_piFu90L!SjpeTS*5Nif%5#$IKlSsRWfG!_`{&4$W zTAy6}sx_+Y=*S8P986|R94+oK)z&Vl4X;j+pekVFLa2;i6-IQA^1@fe1_e>-fW5kb zRIJN*1^N=Sl)={;E}uEq{P%L5Ae^<>qn{{^RG1$#iRkqjQi(Pd1st2gmX1pQ{4qpD z3Sap3s|*DQL7rY(T5^ilm6MBVoqD`Es;sMHzwB*l;;yQwD9Fwxami(*j*cAE(Q6*S z_up-75s-mM!=JqzsD)Mq=c~dET+c{hISkOQrlRLVdC|AYxT@lBs3FK; zZ36>hf6R}7Ex2k_NyDB1Uf6J>w<2zNv+myy@)fz{4HVWWM;uiFZI$L*jfPtngLxw3 zH3s}!aSE5rLf4)KDPK8jUnH{L6^cYN5r7oe1J8QeOv$z#eH78R(Ye6kcppTNB|mq? zAk~#%XUB~c$;1_PP``*RSdWn}W}-lV$?B-BCYE0+?WC{=GIYA^rYR^_A%{`!xXhD` z2nvFw{~k7eD6!J0lgk-GKGK`Svjz*>9*cf5*B8Kha#X`NpXdF+}G4Z_ZC!DRe|7IY=4r}*2}L^ z=aeH)7w3-`NmRd6Z-yV?LIV@!Xe(IWui?|; z9GCJI7@^P=A5I$q1da-24-?}edn4@&MC^O=A+EEYG)QAXeoSS{y}oemmY8P_Rag>z z#aU~z;Wv5lApH3#TaH047lE)I+C5@BBQ*F@`-9+RX#5XXUW*?bE?OrQbM^){Y@m zV!r&nvPQml=>Fu?*E^?D*Ee>rl)0xtvx{b}Pj8Qxw+-4pl5?L%YkfyfD*fcf^?UQ5e@tCqP--RMAS*CH zd~N9kUg&jIgCuYwv7+D{$w$_q_c5lgXu3S&APrdf2AD$D%W~voT?I<)W7bRN0DA|W zP@-w-ZdYQYd~}&o_LO+3!Xf*oU1zqSShy5^w~)VN%ODwueSG&=p|&aDPkjB`XlpyT z#N-pDUk?2Z<>G0+p95QjDutz8+6{qP^hCG+RdWaxAO&?CWQ}|W|MwFfkd;mquxD`0 zf0+fKt$U8^$cjF4OjlxFK+|AG&FCZs@J`J~Vvu^wfyM{MzEW#n`pr7XHL-kROZ~;%uE4B zq|7cN^Z{0MBl2$+tuw$M~I@a=X z&icD@c(ok1)!F9a1^!E9o>+Zo6B5{?s(#FwOr!a=0A@|twDn9)RZmV%bcYz_H#?lK zK|Qaq15vy(IypdVOv3pbQ2hd(?u%~L50=#~nRda9@^0~D2%c<;1LOvrC~ z2ylrS#N`pbM{2K(`0Ih(%$>992WG?I&4P7I$h3HNq)Z!QhS zMXOX_%sQ{Tm!j!+r}SxrX*p@V5E1$%+f~dSkzc@W67liz$y~DUjw+;)fVJG=?|Fq< z4P!NvjB^aLi_Yp1NJm|mHLWx|;D*%P1o3$!Hm#dzKW?`jjC~Ol^j`IG zlXbBM6|3S4>+t>qdT7mqse;PYR3*aT5l}Y;uL&!;fkr!RH1^6>wIR!8a$@u zwFp5m&u1j@kBCmuifU?!U)n$YSOXGS&w$+fi9)o-(TNbM!GV7DKYG74h%3Vt#D3o# zj9M~h#ZD#Bekkbd>@=KA9NHA})d<@3n%}Dz?*3|fhjERc_b{Pl$B<9;ADv97W3#+U{N&gQ;#?gAp z?pRLp5iDXBe=G8r$vVL7aOQz`Qsq{k!a&^^L)}&|S)LMBQ;;Sip^i7@#>4R_Qp8c6 zKx_UNiul|)@y#kn60RS)7D8Ro$#mGCJ`5lPJnkR@upbjS698FW?O31Z`s!@`U?XDn9|;Z;b;ad~)67fYjpo7`~gt!m%O#XAIO~*Aei-mUZGS&zRX>S2uN{ls?3E z2%w5M!UTzSj6y+L#{GOLc~wD5D9u17ExM16WeL{ua6#l71xgn+2b7_!=sN7G%X&No z^?}mDc&JEFYySq>wdirfxtKI$Rob?tLoQ!Dzbth3%-(s{rcR8|hvXWSOX7sWRYVeO z2?us{lX6pf1d=^QB>ltSN5F25{);mz{5Bc6QmD0MI#MATd^!As zFYRmZ1tpMQfd6K&ewHf#Jg1mGDnng~O5iW1dx`C3q>x~jYytwu4GHU?o~uszK9|Hz>FLL@#WOX4XLRWB6mD?|0+ZzV9;3VA*dRT%HXVtWxX_}Y zJLnq>$rMdf5amFjGXjgy1}>9yq)9KYAv2W=w!SO`@C zV81O9$;Bq)lwhtc>QsHtccwESvY$Z5DROkznw^{5l6(>Lkv8y@V}joRwK}ZU0ZWTg zQc|ehyJTZ=!A@+J4yqEFx)UomtkTf=VfhFkr+aetgS&u%06>OneagER2Nz@v;3>rU zPLn8-@{77+4|-H?w3qkmw6DAV)4CW@DADRrGU%c=Y1dnvzfY~}tsMU0x;*i+Wv?#R z-*6>z;Lt7{pG6l);w&m4CokaEw9oVzY_CRUW#Hi8kR_n1{2CQEBnwjfEb#T>htX>v z*OxKR->;8MBDmJn#4Pt8crNp)1^H>~@~YJlskA^HWk-pQMF^7mPfv~ROMTuSDe?0? z|6F!rv56I~^;NrwSmW`Kkr|@17?9+jx@z`1 z&@^oOxCYd~iRaMl3}%)6HMH-U|3sD>c-o<17JA$`st?V~!7b7Sf%BYge~1PQyQ?r# z!MTadsu#VlsYCnRAHcCr#y+2@zN*y~8TO3k5A2)``+UC;Rd+8?%|y&c^A^4A_$ z4ChcK{pi!4AahbT`Qo#O4tiB!$=8pa<1I0iLgf&oMvoCFaSQDI!vOfZ3=T7j8*g_p z6AoFLd%FR7&}H1$+bD{FvDA~a6T1ycVt0k%4{BfQ!iV7Lq#aFOthPHHgy7;Pql6!up!fRs z`ro4@7$Jl?j_nNF)@lBkAX*(7<`d7 zV*Ptx$jmCsDs4!aYyx52O7Ka90%8;yXNuKkLjv^t))G}jtvcCLsNdlbYHuW={@fIm zcb0h5;z{bQ&1Knin~}3dux!?DCd3`4&*#ZPl(=CzXxp`&;g1yKR<=jUfK<*uE;tI%Kz6RPJeZ}U)W723t#0|V zwyem0t&2N3kknn92t>30IgpxdzWJ@;yUQjo{_9uKKp%bR?MKR{eDR=g`(Ka-;7Jy? zkAgUUb*%{w=JLrgN`2e&+)4BC7O6&v+>!7A+x__|l8!L@tRPB=d!=LX7Q z15cf#5=M8262=l5<-KyZ<$G1srSvPU>&pYNhkzbqO09N}Ai)?vPjI0vAeMG%$ek`-3zBn&0__#ExfN*n;zGn{?Nk+8qYzN45ojOTFYzUQkZxPBu zx!BSrU$!O}94$!o-ENZVh>ob(J9aF2Ci~mg|E!aq@m~C9IYr)fo-Q^r(}|6yGDRc$ zbw@H~P_NIhrl;027T^K42aKZtiYs>z=r{qT#Pdz@M~A6oTRL_`z*>!LzyPsi66ZQV z%ZBRWZ@ri|&04pW$>d#qCMo7hKUaF5T(iW~MP}%De6p;8_%8rR$ojVh6q5|6m#{5t zI}+%++73&!(UEEL^7kt<=O)VuWtUl?Cg)Kf)HyP}XyFC!_L9mV*43_4Y2Ij>7olLc z>evV*&_Cp~MtcVgZSf0?2doL*Lsgj|2W~R2qJg*fIdl65gVu@cq7(|UevdsGTuTwv zvkZc?a1bRIw1KkN$f5tB`c8(^jcZ4$Mj%H5>G_OFjR1qvn#FV^mF zzDR`_qQZXX^6Q9SzvMM8%Z?BLjgs#dO=s`*j@IJwu&ta|>WT{IO}wI~88y%% z_B5)}2TJW1YQvd#d2QjcsH<|kZi4kQN@QSYnz$J?Co1*VlB&?i=ep)3?et$>{PH*A1p5z?FDWMpU`|!fTa+@ttTQCQvLXSa>fd%WGaGzeM=7J^W+u zgYDy=C5jnYdo!P9o0#a7(ZfBugM@%mDv&f%MpSR1sdG zka5tjpNH(wkzs18N=+4jru=!=`zH?J_33yG1em8ar5JJVrFW&>a9{5*nUPPfof|kt zsni|m-N61m@aN+`=P5voyFh%ncG+uI;xbZzLB?ZCmVQ*BEV@umC_OX&G>u7X|M_aV z{M(d}l94u}B@CO}x$xUx^WDIo5XJ*EYlMdOEl%sEo|Gbj;F!O{HLEcqa#WEd{$%)~9d3Tt3i~i1Y|TDl|JOQ#Sh-g)T0}Y;2fuiLDL3OjXzS{z)Dd zN|t{oXJwN|!|RHTL-_i-=q_a{_k*7~yc$Om$N=RZu+sTST3|Uy_-6#movT8#R^ZzU zzgO9nFJ1~=*d+w8OK7U_K)69v2eU zg|^0v8EI+KRZNWP?(g>gC`0fv3)E1ObCD_R-~g>anv%e!24PDs#UcFRb#uwy`&5iq zPt~tJd@dWkCSA-}NWuqOaU5lpTIF+ky_%9=`CZHOO#LHFgD&{J9AEf${RHSx@B%^7tIjWWGXBaGS;dn!VjH{}hcU6HH<6 zJ_lbuy+jkwm#NfVFHhGsWiR|KUa(yv{}qQf-8QLGM|Z;kyQpZJ3xy%M2gX&R5nTXtwUciE?>rvJV6d+^(uMCg)dKcPBuDqosRpAw>^P(b9a4jqE$6D3psPGE-U*Bm0A}$hRm#@ zs?SL{$NPiWmRjsmem&NvWj%BHvhuOo9aD5VhWGDFzEUqpTQwm|%f~Z-?XeD4ZDB}| zx(Kk!sLRKta&1T+Rik>1n!@3GqK^)lYhev{o<>cXPw{4=0rtDimZSQ}H!z&!uq=@a6aTp`+(Xw^S8Kj-gXvt#aA_RBa4L!4Joi|KtNz%W&K&RLnzMu z{b)wC`0=12^&q~UvBJjF`dv+QvKoVI$V0e6)*#$&s-D~abd@b}1M*m1*Ir)Wz4Xxg z;B3o_0_h|mt*}aqdUp7U{756StosSmqi+$0si@~aC|@0;xVTxD=-sNP%F@#SVQ&H3 z+kK*0X|Y_Q;WCGHZKZx){@WCG)ea>K# z+aLGd)#%!&tA2`O%Qll}p8wnI8QIw5_FqcG>Fz~ZxGm_xLoUw>y}XeIM(U_@3IA}o zzd!TiWim%lD-c?Opl$p~9n=!|e2-#COa;IjD(~#f?(DjAvW(b?L>qzZ-V?p`w`6*Aq!Krf3$SNGc5itI;i=vaxwu&HP$+MM$Z~u(*;-_$6|H(T5 z*5R-I+M-CBx$fC}t7GhK<$%QeqVUm2`}Kv3AZ{4Dg&dDTJ8EX-bgipp2ZAMbFY)}q zzK|ye4&$$|>~r&K_juq{y@&-*xtBrg*kZ z2|v;<&)+r)4J-hN=M{?F1kUlcskIK6R>&Yz2|PlO$m~o^Or)Wn4yrW#7mJ~9slXDk z$K4FEeg+!&spzek+3m#8C`CnG`@~r}9*4P-iY(7}xu1Ui{JDkd9;VBQuYjq*(@9(Z z>b{|NkcB+P^!GQ{SnJeI%lElbrC^_0OpNznsh0sX4tom`t73GJ4(8TOp_Cy=)0@?e z$PXjF`y!apHa3YcZ}iCVZ{>x^ep|gX+!0YV?a-e@dkO1vG065L_tD?92F%#H5nLKF ztW~_noT6Z{1nhh}GQF~?i1qZUJ+2L+*LotdpWCxIdv!KfG*Ymq)Q|*VE<4l-jjmE)x6XYY-Wz;gXi$?iGv##^Ng zpx)knC^eBxbn~qqkF=Punoa>(vZJz2cqP~vNDgVELa^_iZJ@4+y4&Phw{xDH9oypN ztt`kQ+VmFSZV6s3f~Pz>oVXoYNwlw!T%WBflPciEMA^bYTil3z=?`4ktA1IC!@eD7 zWcI^6TT%9A2an|k)5Wtq zWff0-T?ALYho#MyyKnzE8Fo+#kOvD=S}$M-T0A^>!FFwJfD|0=Fe-#kI zg2e$Yl?~bJ4;6PK9<+_EiLw+J;?h*fFPu^+M{b`6;qmeD!y))ZF)uN?N9;y!a`E@y^lt0@kVEnVvqY0JFnxZ;b;Y~yBwj7nvbLMG@-#L z^Ne)`!K&Fh+NA=6rJ1FW;(RGVW&jR}evibEQlvWOJF5WbcRJcm$^*E~4+iXZV@?8M z(Hcc4%!j{Ev_W7YBe}TQqK@&5UtP}1;=9wG9>1TG#7}Va;xsS}SUWtg_qo`5jLv*y zp<{6*trBaUwD#sM3ctyD0e6OUbz(iLS@vojs4RM~ZW2Hm9(xbk(2{yaiVKn**iZwe zZrnyOHpOv&)-skuf|bkiN0p<$(Mb*Vkr0(Dwf!jf_( zqK|;%Xw+J!Mrj{H5)X9Ec>XsmvM@yvb&NJ0!U_adl9*#Tp2p~3SmEl#ntfI}#-GNd zkIuAKRD805?d-zFIb%Sl?-!d7KejBD(DwkHr-dM^x(eF02n4_Vj=bl<0|YvW_}r6s9Pu&z6w z$GAl)Dj)>X0d*fcwdGYy6^h>{?)jyqa#jm`deI10k2#LYl0PId(s~~`Gwi_&WX>V| zASorT#J%kLC^-r{1eT&D6TD{pqmPNz;LHP3#k|k*l1m^f{OZ~(cqwu?ZQ|Dd;I;0* zH~WPRKH`xR8E3$2lQXaM`qZN-Nx6Th1m}gqr}D?Am+!CN7Yk;Wy5Q4MqLyGFj2~9h z3KT;G>|Iq9j<1JM`29A14}N9Xu4)fw4a=%H(G7$!Do~$%7#_RS7NM!|4pWf>?{^-_ zU+!}ubc^u?Z?};zLQ+B;Lh!8%{o)Q{8)}0uIIM{&L?OMCyZIqc|E7p z^0Zv{FE?Z7X-jo5E@{Po?`OHg{8X9v>qX+ik}tF7GhUdsdXickA;*`{om^d{9wbI% z-vovCTR~16h4w?S+=5%CI`28r>W3ZQ#pC152#~U%><@~{wiWap>ZvmPy1nSk%A{+e zw5@nw$qa%Ub@4g2&$-BPr>xO7pAiPV1pLlhL`7#V6~)cUxUU(d3^neO;SFV&SyqUL8zP`=m{hkj-w80SeRU@Uc%mlPU=vm@ z`mBm?{+gM3sEM8RPVBR0`n);u_7d4z67C+yQ7m}Whpz=CAt6EXE`8Uxp*Ai47Nk35 zKg7Ad!jh{fm3@b8(VxyL?a+>cqIS}aW09?Vhs_D~Xaq+GFa;2^(5o=Yl`yPr@6OT5 zDklBaXP&1bsG|0zdvl&+mVX}<)h=WsX~`YKJPg^$hY?bTZ6o`yw*!FGKW+Oos_2)h zQ!y*Quwp{vX~0Ljd@c|0Jv%9JJ?+6qwI}^VM|d$y!bRPLT|@{eNE)yKYMeZpU3~SJk4zcU{Ha$dxC9FCYhy11 z(t~=&&W%eA_Ekm7A4i!XW7giShRadf9x%|rr=lZ}h+e0_Omj(XXt5&;8k21F*}TB4 zTKR^O*cjVB^{6tWs7U`sXwE`1bD}BOttpw&pvhVR9!W~b>B{Vt;%6rgQWMEJavjjOa5vvjcHPNgmhcb0CWdNS<}Y;-y=T{;To^PhW?}TE;lDQCW)W%e8LE#}N>%TMo-n1D9k%NEQI_VJx?>eN@NTDY)Nf5^Ub#y`{y+AkjNI&r-v@4&u|sNvjD zIGcC~&>^^pEZYi3-ipgWnl44~)u#Wp5*At0R#2yg5;|n~5@}6|<57|Pr$@GTqcyiv z{v%KcMOuM}Gn=unag!E#1Q3D?m;hl%4j6bE|ILg+i8@HZEoRRxxJCtOoQ~;_@mAp0 zlN^N2lxtU_{gj;4RVrlm8bC=R_N{n6!Hrjm(Eq{7jCmz#iS|tgU zsBa3kmyrlZ9d3aj3h6>&oc^4{aAh3d*%(CIaUnbE8t*|y{ua91^!(N>j(2LU$3^~H z48I*W8r94?KE4mO8J1X6&}k7SSg!cotagxg_pN~VhM+Y7M3zPkvln_T={GiEwy$q%giwjBbai)Inf^C&-# zFkN3xa5$y*yzI+~qni5frn`kx@H#Pn3g23A4=lE=S&UJSM_=aV8&m*E5zx?YdwF@y z=;)d3mbz)m@#27Xl=5I1;~LXOOPOUDPwQTK8J(8i{ELA>a*q85ZP|sl7FVfJBSL zldSUNkh4(*C*o-wiPssN)Xa2ZWN4_L#Et&rmer&akJ$ZBEnb1`L6}FA_!#SFi_L)u zgIs)X0rROMzbgWFI4Q?f^`29%S82AU#%(w7Ey}?uzj_*RSaJ*dyh8V4tv}wBk>e68KU~Isogx$3Ngp7# z34&&R9g;V2sC@D)kCofnr`a`HJ(TiSNrb zW_=VOJ~p`TAL*^a5J1c{zPEDQmZb&&jb9;3AF*kSTNWl*z7IdQxz|z^f+}1c9A^LN z{upk^t@7e@-x?AEfzzL>%~!*Ws(h+h@O`A&Wp#ZSS=rcJ*4y2!RDVjK@k5w@J1x~= z6gdi^!SprOu9%m4hXIn{{87bOf%=;2>LVHWcqnIE7y^O-NO`Fd#$H_rHkyQ2A=Z0s zGw~o>r&&Eu5R@;5OTG}uJ*hOqB``10RB z+n=ITgXrPBYkwgGY=+V>7fzV)4H6Lz6ADd5H}bp5jg?$aW_>9Ccz3!6SkygU?U)Y_ zs~+q21Q)?0;CXNCWP+~aYxB9RkRn;EZFocm8;A@>mEdF0GMN_Dn*54`*uR^(s(xxz zdVCBYD?0{6fI}X-&Mk_>g{LYZz3kCgI9#?rv+>jV){u6?%GB~HEV*D}remx}R7cP6 zH(W6=+ZN1Og$aR4|AzaUSZzuBOc@=;DGqQ5&y)9m}}O)I`A(2;9-Ps zxxT%P%z?YrIcZCsYBR~z=<(t{C{heT8az*D!_62^Ww`47S3p!+6gq|);v*0Ji899G z#gUIXa)S5UIrPWear7h^&PWu`%JZRqX;UCNhE9?|@Y+uV@3%N1F>>hFMy)Ri2D}l< zpN>1hO?qE)<@hAx2kDV73>+s4Coa3lwOnWRxHo3oK{44WiNsA}L9 z4nm?-DT-bbTeV(~SsvsLaj2xr!nGojAcsdsD#$)9t*wy|2@LAiW=5AZ8E0|ZW- z&U|2CZCY=C&$2vVoS=^M`iC{)OM#yH)e(Qo$}29i6oW7yBtgX6Y5%+r&*APQ5*NAW z&u7PPk$B+w`FY&ClBbu~u|PL*ir-~f(HcI?AMWQFr5zQ71h-R^*x7NE5{+YvYP2}M z06!LYpJvpz#nI&sj9Ctq=s>GNFC6#pLtpA=l1H4R%3I&SxOA)xrUryUx5tDnPqM0~ zPaiAZys+YurHHoB|C$O33)3*P!nl5(3WqJcPQTD`nA;1RnwliT;4L)S0cXQ}crg0r zEXipZdemM3HS^H{;6sf>V zLqApcyo~mfbZ&sueh3=3@3*2T)cD5EoO$a&68OqtKUCqL>^(&mk~KxPq8Lp10(n&P z)_84~`E&Gu8#nCXvM?>Weo^LkhMj#LWAjW`k_FPc1RGPofE(-XH>05yz??(ZFtoX- z-E;jLN}1)4W%h}C_J21 z4jvtlP3TNdMJu#@=q%jyEqrS8#&YlkMhZV{E=kF)3&61ajuVtxai;7z&F`Rowtikv zj$P-}CQad*S%-MDlaBv>F@~B4Ownjrf&-ix+iDaWvc+Qx4h!$);-lxP*lScJE1b}d zX0HPtNX5?*L}NqrZW<4sW*DEwiL)?$`7SnM6f%fFpWjd;PPQ+xOcO z&CaA^<(HSnJi#P)dF=j`;dOa;WW^qA!eL(oaieIhBrGz25Qkv)bsGeta}8`;ow%Z7 z=ksIc&D_QeGpbnP4faSsCSC{2?c2cs9}>G==-&byHW2HEOZSRua(cno{vJ z=6uE>uzK`qMk2!mf2IX+t3^y9I87!XTZX+1h*g)M-Q=JSZ}QR!0gZczB*z*sWu~jH z+F46VDG6q#Lh0ynElVPHAoi+V8kD3wyTDUOo3Et_%v-?fPsw*`@csZfp>t z1|3e#(8Nz;;D88nr$~7#hOCh ze14o%ymF@3VQvn;N>zXa+7pd>h&J0BDP$-;7ZjEcD3$O{513z&G=>MfS2CMpHN3A_ z3>h&j5kh+I-1g@(d?H@`_vDzcY4QI&o%i;kkO$q47FwMJ$r@=p-m_4WqXk!5x!U_1 zspCot6k}29m$SJk=cw=pg-PWBkSfc{B4JX7W@YZ#b4^dr53nuifGcw4eBQlI9fXl(+nY1l^SP4>`Hx7k9G86p zDf}{R#ncswr}NK#UpXOjInt!+iz6UOB+USe3wfO?SXfwS;y;jB@~kS>{Hh@qsX;t4 z4^B<{IQ+{w7lF)5d6-};W_zI4P|s`~Fp7~JA+QG!m?7Az{E&&xWw}ZXl9tly>hsyu z4tVpUTw7^0!=(|)6XCuAC>snd8Csg%x)u+DkN_EnA%Vo%OAoaMu zEPUW~*EciU)3e!p-Wb=s(kQbuw|W*5C#y_!wtwXm6iaQOiz`gKe<;^@!v-lc=`A^!Uv?U#3AQs z%E(0ch|Bt^HfnaFyfmM}WPny0(5n1^_}+z%2-V(iO1LEo{AO}Ac2fnfG;#+!U0wV7 zPhY*dX;{%$M*a5_J*Ufs|EU&@Bhu{qa`e^p)Z5=0{NKK;&itHl`OMFf$6v!Q>`ZpQ z{@?fi1ACO?wSUeJZyU?+b*)^i9(eH0YS284X8pCPw~}pj+)g$h z+h}+C_l8ME)_*J1C4Ut@U=Yj;K6if2B?}qBUk3_S|C)GVKbv58^S!SNnR83oj!sXM z(RYjg-=F)X-fnAv@Oval zKCX}B+A%NVuSb>_k7!kov8mg#Soy;{f_mO%*7QE}oonzQqEALJ z>58mz=7a6*eVIxkycSv=;xg9?GOMfYb0cb}ntd1QzWCuo;Ip9By$Z)fPkczP(l{r= zf6S`n7?0I#d7xolJ#YMO-@XePj680oygO0GdQ#_7v+m>3a~mILKbAAj*V@g2T@f8{y zJ+9j&+;;po)A-DXfabH6@t50UA9qS{2m8O&{+PtBXe6h9D0Af;e@>?>2hMUFR%w^c z+HJY=d`64!ckfPD;E-9~wwVGi`^`o5+;)14DYYfa9OjUIAH6=jD2of;+&RX9hpPn8Ybb6o$Z?*m`SB7zn>zN7RS}^xXH@Y@<_UE z;V-kpOL+J$ZaM@;)fLvWNz7cK=sEHqnT{KE+}k>{UpJBq}54MO*ZL@ z-?@3SmN<7@Oj`bCO*ETJWofU;VS}EzE^BA`tXjL{=*1;nOw(o9y9I!P&61#_ASBvO zn#FAINR&`Jx@5=xm78|&-hJ-v^PaiDZMZzNN0HC}a~m+^2zo?nE^S^9JVAuP)78&q Iol`;+0G@z{cK`qY diff --git a/modules/distribution/src/repository/jaggeryapps/iot/units/showcase/public/images/beagleBone.png b/modules/distribution/src/repository/jaggeryapps/iot/units/showcase/public/images/beagleBone.png deleted file mode 100644 index 8bb45023fe81f46240cbd2531b4995a95ba42006..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10433 zcmaKSWmFu^wl?l=!5PTl?(PG@oj`yPYzPpTA-KD{dvJogyL*rz!7aGE+sAwEIrqCi z?z+8JcS&!ny?0f2Kh>dXDjzV>NYP+mU@+z7KpJnQ{M)IIg7kJ3w<%J3D@YtDuGpGp|Aa7&*6|4a^Hgo+x3>JZbfe*0M(sj^PRuVFW+OQe_L&N4`WBbMp z10y2tVry*r4eS6g0e`iGh|-+4cG3VW%|vN*c$GPnZKc5$mU3=(U`;m_EmOB|rh;ZP z;$i?17oj%+Hed&1fQyYa#9qinl;&S@h2HA_bhFa{{zc;OO_b)pjM7zB14u*dzyMx0 zK2}o>P96ZiAR8wyAHN_!3xMmb&CVgf&c(sXAt=PlEyTeE`1e8crp?aGTu1{X`)^%u zEm0Z^2M1drc6MiHXEtYUHmKcKc1}S-L3R!SM+Z@wH%tF(2sXCL%Kt4GV*hVPy}69t#n_gelZ}Jj#^#@K{fpY( zK?D5%&G=ub?X_HO!R#7fd#IzG>03O^-~WgC&3FH|qJIeAtPxVRvwRDRu{8*4>SzOo zILL!UY2NOznOT|%32+#j2nY)Bu<~%28?&18^YF3?a&vI7a&wsT@ECJ(8FQMO{zuOL z#?Q?sz`@DOEh8(*Da*+z!y_rh#UsPT!zswi&n3;x&G#Q(d5FD(F~k)7AKjL3y8q1! z`agMvr0u}Q4p2KSDAf8tS)gVCb%5GiKy3li(*KG&fI-I+Vg_}#XZ$Bj|21k5*v`@k zY$j_5wE_Ig&q9{}iw(xy=A4{h9zIq<4s%mhGj1LMR%3HP6IL*oiw|sU%KK)c3C+Lx z&Hjh~{wq)4dfvui`yX?JxJ)@Xz}(x{io|KKmV!z_r!Q>{P)xXL*C|--P^?Jmbc=EfdNj-gCwJfQ}Xh5Tk|-!cc+j@Ih`C{9rT`Lmd+vi=`eL>%uU|AG&VWZBpHp(;I9&ktu3a zyO7<{L1|)QV)QG8ljGYT7BvQfcK?|ye>TG$ErmKv);xBrL+Iu_S>arACOS6umXuW+ zF&sB-*KG<$*lw$NVEKT4Zf@G#`VW%n1lI|*v9J84VpNYF++U6xk8juxyV z;Lh+17a(e5PGe^jrxFMzC8N(ZJtXo;6=_qY_hWtH)Af~2cMbw z(<4jS`Va`*nc6pXSvdJE*~>2;5iygmUWjvm_hnHiYfu!hy-=vFcmt5pjLpKx!e z_U>!-N9BnC5}0zfO{f!gys(P#le+_ZzDTSYpu@$I-|gvf;XMPqd_Wf)*dK_VH>n(l zO$Q@dbpY#G4~^##GYlD;>g6%qpM;4C?CytIr(S)Ie8|fQxk&sdJ_rMWdrd3JFfCTu ztEhbn3?fxT);s2Mq~H0Qj?6{=V5*4x34jR?fO9dCgfk16DS$q|EU7M2uEN*>Is<>S zu*CocBIrhIdV{e&DOmnM!gUhb>s@L_UUzVPZJV+QUmiXQdbAf(YRABPWQeX{1&_kF zHWOYnydauzLjqyp>HT`G_B_`1FE~Qmyq(CE$PN^~)S8d!l$Sr)Qv2P$YOKh)snvrH z`5|7NC2cO}e&=Y!{4-Pu7e*570Z2>mAA`wM5{TFRZFncG?0VX{d%8@W^FXe_VeACb zHp5~T6|6p2`x6qIkIvcZ&M?VyNC@(Y{Rct9KS5IagZJ;hJdKv{^OZe1;4bn8v*XF! zOz5;s<^geGM3rIPSPewSlMngDyzjay`k8l-d&@U_C7I&0)pvY;|3wI2K{RMf;*@?~ z?>q_dYp2%(+*&gafke^Sf=7{~mk|2}v!o?ln1E4j=(FQ?`<@wm2y0Q{XY)40YEI^- zPtoF^JLk=7rQ<6|NYfp3#^`=v(N3a%9nTEh{o(>^=yEP&E?lV?cje|8jVxE7F@H6y zk&ZTGp_RpQR>BJU61@-LRTr+bEGPHCjAuSgv8O*!N*p%-$W<>?G5nzEzNu6=Uz2vRNri5T_Wx` zgHbpVVT*r}lPU4{Y?65Cmzv9&X$Ub7q6WP<*5jOLl+~_@)2P2V4J;`v;yMWcN;lfyTG+h!z++r_wdpTNhY>hW*^vH@4&>fJy54_O7b(rFyvGVQI(8C zf>W;avq=kzkM?u`amBIub~&>a!R3PGG0}XL#r;@z&)xlwj*eN#$jHg_$2X(a*r_OS zFNfy=PbWj!{4pVD&s8>$pBdHh=x{%_w$9;me2kn4+Qn%T58h=s_scGtg%^owcNg{?HE*u_myZ9zRmKJ zt9_T6K3Tid@gnlq@r-+(;&?LOpG^@J_mer&o(+=ies$0_u}aGFij%)%yt81&=y6Q= z<^W_?S^BG=t5+R_+FXnpBfy_cQy6&~&uZJtYFgkx(m4(R{Y4+iuUH@?RAYrCQabY@ zNkD>6#|t^nX8}}Sb&?p)W0LvTet08}z3hAq>@}MO3>vZAHHg2{=>osa)(~!`B@b!2 zA=Ia`^My1BlWbrna;EHyWLRY6u`HNpo>iF!zI=KRw{G#qvM2q=*(sK%o{Pm{T7{OgI z!@?_31gQ&w*y7m&?f!=!vor%?wqW4$AKC z?neGdIzc8C=LwO0chxVCBR(Rh(Y4cl{YypL>W7-aDnjGRgD?jv#-1bFkH)fb41BJq zbEJDU{WfHzNKX`yhIfccI=ZC#K8`RKvPLam&+oiuBa7MY7#GAXLLU1l@-eFPq$Ibh zn%oS*R5Dq*&lRP#ARj}M-SIE)NHN{OvL-A78J^re2tP3w?4(@u$#qVXQ&W+>8-QD$~_R{ef3S{37ZR|=y9gXE|KPbX~c zi9iYk6-P?DoshO4`{Obt;-Qn(M(+3kMzbEH&wf!@s=NYGW$cEdkc|Rc=*RPGBWb<>G^q0=6welX5*iI2Sfa&6QcZ}prFwgW!cld zP<(uLEgf2M0d&lU5Nz|-!!#AyCpuV3u`geJ)tv}|ABNW#+;ej}7RKS$CA?vU5X8_$ zMSc+YB1>U-c{V3D-GT0=vtAHJli7o9mKq{gIy@hB%Ri=T8W^-$jwCQ3>|4?P z?x#d|n1O&pD(0pBeV@1h!3b1?Mh>~<4QCB(I>*&0n$pwV`)k{Ri}04!;nYG}7*b;I zl!)HFkN9P5v`lx2j;L(r_5~iABJM5bakmkCwroEUiGq&q?m3#oDn2taqeMTpR|@)! zh=*4*PC`kEB{xpve6lERI)g(2P_|C8AVm>erssDP!(!nY3T}g%vQ;6c*+z*^ZxxpL|B+# zObkw!+^bh|GpCEfM;z0^lS8?+nEXe^I}{|ld@KAod6h!rU5Bv&Y6+}x%7q&PIa1eK zM>4~ykOIZzo+t|81eY&RkBedYwcJJ8I|Z)F8hLuv%%h$v!EW*At4sK;mQ7?i50iP( zX&4wrrPN75JR&{6RZi$dO6pVK1-tZKWaP zaoC%jENgk2zZ(Kiirq=EiQ|n?wE@LDdy!PWNrCeGv@EVK`TFVkA2oTSc5IXTJg!Lnxt5)Rg#0(_iHpie6uw9o0 z4sYMz-;+%ubw+GWZ{f=+fYa$E2S}ZH*k659a9|@ykAg8CA7EMt&RVEhvE*s(@~5}y zh~rC48bV;r_@yO4q!CSE!nnZ~Sd@Kq7K5gke%p9@)u3cUH&iu0fRIoc?)b&UMT+yP z>u$8Rw)TE#XsBXbeEc`}dU@iZ7w_lmZ7~waNVgFJt9Y8TwP8RIdR|ab>h3-^qm^cJ1J6-WH&c;im0$M}h;YlV z*E}GlP7sIS#{!hk;`U_aY>a=cYb23*VLZ5D90WibHfH4OIg3%279$*mI8xdJk8;AGzL3=C&mTC z)uUVIHBaQk#6+Vm;@FwfyYo#SV@2mU`U_NG0?_s4T(dFozSTtf& z8NO%>ji5f?u<(xqy$|kpkB_~`R30#vmX@Mkkp3{jDvRGVH9ELrzFMC>sgr6#n3`ck z_$6j1V||CWf_@Uc3qdqMk=Xn^X9gd&9gs8iO%L&TNU<$gPvnwdHLTp~^{OmTNC zeeiF~yDuKN4nh>PZLrnV>xIwsLJqn6Xc`_bkEQHw5J8kjs8p_JEBt#C zrSBO_3j{(?%wf@Qh_Gg37B1FeI=j3y^?5%0@@hh9d$QatlqK=kghM8_d3vQ2CbpW6 zesXdPl&4HG#CM%rqt%{@9Q4zQXy!(TVQK}yco4!Mgmj*-UHY-QbJohSSoOfXUKhiR zouRV#m>y{u&Rt<|-@vG$t{)22?y`*Db&;w{OUo|kAn+QMgjsPvZCBIOl-AIuA}9A4 zr;ow=yBStaETm;=^Ml`|9p?88uka_z;xS*>7(?6n!x^QV1k`g{`k92IN9C@Z7V_fx zjAr|s>};QQKKq?tHt#<~mEEA`M?_q~mzk)4Glx95<%i}6wwb;!(XCw_o1y_~XnDuW z6{(!UmXBj~TT!1O;uQ%y<7DtnW5NfUG`G9o)*wxRM=66_7WI&Pv??sx8JQ0+ySgNT zRRLp}qK{Ql1rVkZu9_K?Xm^__=|OdlQX2=U@QtZk91A>7G6=L$(@*$Kqs->&_3UU;?PL0~362s_{Y(&6=iY! z@LwbfJAl*lakirw?LIfGm&nI4+A}Y)693`e89DwYBftk=qztVJ8GSgf?ocsUDbIO= zI*l)`>gu?PCE8kA5|);X@TI15=R!YahmDQfFk}%%0dhU2z6}V{m96m!RePcz1W>=01d&!)53rSMA@&m@_gs;?+0tx$P*r8UQjA(AvvwKhw9Lt|rL zbUXpd0Pnb_ke!H9JV&Rx>#ztVPJ@aLN*2uyhK6S*O_X?I> z%F@qSG#KIHtgfVh1vD69Ir~g|2~M}L00gM)hiD9;50fxpAISjj?8RW zeVU%0N-BMR{^tDx9=x3JvNhy$SHk&4P6A_0iaV;PY1|bmH1+|z;wN|GBP^8Qh!?XTCB5l8PkFFlnPBg%vb6B_vUr(7(-Y@+pQM>JDJ?J_zy>Cy@Dz|H^q!cNr zbI9OkCU+|9zF?u%%zeL`g++aB`b{sshCh*VV#dT&TUb;m6Rjkl@~1)BcKn82zV2ZC zZ`~o;Wlf@S1<+QwnWUcUDnB!=gI}d+aa*noxrIWciERuzpq2L!DtkfYqAA&gD}6kI zvX>9R^53al8E&XDAwGG0GAp9tL~UFicV|h4w8eQ>xoQkFzhQzJ>go~#gMuJ#Td`}q zi3IN^Rv)IL?$dAoV6COj^~^B{?xmWQ@r>=->%JpJEXQj5#9ZxEik=pUHTgbNi}{{| zSs170x0o6f|60>9Q>0sM$QY@Z34sR5?H01Xzi%z}bf&?;UTO3k^Y(RCh8>E*t1Ub9 z@%P~s6psH52BsQAc%An1n*m`IC1aj{CDDO3>{;wF*VQ)(qQw?Jb25?gC{R84v%IV% zYm4L-j;($@L*;p;&bwInK{kT8TDo+$0t@|jS*r8sQAC^Ry(SYgd&E6$rCXcQuZ@CD zGED6pi!mvm#|2mNjlI5}T5EnC%$K%FNVj;PX zaA74?Ce;`OB`{SB$3}dq-PusY&-iY`K~@%!vcM9(c4ljdJI=O_=_0;0YziR<rL%h|L6vxCNHMf0ZB&5RwQf%L(9e`*3~q|3OH2M6jIj@7X}gE zit4Vq;IY*ljjwW~gJpkZiF;$yR$-9~bm4uX@@#WLr8@FE>dsM;y3(;_Y@J0I>9UX; z$v_#&*2OUnIF$&kCP`OwJNh+w*^j1Xl}pXQgiax$U!TN8qGd_@BHc~ThM}34R^uVy zwfFfW7T%dFK-w}==ginT4FOKQG8W$MVq)Ji?EomxEOipwBK{>gFRYQHu{ z8oc3dlA&GH5*#Zf@Tk>&d|J4_bqmP28D8HNW({(Qh$#CC_+r$PJP$bl`Fn&1F| znGCVNzaVcgVq{TyPNl85)M0WB#fdO2mdUNNsVPOUaJ5CLX(dKJcUy=n0D&NKOVU4t zD558Rq=@Z9`>KndZFql~Qb0wVaj-KZGv;@!?6)M@naET~DlVh~e~m0Gd2